涉及到的key:

1. article_time, 记录文章的发布时间,zset结构

2. article_score, 记录文章的得分, zset结构

  得分 = 发布时间 + 投票用户数 X 432

3. voted_article_id, 记录文章的投票用户集合,文章的发布者默认为文章的投票用户,set结构

4. article_article_id, 用来描述文章,hash结构

5. group_groupname, 群组groupname下的文章集合,set结构

6. score_groupname, 群组groupname下的文章得分集合,zset结构

  1. # python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. import redis
  5. import time
  6.  
  7. ONE_WEEK_IN_SECONDS = 7 * 86400
  8. # 如果一篇文章获得200个赞,那么这篇文章就是有趣的
  9. VOTE_SCORE = 86400 / 200
  10. ARTICLES_PER_PAGE = 25
  11.  
  12. def redis_init(redis):
  13. # article_time记录文章发布时间
  14. redis.zadd('article_time', article_100408=1496762197, article_100635=1496769721, article_100716=1496760089)
  15. # article_score记录文章得分
  16. redis.zadd('article_score', article_100408=1496766517, article_100635=1496770153, article_100716=1496765705)
  17. # voted_article_id记录编号为article_id的文章的点赞用户集合
  18. redis.sadd('voted_100408', 'user_234487', 'user_253378', 'user_364680',
  19. 'user_132097', 'user_350917')
  20. # 用hash描述每篇文章
  21. article_desc = {'title':'kunlun', 'link':'www.kunlun.com', 'poster':'user_234487',
  22. 'time':1441728000, 'votes':523}
  23. redis.hmset('article_100408', article_desc)
  24. article_desc = {'title': 'zhuxian', 'link': 'www.zhuxian.com', 'poster': 'user_234488',
  25. 'time': 1081440000, 'votes': 677}
  26. redis.hmset('article_100635', article_desc)
  27. article_desc = {'title': 'soushenji', 'link': 'www.soushenji.com', 'poster': 'user_234489',
  28. 'time': 1187280000, 'votes': 421}
  29. redis.hmset('article_100635', article_desc)
  30. # 记录文章总数
  31. redis.set('article_index', 200000)
  32.  
  33. # 用户给文章投票
  34. def article_vote(conn, user, article):
  35. cutoff = time.time() - ONE_WEEK_IN_SECONDS
  36. if conn.zscore('article_time', article) < cutoff:
  37. return
  38.  
  39. article_id = article.partition('_')[-1]
  40. if conn.sadd('voted_' + article_id, user):
  41. conn.zincrby('article_score', article, VOTE_SCORE)
  42. conn.hincrby(article, 'votes', 1)
  43.  
  44. # 发布新文章
  45. def post_article(conn, user, title, link):
  46. article_id = str(conn.incr('article_index'))
  47.  
  48. voted = 'voted_' + article_id
  49. # poster默认为文章的投票用户
  50. conn.sadd(voted, user)
  51. # 设置key过期时间
  52. conn.expire(voted, ONE_WEEK_IN_SECONDS)
  53.  
  54. now = time.time()
  55. article = 'article_' + article_id
  56. conn.hmset(article, {
  57. 'title': title,
  58. 'link': link,
  59. 'poster': user,
  60. 'time': now,
  61. 'votes': 1,
  62. })
  63.  
  64. conn.zadd('article_score', article, now + VOTE_SCORE)
  65. conn.zadd('article_time', article, now)
  66.  
  67. return article_id
  68.  
  69. # 取出评分最高的文章
  70. # 取最新发布的文章,order='article_time'
  71. # page, 按页取
  72. def get_articles(conn, page, order='article_score'):
  73. start = (page-1) * ARTICLES_PER_PAGE
  74. end = start + ARTICLES_PER_PAGE - 1
  75.  
  76. ids = conn.zrevrange(order, start, end)
  77. articles = []
  78. for id in ids:
  79. article_data = conn.hgetall(id)
  80. article_data['id'] = id
  81. articles.append(article_data)
  82.  
  83. return articles
  84.  
  85. # 添加文章到群组,或者从群组里删除文章
  86. def add_remove_groups(conn, article_id, to_add=[], to_remove=[]):
  87. article = 'article_' + article_id
  88. for group in to_add:
  89. conn.sadd('group_' + group, article)
  90. for group in to_remove:
  91. conn.srem('group_' + group, article)
  92.  
  93. # 获取群组中的文章
  94. def get_group_articles(conn, group, page, order='article_score'):
  95. key = order + group
  96. if not conn.exists(key):
  97. conn.zinterstore(key,
  98. ['group_' + group, order],
  99. aggregate='max'
  100. )
  101. # 缓存60s
  102. conn.expire(key, 60)
  103. return get_articles(conn, page, key)
  104.  
  105. r = redis.Redis(host='redis_serverip', port=6379, password='redis_passwd', db=0)
  106.  
  107. # redis_init(r)
  108.  
  109. # article_vote(r,'use_115423', 'article_100408')
  110. #
  111. # new_article_id = post_article(r, 'user_5424', 'yingxiongzhi', 'www.yingxiongzhi.com')
  112. # print('new_article_id:', new_article_id)
  113. #
  114. # add_remove_groups(r, 'article_100408')
  115. #
  116. # get_group_articles(r, 'programming', 1)

PS:

redis-py模块中有两个类:Redis和StrictRedis,两者部分API稍有不同,本文使用Redis这个类。


反对票的实现:

  1. def article_against(conn, user, article):
  2. cutoff = time.time() - ONE_WEEK_IN_SECONDS
  3. if conn.zscore('article_time', article) < cutoff:
  4. return
  5.  
  6. article_id = article.partition('_')[-1]
  7. if conn.sadd('against_' + article_id, user):
  8. conn.incrby('article_score', article, -VOTE_SCORE)
  9. conn.hincrby(article, 'votes', -1)

移除投票的竞争条件:

  1. def article_against(conn, user, article):
  2. cutoff = time.time() - ONE_WEEK_IN_SECONDS
  3. if conn.zscore('article_time', article) < cutoff:
  4. return
  5.  
  6. article_id = article.partition('_')[-1]
  7. if conn.sadd('against_' + article_id, user):
  8. pipeline = conn.pipeline()
  9.  
  10. conn.incrby('article_score', article, -VOTE_SCORE)
  11. conn.hincrby(article, 'votes', -1)
  12.  
  13. pipeline.execute()

参考资料:

《Redis实战》

https://pypi.python.org/pypi/redis

https://redis-py.readthedocs.io/en/latest/

使用Redis构建文章投票网站的更多相关文章

  1. redis 实例2 构建文章投票网站后端

    redis 实例2 构建文章投票网站后端   1.限制条件 一.如果网站获得200张支持票,那么这篇文章被设置成有趣的文章 二.如果网站发布的文章中有一定数量被认定为有趣的文章,那么这些文章需要被设置 ...

  2. 使用redis构建文章投票系统

    首先,我得说明这篇博客基本上就是<<redis in action>>第一章内容的读书笔记. 需求 首先,说明一下,我们的需求 用户可以发表文章,发表时,自己就默认的给自己的文 ...

  3. Redis构建文章聚合信息分类网站

    本系列教程内容提要 Java工程师之Redis实战系列教程教程是一个学习教程,是关于Java工程师的Redis知识的实战系列教程,本系列教程均以解决特定问题为目标,使用Redis快速解决在实际生产中的 ...

  4. Redis实现文章投票功能

    Redis的具体操作这里就不说了,说一下需求和设计思路. 需求:自己实现一个文章投票的功能1.能够按照时间分页倒叙查看文章信息2.能够给文章投票,一个用户给一篇文章只能投票一次3.需要记录分值.每次投 ...

  5. 使用Redis构建电商网站

    涉及到的key: 1. login,hash结构,存储用户token与用户ID之间的映射. 2. recent_tokens,存储最近登陆用户token,zset结构 member: token,sc ...

  6. Redis in Action 文章投票

    原书用 Python 与 Redis 进行交互,我用 PHP 来实现. 环境:LNMP(CentOS 6.6 + Nginx 1.8.0 + MySQL 5.6.23 + PHP 5.6.9)+ Re ...

  7. Redis 实战 —— 02. Redis 简单实践 - 文章投票

    需求 功能: P15 发布文章 获取文章 文章分组 投支持票 数值及限制条件 P15 如果一篇文章获得了至少 200 张支持票,那么这篇文章就是一篇有趣的文章 如果这个网站每天有 50 篇有趣的文章, ...

  8. .Net Redis实战——实现文章投票并排序

    本系列文章为学习Redis实战一书记录的随笔. 软件和环境版本:Redis:5.0.7  .Net 5.0 文中不会对Redis基础概念做过多介绍. Redis数据类型和命令可在菜鸟教程学习:http ...

  9. Skeljs – 用于构建响应式网站的前端开发框架

    skelJS 是一个轻量级的前端框架,用于构建响应式站点和应用程序.让设计人员和开发人员可能够使用四个强大的组件:CSS 网格系统,响应式处理程序,CSS 的快捷方式和插件系统. 您可能感兴趣的相关文 ...

随机推荐

  1. JAVA debug 调试demo

    1.设置断点,在代码的行号后面鼠标左键即可2.想要看调用方法的执行流程,那么调用方法也要加断点. package day6_debug; /* * 1.设置断点,在代码的行号后面鼠标左键即可 * 2. ...

  2. itoa、ltoa

    #include <stdlib.h> /*整形转字符型*/ char * itoa(int value, char *string, int radix) { char tmp[33]; ...

  3. centos7 NAT链接配置(静态ip/修改网卡名为eth0)|1

    NAT的静态ip设置并且修改网卡名为eth0 1 cd /etc/sysconfig/network-scripts/ mv eno16777736  ifcfg-eth0 #修改名称 vi eth0 ...

  4. 文件上传——客户端检测绕过(JavaScript检测)(一)

    前言 通常再一个web程序中,一般会存在登陆注册功能,登陆后一般会有上传头像等功能,如果上传验证不严格就可能造成攻击者直接上传木马,进而控制整个web业务控制权.下面通过实例,如果程序只进行了客户端J ...

  5. CSS两种盒子模型:cntent-box和border-box

    cntent-box 平时普通盒子模型,padding,border盒子会变大,向外扩展border-box 特殊盒子模型,padding,border盒子会变大,向内扩展

  6. python脚本如何同时运行多个

    当我们想一次运行多个py脚本的时候你想到了什么应用场景了吗?当你想同时并行的处理一些对象时你有什么好方法吗?下面我就简单的总结一些这方面的小技巧,方便大家根据情况灵活处理. 1 用一个py脚本运行多个 ...

  7. L14梯度消失、梯度爆炸

    梯度消失.梯度爆炸以及Kaggle房价预测 梯度消失和梯度爆炸 考虑到环境因素的其他问题 Kaggle房价预测 梯度消失和梯度爆炸 深度模型有关数值稳定性的典型问题是消失(vanishing)和爆炸( ...

  8. stand up meeting 1--11

    今天国庆同学回中科大考试因此缺席了今天的daily scrum.不过国庆的任务已经基本完成,不会影响项目进度. 今日更新: 分享功能已经完成一个版本,如下图为分享至邮件: 针对AP返回结果中没有Wor ...

  9. Product Owner交流记录1

    Abstract 最终我们选择了UWP版必应词典功能开发. 项目:“单词挑战”功能 然后我们今天中午我们和Product owner聊了聊. Content Product owner是Travis ...

  10. Daily Scrum 12/14/2015

    Progress: Dong&Minlong: 基于Oxford Speech API成功实现语音输入的功能,但由于服务器存在访问次数的限制(每分钟6次),所以暂不准备将此功能加入ALPHA版 ...