在Reddit和Stackoverflow或者知乎上都可以看见有一个Upvote功能,这种功能让用户去维护信息流动。它可以用Redis数据库实现。
构造数据库
我们用一个zset(由权重+值两部分组成)来存储每篇文章的post时间,zset是排序好的set,它是根据值对应的权重来排序的。这样就可以让文章以时间排序的方式排列显示。
127.0.0.1:6379> zadd time: 1430104804 article:100409
(integer) 1
127.0.0.1:6379> zadd time: 1332075503.49 article:100635
(integer) 1
127.0.0.1:6379> zadd time: 1332082035.26 article:100716
(integer) 1
用另外一个zset来存储每篇文章的排名加权权重,这样就可以让文章以排名权重的方式排列显示。
127.0.0.1:6379> zadd score: 1332225027.26 article:100716
(integer) 1
127.0.0.1:6379> zadd score: 1332075503.49 article:100635
(integer) 1
127.0.0.1:6379> zadd score: 1332065417.47 article:100408
(integer) 1
用一个元素不重复的set来存储对某篇文章投票过用户的id。假设已有三个用户对article:100408投过票。
127.0.0.1:6379> sadd voted:100408 user:234487
(integer) 1
127.0.0.1:6379> sadd voted:100408 user:253378
(integer) 1
127.0.0.1:6379> sadd voted:100408 user:364680
(integer) 1
实现
#! -*- /bin/user env python
# -*- coding: utf-8 -*-
import redis
import time
ONE_WEEK_IN_SECONDS = 7 * 86400
VOTE_SCORE = 432 # 自定义投票后增加的排序权重
conn = redis.StrictRedis(host=‘localhost‘, port=6379, db=0)
def article_vote(conn, user, article):
cutoff = time.time() - ONE_WEEK_IN_SECONDS
# 只能只对最近一个星期内的文章进行投票
if conn.zscore(‘time:‘, article) < cutoff:
return
article_id = article.partition(‘:‘)[-1]
# 在voted:article_id set中添加对这篇文章 upvote的用户,防止重复upvote
if conn.sadd(‘voted:‘ + article_id, user):
# 对这篇文章增加排序权重
conn.zincrby(‘score:‘, article, VOTE_SCORE)
# 维持一个hashtable对文章的upvote计数
conn.hincrby(article, ‘votes‘, 1)
if __name__ == ‘__main__‘:
article_vote(conn, ‘user:1‘, ‘article:100408‘)
article_vote(conn, ‘user:2‘, ‘article:100408‘)
article_vote(conn, ‘user:3‘, ‘article:100408‘)
Upvote结果
查看set中voted:100408是哪些用户投票的
SMEMBERS voted:100408
127.0.0.1:6379> SMEMBERS voted:100408
1) "user:1"
2) "user:5"
3) "user:4"
4) "user:234487"
5) "user:2"
6) "user:3"
7) "user:253378"
8) "user:364680"
查看哈希表article:100408中项votes的计数,即投票数,可以得到投票数为8。
HGET article:100408 votes
Reference
[1].Redis in Action. Page16~18
[2].http://redis.io/commands/zscore
时间: 2024-11-25 15:44:15