最近在学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
}
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)
}
}