来自《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

Redis 练习(一)的更多相关文章

  1. 使用redis构建可靠分布式锁

    关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...

  2. Ignite性能测试以及对redis的对比

    测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像.测试方法很简单主要是下面几点: 不作参数优化,默认 ...

  3. mac osx 安装redis扩展

    1 php -v查看php版本 2 brew search php|grep redis 搜索对应的redis   ps:如果没有brew 就根据http://brew.sh安装 3 brew ins ...

  4. Redis/HBase/Tair比较

    KV系统对比表 对比维度 Redis Redis Cluster Medis Hbase Tair 访问模式    支持Value大小 理论上不超过1GB(建议不超过1MB) 理论上可配置(默认配置1 ...

  5. Redis数据库

    Redis是k-v型数据库的典范,设计思想及数据结构实现都值得学习. 1.数据类型 value支持五种数据类型:1.字符串(strings)2.字符串列表(lists)3.字符串集合(sets)4.有 ...

  6. redis 学习笔记(2)

    redis-cluster 简介 redis-cluster是一个分布式.容错的redis实现,redis-cluster通过将各个单独的redis实例通过特定的协议连接到一起实现了分布式.集群化的目 ...

  7. redis 学习笔记(1)

    redis持久化 snapshot数据快照(rdb) 这是一种定时将redis内存中的数据写入磁盘文件的一种方案,这样保留这一时刻redis中的数据镜像,用于意外回滚.redis的snapshot的格 ...

  8. python+uwsgi导致redis无法长链接引起性能下降问题记录

    今天在部署python代码到预生产环境时,web站老是出现redis链接未初始化,无法连接到服务的提示,比对了一下开发环境与测试环境代码,完全一致,然后就是查看各种日志,排查了半天也没有查明是什么原因 ...

  9. nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...

  10. windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...

随机推荐

  1. C#.Net全栈工程师之路-学习路径

    C#.Net全栈工程师之路-学习路径 按架构分: C/S架构: B/S架构: Mobile移动开发: 按技术点分: C#编程基础以及OOP面向对象编程: 数据库基础以及高级应用(MYSQL+MSSQL ...

  2. 有了这套微信小程序x5调试,调试一些简单的开发者工具调试不了的功能不成问题!!!!

    1.首先我们需要打开微信 TBS 调试 地址是:http://debugx5.qq.com 2.然后打开手机 打开开发者模式,打开 USB 调试 3.然后 在谷歌浏览器地址栏输入 chrome://i ...

  3. MySQL 整体架构一览

    MySQL 在整体架构上分为 Server 层和存储引擎层.其中 Server 层,包括连接器.查询缓存.分析器.优化器.执行器等,存储过程.触发器.视图和内置函数都在这层实现.数据引擎层负责数据的存 ...

  4. 一起了解 .Net Foundation 项目 No.19

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. Salesforce To ...

  5. winform不能循环引用,使用接口传值到界面

    public partial class frmMain : Form, IFormManager { 4 public frmMain() { InitializeComponent(); 8 } ...

  6. oracle --游标详解(转)

    转自:http://blog.csdn.net/liyong199012/article/details/8948952 游标的概念:     游标是SQL的一个内存工作区,由系统或用户以变量的形式定 ...

  7. JVM 常用参数一览表(转)

    参数 默认值或限制 说明 参数 默认值 功能 -XX:-AllowUserSignalHandlers 限于Linux和Solaris,默认不启用 允许为java进程安装信号处理器,信号处理参见类:s ...

  8. tf.slice()函数详解(极详细)

    目录 1.官方注释 2.参数解释 3.例子 参考 @(tf.slice()函数详解 ) tf.slice()是TensorFlow库中分割张量的一个函数,其定义为def slice(input_, b ...

  9. 图解I/O模型

      本文带你鸟瞰I/O模型全貌,希望可以让你对I/O模型有一个直观的认识 什么是I/O?I/O的过程?同步阻塞 I/O同步非阻塞 I/OI/O多路复用异步I/O 什么是I/O?   I/O就是计算机内 ...

  10. jenkins-gitlab-harbor-ceph基于Kubernetes的CI/CD运用(三)

    从最基础镜像到业务容器 构建 [为gitlab项目部署做铺垫] 业务镜像设计规划 目录结构 # pwd /data/k8s/app/myapp # tree . . ├── dockerfile │  ...