文档章节

Redis学习——举个栗子

lan_cyl
 lan_cyl
发布于 2017/04/06 16:45
字数 679
阅读 3
收藏 0
点赞 0
评论 0

原文地址:1.3 文章投票系统

1. 需求分析

要做一个可以对文章进行投票的系统,文章的排名跟得票数和发布时间相关,得票越多发布时间越近,排名越高。

一个简单的评分函数:score = post_time_in_seconds + votes * (1 * 24 * 60 *60) / 200

其中post_time_in_seconds是文章发布时间,取Unix time,即从1970年1月1日至发布时经过的秒数
votes为文章得票数,最后一项为每一票的权重。可以看出200票的权重等于一天的时间

效果类似于http://stackoverflow.com/

2. 存储结构设计

2.1 文章存储:

数据结构:hash
key: article:article_id
value:title: title, link: article_url, poster: user:user_id, time: post_time_in_seconds, votes:200

跟普通的关系数据库存储结构差不多

看个例子,图片源于原文: 以HASH结构存储文章的例子

2.2 时间排名的存储:

数据结构:zset
key: time:
value:'article:article_id': post_time_in_seconds

2.3 得分排名的存储:

数据结构:zset key: score:
value: 'article:article_id': score

类似对time和score两个字段分别做了索引

看个例子,图片源于原文: 以ZSET结构存储文章的排名

2.4 投票者的存储

数据结构:set
key: voted:article_id
value:user:user_id

记录一篇文章的所有投票者,用MySQL要更麻烦一些

看个例子,图片源于原文: 以ZSET结构存储文章的排名

2.5 分组信息的存储

数据结构:set
key: groups:group_name
value:article:article_id

看个例子,图片源于原文,score:programming是两个集合交叉的结果: 以ZSET结构存储文章的排名

3. 功能实现

ONE_WEEK_IN_SECONDS = 7 * 86400
VOTE_SCORE = 86400 / 200

# 给文章投票,当前仅支持投赞成票
def article_vote(conn, user, article):
    # vote time is one week
    cutoff = time.time() - ONE_WEEK_IN_SECONDS
    if conn.zscore('time:', article) < cutoff:
        return
    # if the user hasn't voted for this article before,
    # add the user to the voted:
    # increase this article's score
    # increase this article's votes count
    article_id = article.partition(':')[-1]
    if conn.sadd('voted:' + article_id, user):
        conn.zincrby('score:', article, VOTE_SCORE)
        conn.hincrby(article, 'votes', 1)

# 发表文章
def post_article(conn, user, title, link):
    # increase the article id
    article_id = str(conn.incr('article:'))
    voted = 'voted:' + article_id
    # the poster as the first voted:
    conn.sadd(voted, user)
    conn.expire(voted, ONE_WEEK_IN_SECONDS)

    now = time.time()
    article = 'article:' + article_id

    # add this article
    conn.hmset(article, {
        'title': title,
        'link': link,
        'poster': user,
        'time': now,
        'votes': 1,
    })

    # add this article to the sorted set
    conn.zadd('score:', article, now + VOTE_SCORE)
    conn.zadd('time:', article, now)
    return article_id

# 获取文章
ARTICLE_PER_PAGE = 25
def get_articles(conn, page, order='score:'):
    start = (page-1)*ARTICLE_PER_PAGE
    end = start + ARTICLE_PER_PAGE - 1

    # fetch the article ids
    ids = conn.zrevrange(order, start, end)
    # get article info from ids
    articles = []
    for id in ids:
        article_data = conn.hgetall(id)
        article_data['id'] = id
        article.append(article_data)
    return articles

# 对文章进行分组
def add_remove_groups(conn, article_id, to_add=[], to_remove=[]):
    article = 'article:' + article_id
    # add this article to the group
    for group in to_add:
        conn.sadd('group:' + group, article)
    # remove this article fromt the group
    for group in to_remove:
        conn.srem('group:' + group, article)

# 获取一组文章
def get_group_articles(conn, group, page, order='score:'):
    key = order + group
    # add this group's sort info
    if not conn.exists(key):
        conn.zinterstore(key,
            ['group:'+group, order],
            aggregate='max',
        )
        conn.expire(key, 60)
    # get a page of articles from the key
    return get_articles(conn, page, key)

© 著作权归作者所有

共有 人打赏支持
lan_cyl
粉丝 0
博文 9
码字总数 8771
作品 0
武汉
Java的位运算符——与(&)、非(~)、或(|)、异或(^)

1.与运算符(&),其使用规律如下: 两个操作数中位都为1,结果才为1,否则结果为0,举个栗子: a=5,b=3 a 和b 与的结果是:1 5 0101 3 & 0011 0001 => 1 2.或运算符(|),其运算规律如下...

varuscn ⋅ 02/27 ⋅ 0

《C Primer Plus》读书笔记——递归

递归的原理 一个函数调用其本身,此调用过程为递归(recursion)。 递归的使用 举个栗子: 输出如下: 递归的基本原理 每级递归都使用其私有变量(如例子中的n) 每次函数调用都返回前一级(...

cugwyman ⋅ 2017/02/04 ⋅ 0

《C Primer Plus》读书笔记——数组和指针(1)

背景 此章笔记以读者有简单的C语言基础,对数组(array)、指针(pointer)有初步了解及应用,想扎实基础或深入探究为背景而写。 数组的使用 举个栗子: 输出如下: 用标识符常量表示数组大小...

cugwyman ⋅ 2017/02/06 ⋅ 0

论文翻译和内容讲解

如何把个人有限的研究内容与实验室无限的大方向相结合?——Mr. Lei 1、论文研究的主要对象; 2、主要关注哪些问题; 3、怎么解决这些问题; 4、效果怎么样; 5、与本实验室的研究方向有哪些...

realsa ⋅ 2014/07/12 ⋅ 0

小白来实现一个Ajax请求[Ajax使用方法及相关知识点详细解析——超级全]

写在前面: 本文主要总结整理Ajax使用方法背景知识点的详细解析,以及Ajax跨域的具体使用方式并且对栗子进行了讲解,需要的朋友可以过来参考下,喜欢的可以点波赞,或者关注一下本人,希望通...

OB丶Koro1 ⋅ 2017/06/01 ⋅ 0

《How Tomcat Works》读书笔记(一)A Simple Web Server

一个基于JAVA的Web服务器主要使用两个重要类:java.net.Socket和java.net.ServerSocket。 因为web服务器使用HTTP与客户端进行通信,所以也称HTTP服务器。 1.1 HTTP HTTP请求:  Method—U...

奋斗的海贼 ⋅ 2013/01/14 ⋅ 16

Docker学习笔记——构建镜像

Docker有两种构建镜像的方式: 使用docker commit命令; 使用Dockerfile文件; 以下分别介绍这两种方式。 1.docker commit 使用命令创建镜像的步骤如下: 1. 运行容器; 2. 对容器进行修改;...

dendi_hust ⋅ 2017/12/13 ⋅ 0

遍历——PowerShell三分钟(十)

今天来介绍一个特别有用的循环——遍历 Foreach Foreach的含义是 对输入对象集合中的每个对象执行操作 假设有一到五共五个对象,那么Foreach的作用就是针对每一个对象均执行操作 举个栗子,在...

Liuzw_37 ⋅ 前天 ⋅ 0

[随机数详解]生成一个随机数,生成指定范围的随机数及随机数组去重

写在前面: 很早之前在简书写过几篇关于随机数的文章之前写的很乱,现在重新整理一下这些知识点。本文包含了如下这些知识点:js生成随机数,生成指定范围的随机数,获得不重复随机数组。 js...

OB丶Koro1 ⋅ 2017/05/09 ⋅ 0

Kotlin学习(十八): 委托模式(Delegate)和委托属性(Delegate Properties)

Tooling 委托模式已经被证明是实现继承的一个很好的替代方式,在扩展一个基类并且重写方法时,基类就必须依赖子类的实现,当不断地修改的时候,基类就会失去当初的性质,Kotlin中就将类默认为...

叫我旺仔 ⋅ 2017/11/26 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Day 17 vim简介与一般模式介绍

vim简介 vi和Vim的最大区别就是编辑一个文件时vi不会显示颜色,而Vim会显示颜色。显示颜色更便于用户编辑,凄然功能没有太大的区别 使用 yum install -y vim-enhanced 安装 vim的三种常用模式...

杉下 ⋅ 45分钟前 ⋅ 0

【每天一个JQuery特效】根据可见状态确定是否显示或隐藏元素(3)

效果图示: 主要代码: <!DOCTYPE html><html><head><meta charset="UTF-8"><title>根据可见状态确定 是否显示或隐藏元素</title><script src="js/jquery-3.3.1.min.js" ty......

Rhymo-Wu ⋅ 55分钟前 ⋅ 0

OSChina 周四乱弹 —— 初中我身体就已经垮了,不知道为什么

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @加油东溪少年 :下完这场雨 后弦 《下完这场雨》- 后弦 手机党少年们想听歌,请使劲儿戳(这里) @马丁的代码 :买了日本 日本果然赢了 翻了...

小小编辑 ⋅ 今天 ⋅ 12

浅谈springboot Web模式下的线程安全问题

我们在@RestController下,一般都是@AutoWired一些Service,由于这些Service都是单例,所以并不存在线程安全问题。 由于Controller本身是单例模式 (非线程安全的), 这意味着每个request过来,...

算法之名 ⋅ 今天 ⋅ 0

知乎Java数据结构

作者:匿名用户 链接:https://www.zhihu.com/question/35947829/answer/66113038 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 感觉知乎上嘲讽题主简...

颖伙虫 ⋅ 今天 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部