Redisを使用した記事投票サイトの構築
関連する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構造
PS:
redis-pyモジュールには、RedisとStrictRedisの2つのクラスがあり、両者の部分的なAPIはやや異なり、本稿ではRedisというクラスを使用する.
反対票の実現:
投票の競合条件を削除するには、次の手順に従います.
参考資料:
『Redis実戦』
https://pypi.python.org/pypi/redis
https://redis-py.readthedocs.io/en/latest/
転載先:https://www.cnblogs.com/gattaca/p/6958789.html
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構造
# python3
# -*- coding: utf-8 -*-
import redis
import time
ONE_WEEK_IN_SECONDS = 7 * 86400
# 200 ,
VOTE_SCORE = 86400 / 200
ARTICLES_PER_PAGE = 25
def redis_init(redis):
# article_time
redis.zadd('article_time', article_100408=1496762197, article_100635=1496769721, article_100716=1496760089)
# article_score
redis.zadd('article_score', article_100408=1496766517, article_100635=1496770153, article_100716=1496765705)
# voted_article_id article_id
redis.sadd('voted_100408', 'user_234487', 'user_253378', 'user_364680',
'user_132097', 'user_350917')
# hash
article_desc = {'title':'kunlun', 'link':'www.kunlun.com', 'poster':'user_234487',
'time':1441728000, 'votes':523}
redis.hmset('article_100408', article_desc)
article_desc = {'title': 'zhuxian', 'link': 'www.zhuxian.com', 'poster': 'user_234488',
'time': 1081440000, 'votes': 677}
redis.hmset('article_100635', article_desc)
article_desc = {'title': 'soushenji', 'link': 'www.soushenji.com', 'poster': 'user_234489',
'time': 1187280000, 'votes': 421}
redis.hmset('article_100635', article_desc)
#
redis.set('article_index', 200000)
#
def article_vote(conn, user, article):
cutoff = time.time() - ONE_WEEK_IN_SECONDS
if conn.zscore('article_time', article) < cutoff:
return
article_id = article.partition('_')[-1]
if conn.sadd('voted_' + article_id, user):
conn.zincrby('article_score', article, VOTE_SCORE)
conn.hincrby(article, 'votes', 1)
#
def post_article(conn, user, title, link):
article_id = str(conn.incr('article_index'))
voted = 'voted_' + article_id
# poster
conn.sadd(voted, user)
# key
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('article_score', article, now + VOTE_SCORE)
conn.zadd('article_time', article, now)
return article_id
#
# ,order='article_time'
# page,
def get_articles(conn, page, order='article_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
# ,
def add_remove_groups(conn, article_id, to_add=[], to_remove=[]):
article = 'article_' + article_id
for group in to_add:
conn.sadd('group_' + group, article)
for group in to_remove:
conn.srem('group_' + group, article)
#
def get_group_articles(conn, group, page, order='article_score'):
key = order + group
if not conn.exists(key):
conn.zinterstore(key,
['group_' + group, order],
aggregate='max'
)
# 60s
conn.expire(key, 60)
return get_articles(conn, page, key)
r = redis.Redis(host='redis_serverip', port=6379, password='redis_passwd', db=0)
# redis_init(r)
# article_vote(r,'use_115423', 'article_100408')
#
# new_article_id = post_article(r, 'user_5424', 'yingxiongzhi', 'www.yingxiongzhi.com')
# print('new_article_id:', new_article_id)
#
# add_remove_groups(r, 'article_100408')
#
# get_group_articles(r, 'programming', 1)
PS:
redis-pyモジュールには、RedisとStrictRedisの2つのクラスがあり、両者の部分的なAPIはやや異なり、本稿ではRedisというクラスを使用する.
反対票の実現:
def article_against(conn, user, article):
cutoff = time.time() - ONE_WEEK_IN_SECONDS
if conn.zscore('article_time', article) < cutoff:
return
article_id = article.partition('_')[-1]
if conn.sadd('against_' + article_id, user):
conn.incrby('article_score', article, -VOTE_SCORE)
conn.hincrby(article, 'votes', -1)
投票の競合条件を削除するには、次の手順に従います.
def article_against(conn, user, article):
cutoff = time.time() - ONE_WEEK_IN_SECONDS
if conn.zscore('article_time', article) < cutoff:
return
article_id = article.partition('_')[-1]
if conn.sadd('against_' + article_id, user):
pipeline = conn.pipeline()
conn.incrby('article_score', article, -VOTE_SCORE)
conn.hincrby(article, 'votes', -1)
pipeline.execute()
参考資料:
『Redis実戦』
https://pypi.python.org/pypi/redis
https://redis-py.readthedocs.io/en/latest/
転載先:https://www.cnblogs.com/gattaca/p/6958789.html