来自《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. 树莓派3b+ 交叉编译 及升级 kernel

    安装 gcc pkg 等工具sudo apt-get install build-essential git 官方介绍 https://www.raspberrypi.org/documentatio ...

  2. ALSA 声卡 驱动 linux 4.1.36 中变化

    linux 4.1.36 中变化 1ret = request_irq(IRQ_DMA2, s3c2440_dma2_irq, IRQF_DISABLED, "myalsa for play ...

  3. 使用pyecharts绘制词云图-淘宝商品评论展示

    一.什么是词云图? 词云图是一种用来展现高频关键词的可视化表达,通过文字.色彩.图形的搭配,产生有冲击力地视觉效果,而且能够传达有价值的信息. 制作词云图的网站有很多,简单方便,适合小批量操作. BI ...

  4. TLS/SSL 梳理

    数据加密通篇都是为了防止第三方的劫持伪造,保证连接安全, 毫无遮掩的明文传输只有民风淳朴的时候才是安全的. 先是一些基础的内容: 对称加密 最开始为了对数据进行加密,使用的是对称加密算法,即双方协商好 ...

  5. ESLint {} 内部强制有空格 .eslintrc.js 配置文件 'object-curly-spacing': ["error", "always"],

    module.exports = { root: true, 'extends': [ 'plugin:vue/essential', '@vue/standard' ], rules: { 'obj ...

  6. gulp常用的插件

    参考地址: http://www.cnblogs.com/1wen/p/5421212.html https://my.oschina.net/wolfx/blog/673905 http://www ...

  7. 【Weiss】【第03章】练习3.20:中缀表达式转后缀表达式

    [练习3.20] a.编写一个程序将中缀表达式转换为后缀表达式,该中缀表达式含括号及四则运算. b.把幂操作符添加到你的指令系统中去. c.编写一个程序将后缀表达式转化为中缀表达式. Answer: ...

  8. [AFO·游记]我的C++451天游击战

    写在前面 05/10/19 今天心情很糟糕,没学新东西,复习没复习,作业没写完,下午要网课,明天要月考,脑子里就像是被一团棉花塞住了.静静的思考了半个小时,把自己手头上的事情排了个序,所以决定先把游记 ...

  9. WSGI标准、MVC和MTC框架

    WSGI服务: wsgiref模块其实就是将整个请求信息给封装了起来,就不需要你自己处理了,假如它将所有请求信息封装成了一个叫做request的对象,那么你直接request.path就能获取到用户这 ...

  10. volatile 手摸手带你解析

    前言 volatile 是 Java 里的一个重要的指令,它是由 Java 虚拟机里提供的一个轻量级的同步机制.一个共享变量声明为 volatile 后,特别是在多线程操作时,正确使用 volatil ...