分享Redis中bittop和bitcount的有趣的实例
利用redis的bitop和bitcount来实现每日的用户量快速统计和单独用户的一段时间的登录次数
用bitop的位逻辑运算来计算每日的用户量的思路来源于一篇外文博客。
地址:https://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/
因为是篇英文博客,因此我借着这个机会锻炼英语阅读能力,同时学习一下这种运算思维逻辑,写出自己一些感悟。
一 思想来源的背景
目前很多软件中都会统计的功能,例如淘宝统计在线人数,统计每个店铺月销量,或者全民K歌中统计每一首歌在一个月内被多少用户翻唱过等等。因为这些统计往往是一种聚合,并且表述的有时很复杂,很烦多。因此用普通数据库来实现的话,有点小题大用了,而且会和磁盘I/O打上交道,一旦并发量大,又要考虑堆服务器,甚至分库分表等。
因此选用redis中间件来存放这些计算统计数据,一是因为redis中大部分的指令的时间复杂度都很小,而是所需的内存空间也很小。根据这篇外文博客中指出的:In a simulation of 128 million users, a typical metric such as “daily unique users” takes less than 50 ms on a MacBook Pro and only takes 16 MB of memory.
意思就是:在对1.28亿的用户数模拟中,就像计算每日不同用户的登录的这种典型指标,消耗了低于50ms的时间和仅仅使用了16MB的内存大小(这是基于bitmap的内存消耗)。
二 Bitmap的简要介绍
bitmap(位图)是一连串由0或1组成的二进制位,每一个位置表示一个偏移量,它提供了AND,OR,XOR等其他逻辑运算。
三 统计日用户量的思想
例如全名K歌中,某首歌(假设这首歌叫做《梦灯笼》)在一小时内被用户翻唱过一次的统计,则键可以设置 key=”梦灯笼:2020-07-23-13“,则指令为redis.setbit(key,5,1)
{width=80%}
说明:用用户id来表示key的offset,用那么上图总共16位,其中9位置为1,则使用bitcount统计,则一个小时内该歌曲被9个不同的用户翻唱过。当然用于登录次数也可以用这种表示。
四 某个用户一段时间的统计量
例如某个用户一年的登录次数,用bitmap,最大也只需要365bit的空间,键值就可以为该用户的id了。
五 使用bitop将范围延伸
如果此时有个需求,我统计了每天的数据,那么我想要按周计算每个月的某首歌的翻唱不同用户数(不叠加),这里是记录不重复的次数,因此可以用bitmap,设置偏移量,如果需要记录重复的次数,那么就要考虑用其他数据结构了,这里先不谈。
因此我们使用bitop对已有的数据做逻辑运算,例如我要获取一周内,翻唱的次数,我可以这样做,对每天的统计量进行或运算。
1 |
|
如上我对《梦灯笼》这首歌曲分别在2020-7-23~2020-7-25日期间对不同的用户模拟设定了翻唱。然后我要统计2020-7-23这天翻唱的人数,只需BITCOUNT 梦灯笼:2020-07-23
。
如果我要统计一周内翻唱的不同用户总数,只需要
1 |
|
注:利用bitop来做逻辑运算,求得1周内总共有多少不同的用户对该首歌进行了翻唱。
如果还想要统计某一区间的用户的翻唱情况,可以使用BITCOUNT
的start和end来进行约束,例如:
我想要获取用户区id区间在16,31中的翻唱情况,则可以使用BITCOUNT 梦灯笼:2020-07-25 2 4
,这里的[start, end]基本单位为字节,也就是8bit,因此[2,4]表示[16,31],但是最低也只能8个为单位,因此也存在一定的局限性。
redis用于统计数据的时候,可以看出效率还是蛮高的,下图是截取了外文博客的一个时间比较。
{width=80%}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!