使用redis如何实现动态时间段内统计排序?

本文介绍如何利用Redis的Hash和ZSet数据结构,实现动态时间段内(如过去24小时)对数据(如帖子)的统计值(如点赞数)进行排名,并讨论了解决方案的优化和一致性问题。
摘要由CSDN通过智能技术生成
本文和大家分享的主要使用redis实现动态时间段内统计排序的相关操作方法,希望对大家学习redis 有所帮助,一起来看看吧。
问题描述
需要根据某类数据在动态时间段内的统计值对这些数据进行排名。例如按过去24小时内点赞数排名的帖子,每隔一小时计算一次结果。以下描述均针对这个例子展开。
解决思路
针对这种问题,我的第一反应是直接通过mysql一张数据表记录所有数据的每一条统计值改变的行为,例如记下每个帖子在哪个时间点被谁点赞。排序结果直接通过select + where + order_by + limit。简单粗暴,但效率低下,扩展性差,而且当数据量很多时,会导致数据库查询效率低下。
那么为了提高效率,mysql换成redis如何?将这些统计值改变的记录移到redis的zset中,为每个帖子建立一条zset,zset的每一条member代表一条点赞记录,field为帖子id,score记录点赞时间。利用zcount查询每个帖子有效时间段内的点赞总数。redis查询也快,看起来可行,但当帖子基数和点赞数很大时,zset中成员量暴增,而且对于过期数据怎么处理?而且把点赞量换成点击量呢?就要记录每个用户对每篇帖子的点击行为了,这个方案是否合理?
仔细想一下这个问题,其实我们只需要关注帖子的点赞数量,而不是每条点赞行为。因此可以考虑利用redis记录帖子在每个时间点内的点赞数量,并且定期删掉过期的数据,例如记录每条帖子每个小时内的点赞数。这样就可以知道过去24小时内这个帖子的点赞总数了。具体的方案下面将展开。
数据结构
需要两个redis数据结构,分别存放 过程 和 结果,因为要定期过期一些数据,所以要通过 过程 记录数据统计值的历史记录,同时 结果 记录所有有效过程内的总体排序结果。
例如当前时间9:00,就需要知道当前9点到昨天9点的所有点赞数量,也就不需要昨天8点的点赞数了,所以结果里面需要加上今天9点的数据,减去昨天8点的数据。而随着时间往后推移,昨天9点到今天9点的数据也会依次被减掉,所以需要记录有效时间段内每个时间点的数据,这就是过程的作用了。结果的作用显而易见了,记录结果并支持排序。
·
过程 利用 hash 结构存放在有效期内每个时间节点的所有帖子的统计值,例如建立: last_1, last_2, last_3 ……等24个key(因为是统计过去24小时内),每个hash key内记录该节点到下个节点的时间段内被点赞的帖子(field)及其点赞数(value) 为什么采用hash结构而不是list或set,因为在定时更新统计数据过程中,需要先获取当前最新,再加一或减一,hash的 hincrby 方法支持原子操作,可以在一个事务内完成这两个操作。试想在list结构下,对同一个帖子的多个并发点赞,可能导致数据错误。
·
·
结果 利用 zset 结构存放所有帖子的统计总数,也就是排序结果。包括所有帖子(member)及其统计总数(value) zset支持记录score以及按score排序,也可以支持分页获取数据。
·
想法实现
基于以上过程和结果的redis结构,需要处理统计数据的更新,以及排序结果的定时更新两个关键流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值