来自《Redis 实战》第一章

对于 Redis 数据结构类型及使用不太清楚的可以参考 此链接

需求:

  1. 网站需要根据文章的发布时间和文章获得的投票数量计算出一个评分,然后按照这个评分来决定如何排序和展示文章。
  2. 得分的计算方式为:将文章得到的支持票数乘以一个常量(假设为432),然后加上文章的发布时间(定为从1970年1月1日到现在经过的秒数),得出的结果就是文章的评分。
  3. 同时需要提供既能按照发布时间来展示文章,又能根据评分来展示文章的功能。
  4. 如果文章发布超过一周,则不提供投票功能。

Redis 中结构设计:

文章信息
value 结构 HASH
key article:<文章id>   例:article:100408 (使用冒号来区分名字的不同部分,100408为文章ID)
value 保存的键值对包含 标题、链接、发布者、发布时间、得票数 信息
文章发布时间信息
value 结构 ZSET
key time:
value

成员为 article:<文章id>   分值为 1997年1月1日到现在的秒数

例:article:100408 (成员) - 1332065474.47 (分值)

文章评分信息
value 结构 ZSET
key score:
value

成员为 article:<文章id>   分值为 文章评分

例:article:100408 (成员) - 13320656524.47 (分值)

投票记录信息
value 结构 SET
key voted:<文章id> 例:voted:100408
value user:<用户id> 例:user:234487

Python 实现的代码

import time

ONE_WEEK_IN_SECONDS = 7 * 24 * 60 * 60
VOTE_SCORE = 432
ARTICLES_PER_PAGE = 25 '''
用户对文章进行投票(目前没有考虑事务问题)
用户尝试投票时,使用 ZSCORE 命令检查记录文章发布时间的有序集合,判断文章的发布时间是否未超过一周,
如果仍可投票,使用 SADD 命令,尝试将用户添加到 记录文章已投票用户名单的集合里面,
如果成功,说明此用户是第一次为这个文章投票,此时使用 ZINCRBY 命令为文章添加 432 的评分数,
并使用 HINCRBY 命令对散列记录的文章投票数量进行更新
'''
def article_vote(conn, user, article):
# 计算投票的截止时间
cutoff = time.time() - ONE_WEEK_IN_SECONDS
if conn.zscore('time:', article) < cutoff:
# 超过投票截止时间则直接返回
return
# 获取文章 ID 部分
article_id = article.partition(':')[-1]
# 尝试将投票用户添加到文章已投票用户集合中
if conn.sadd('voted:' + article_id, user):
# 为文章添加评分
conn.zincrby('score:', article, VOTE_SCORE)
# 更新文章的得票数(+1)
conn.hincrby(article, 'votes', 1) '''
发布文章
通过对一个计数器执行 INCR 命令来生成文章id,
接着使用 SADD 将文章发布者的id 添加到记录文章已投票用户名单的
集合里面(这个集合需要使用 EXPIRE 命令设置为一周的过期时间,因为只有一周内的文章可以投票),
之后使用 HMSET 命令来存储文章的相关信息,并执行两个 ZADD 命令,
将文章的初始评分和发布时间分别添加到两个相应的有序集合里面
'''
def post_article(conn, user, title, link):
# 通过自增方式生成文章 ID
article_id = str(conn.incr('article:'))
# 生成并添加对文章投票的用户信息,同时设置过期时间
voted = 'voted:' + article_id
conn.sadd(voted, user)
conn.expire(voted, ONE_WEEK_IN_SECONDS)
# 存储文章信息
now = time.time()
article = 'article:' + article_id
conn.hmset(article, {
'title': title,
'link': link,
'poster': user,
'time': now,
'votes': 1,
})
# 保存文章发布时间及评分信息
conn.zadd('score:', article, now + VOTE_SCORE)
conn.zadd('time:', article, now)
return article_id '''
获取指定排序后的文章信息
使用 ZREVRANGE 取出多个文章id, 再对每个文章id 执行一次 HGETALL 来取出文章的详细信息
'''
def get_articles(conn, page, order='score:'):
start = (page - 1) * ARTICLES_PER_PAGE
end = start + ARTICLES_PER_PAGE - 1
# 逆序(从大到小)获取数据
ids = conn.zrevrange(order, start, end)
articles = []
for id in ids:
article_data = conn.hgetall(id)
article_data['id'] = id
articles.append(article_data)
return articles

最新文章

  1. 解决Unable to create new native thread
  2. 模拟discuz发帖的类实现
  3. Ext.store.load callback
  4. Android 实现图片画画板
  5. 使用hessian开发WebService,轻量级,更简单、快捷
  6. 有关struts2中用到 js 总结
  7. Android gradle问题解决: This app has been built with an incorrect configuration. Please configure your build for VectorDrawableCompat
  8. EXCEL中讲 10分10秒转换成610秒
  9. 《Java编程那点事儿》读书笔记(三)——static,this,抽象类,接口和包
  10. POJ 2886Who Gets the Most Candies?(线段树)
  11. CentOS 6.5下安装MySql 5.7
  12. (转+原)python中的浅拷贝和深拷贝
  13. LPC1768串口使用
  14. 【教程】webstorm的破解以及汉化
  15. VMware Workstation 12 Player之安装林耐斯-Linux Deepin -系统
  16. Arrays和Collections 对于sort的不同实现原理
  17. SQL Server 一列或多列重复数据的查询,删除(转载)
  18. 测试CentOS-7-x86_64-Minimal-1708.iso这种光盘安装效果
  19. C_运算符_逻辑表达式
  20. Qt动态库静态库的创建、使用、多级库依赖、动态库改成静态库等详细说明

热门文章

  1. django中ORM中锁和事务
  2. 解决mongo单文档超过16M
  3. JS实现滚动区域触底事件
  4. LSTM + linear-CRF序列标注笔记
  5. 记一次nor flash固件烧录速度优化
  6. Vulnhub靶场 DC-2 WP
  7. Jenkinsfile里定义对象和函数,获取git提交人, 发送钉钉通知
  8. [深入学习C#] 匿名函数、委托和Lambda表达式
  9. JMM内存模型、CPU缓存一致性原则(MESI)、指令重排、as-if-serial、happen-before原则
  10. hdu1429 胜利大逃亡(续)???天天逃亡???