最近在學redis,本人菜鳥.代碼是過程式的,沒考慮最佳化.就是發篇文章記錄一下.感覺redis還是很強大的.
規則
- 評分 = 支援票數*(86400/200)+時間戳記, 文章獲得為200票就可以在首頁展示一天,隨著時間的流逝,當分數小於目前時間戳的時候,就從首頁撤下.
- 使用hash記錄文章的標題,連結,作者,文章發布時間,文章得到的投票數量.
- 使用兩個有序集合來有序的儲存文章:第一個有序集合的成員為文章ID,分值為文章的發布時間;第二個有序集合的成員同樣為文章ID,分值為文章的評分.通過這兩個有序集合,網站既可以根據文章發布的時間來展示文章,也可以根據文章評分的高低來展示文章.
- 為了防止使用者對同一篇文章進行多次投票,網站需要為每篇文章記錄一個已投票使用者名稱單,為此,程式將為每篇文章建立一個集合,並使用這個集合來記錄所有投票使用者的ID.
- 為了節約記憶體,一篇文章發布滿一周后將不能再對它進行投票,文章的評分將被固定下來,而記錄文章已投票的使用者名稱單的集合也會被刪除.
發布文章
//建立文章func CreateArticle(conn redis.Conn, title, content, link string, userId int) (err error) { articleId, err := redis.Int(conn.Do("incr", "articleid:")) //產生文章ID if nil != err { return } now := time.Now().Unix() _, err = conn.Do( //將文章詳情存入redis中 "hmset", "article:"+strconv.Itoa(articleId), "title", title, "content", content, "link", link, "votes", 1, "author", userId, "time", now, ) if nil != err { return } _, err = conn.Do("sadd", "voted:"+strconv.Itoa(articleId), userId) //將已投票使用者存入集合中 if nil != err { return } exTime := time.Now().Unix() + 7*86400 _, err = conn.Do("expireAt", "voted:"+strconv.Itoa(articleId), exTime) //記錄到期時間為一周 if nil != err { return } _, err = conn.Do("zadd", "score:", now+VOTE, articleId) //記錄文章分值 if nil != err { return } return nil}
對文章進行投票
//對文章進行投票func VoteArticle(conn redis.Conn, articleId, userId int) (err error) { cutoff := time.Now().Unix() - 7*86400 reply, err := redis.Int64(conn.Do("hget", "article:"+strconv.Itoa(articleId), "time")) if nil != err { return } if reply < cutoff { //驗證投票是否截止 fmt.Println("投票已截止") return } bool, err := redis.Bool(conn.Do("sismember", "voted:"+strconv.Itoa(articleId), userId)) //檢查是否已投過票 if nil != err { return } if bool { fmt.Println("你已投過票") return } _, err = conn.Do("sadd", "voted:"+strconv.Itoa(articleId), userId) //將投票人ID加入集合中 if nil != err { return } _, err = conn.Do("hincrby", "article:"+strconv.Itoa(articleId), "votes", 1) //文章得票 +1 if nil != err { return } _, err = conn.Do("zincrby", "score:", VOTE, articleId) //增加文章得分 if nil != err { return } fmt.Println(11) return nil}
按分數高低擷取文章
//設定分頁const ( ARTICLES_PER_PAGE = 2)//擷取文章func GetArticles(conn redis.Conn, page int) (ids []int, err error) { start := (page - 1) * ARTICLES_PER_PAGE end := start + ARTICLES_PER_PAGE - 1 ids, err = redis.Ints(conn.Do("zrevrange", "score:", start, end)) //擷取文章排名,分數由高到低 if nil != err { return } return ids, nil}
main
const ( VOTE = 86400 / 200 //分值)func main() { conn, err := redis.Dial("tcp", ":6379") if nil != err { fmt.Println(err) os.Exit(1) } //建立文章 err = CreateArticle(conn, "第一篇", "內容1", "www.baidu.com", 1) if nil != err { fmt.Println(err) } //對文章進行投票 err = VoteArticle(conn, 1, 2) if nil != err { fmt.Println(err) } //擷取分數最高的文章,並進行分頁 ids, err := GetArticles(conn, 1) if nil !=err { fmt.Println(err) } fmt.Println(ids)}