假设老板给你提了个需求:“小胖儿,来给我统计下咱们系统最近一个月的活跃(登录)用户数。”。

熟悉关系数据库的我们都知道,建个用户登录表呗,一个sql查询搞定。
就像这样:

select distinct userid from login_log 
where login_date >20201101 and log_date<20201130;

假设用户登录表数据特别庞大,一来占用很大磁盘空间,二来,这样的sql查询效率一定不高。

你可能会问,那不然呢?


对于这个问题,Redis还真有解决方案。对,就是这个命令。

redis desktop manager咋样找自己的userid redis查看用户_用户登录

什么意思呢?

举个例子:

setbit k1 1 1 
/*设置k1的第二位为1,此时k1就是 0100 0000
(此命令会以字节为单位计值,ascii码是@,使用get k1会返回@)*/
setbit k1 14 1
/*此时 k1就是 0100 0000 0000 0010,十六进制是 @\x02 */

redis desktop manager咋样找自己的userid redis查看用户_位运算_02

对于上面一开始提到的问题,我们可以用日期作为Redis的key,把各个用户排序后映射到value上的每一个bit,然后取出当月的每一天,进行或运算,即可计算出当月的登录用户数,而位运算正是计算机非常擅长做的事情。

下面我们看下Reids的位运算这个知识点。

 

redis desktop manager咋样找自己的userid redis查看用户_位运算_03

redis desktop manager咋样找自己的userid redis查看用户_位运算_03

这样用:

redis desktop manager咋样找自己的userid redis查看用户_位运算_05

经过setbit操作后,上述k1的值是0100 0000,k2的值是0000 0000,进行bitop与运算后,将结果存入k3,此时k3的值是0000 0000,所以get k3结果是\x00。

redis desktop manager咋样找自己的userid redis查看用户_用户登录_06

不难理解,进行“或运算”的情况。

好了,回到开头时说的问题。

我们设置了20201101、20201102、20201103三个key来代表每天的用户登录情况,使用bit位上的每一位代表每个用户的登录情况,当天登录就设置为1。

假设第一天第20个用户登录,第二天第一个用户登录,03这天还是第一个用户登录,即2个用户登录三次。如下图:

redis desktop manager咋样找自己的userid redis查看用户_redis_07

redis desktop manager咋样找自己的userid redis查看用户_位运算_08

 在对每天的登录情况进行“或运算”(对用户去重),把运算结果存入reslut变量中,再统计该变量中1的个数。

最后,用bitcount计算出登录用户数为2。


总结

简单总结一下,我们统计用户登录情况,除了传统的使用关系型数据库查询之外,还可以有另外一种思路,就是使用基于key-value的内存数据库Redis。

使用Redis的setbit命令,以日期为key,并将每一个用户映射到value中的每一个bit。然后使用bitop进行计算机非常擅长的位运算,最后通过bitcount计算出value中1的bit位数,也就是登录用户数。