美文网首页redis学习大数据码农的世界
用redis的bitmap方式统计上亿访问量的周活跃用户

用redis的bitmap方式统计上亿访问量的周活跃用户

作者: lizyyy | 来源:发表于2018-03-27 00:19 被阅读203次

    提出问题

    网站每天有1亿的访问量,产品提出要统计每个uid的周活跃,目前是日志分析解决的,每天有20G的日志,公司有dip平台会用日志去计算,每次要计算两小时才能处理完。

    分析问题

    考虑了一下是否可以用redis的bitmap的方式来做一个统计周活跃的功能

    先简单说下bitmap的原理:
    假设有3个同学:

    小明 1 小明 2 小明 3

    如果有三间房,0是男,女是1,

    房1 房2 房2
    0 1 1

    如果要统计现在班上有几位女生,就可以看到两个1就是两位女生

    在计算机里,一个字节里有8个二进制位,即1byte=8bit
    假设有7个数字,我们可以按照编号放进一段连续内存里,对应位置中存在就显示1,其它默认都显示0
    比如 3,5,1,7,11,15,4,1
    那对应的位置为:

    byte0  0 1 0 1 0 1 0 1
    byte1  0 0 0 1 0 0 0 1
    

    很明显我们已经方便的对这些数字做了排序了,甚至还做了排重
    如果我们要找7是否存在这个数组中,

    只需要7/8 对应到第一个字节byte0中
    7%8对应到第7位上,如果是1就存在,0就不存在。
    

    如果两亿的数字做排序排重,我们大概要占用好几G的空间,如果用bitmap方式,最少只需要200000000/8/1024/1024 = 24M的空间就够了

    接下来我们看看bitmap在redis上的应用:

    假设这是我们uid的登录情况
    0代表未登录,1代表登录

    Monday
    8987129 0
    8298191 1
    8892198 1
    
    Tuesday
    8987129 0
    8298191 0
    8892198 1
    
    Wednesday
    8987129 0
    8298191 1
    8892198 1
    
    Thursday
    8987129 0
    8298191 0
    8892198 0
    
    Friday
    8987129 0
    8298191 1
    8892198 1
    
    Saturday
    8987129 0
    8298191 1
    8892198 0
    
    Sunday
    8987129 1
    8298191 1
    8892198 0
    

    用setbit方法,将这些数据录入到redis中:

    setbit key offset value
    设置offset对应二进制上的值,返回该位上的旧值
    
    注意:如果offset过大,则会在中间填充0
       offset最大到2^32-1,即可推出最大的字符串为512M
    
    127.0.0.1:6379> setbit Monday 8987129 0
    (integer) 0
    127.0.0.1:6379> setbit Monday 8298191 1
    (integer) 0
    127.0.0.1:6379> setbit Monday 8892198 1
    (integer) 0
    127.0.0.1:6379> setbit Tuesday 8987129 0
    (integer) 0
    127.0.0.1:6379> setbit Tuesday 8298191 0
    (integer) 0
    127.0.0.1:6379> setbit Tuesday 8892198 1
    (integer) 0
    127.0.0.1:6379> setbit Wednesday 8987129 0
    (integer) 0
    127.0.0.1:6379> setbit Wednesday 8298191 1
    (integer) 0
    127.0.0.1:6379> setbit Wednesday 8892198 1
    (integer) 0
    127.0.0.1:6379> setbit Thursday 8987129 0
    (integer) 0
    127.0.0.1:6379> setbit Thursday 8298191 0
    (integer) 0
    127.0.0.1:6379> setbit Thursday 8892198 0
    (integer) 0
    127.0.0.1:6379> setbit Friday 8987129 0
    (integer) 0
    127.0.0.1:6379> setbit Friday 8298191 1
    (integer) 0
    127.0.0.1:6379> setbit Friday 8892198 1
    (integer) 0
    127.0.0.1:6379> setbit Saturday 8987129 0
    (integer) 0
    127.0.0.1:6379> setbit Saturday 8298191 1
    (integer) 0
    127.0.0.1:6379> setbit Saturday 8892198 0
    (integer) 0
    127.0.0.1:6379> setbit Sunday 8987129 0
    (integer) 0
    127.0.0.1:6379> setbit Sunday 8298191 1
    (integer) 0
    127.0.0.1:6379> setbit Sunday 8892198 0
    (integer) 0
    

    接下来要计算7天内有登录行为的用户,只需要将周一到周五的值做位或运算就可以了

    补充下位与运算符:

    按位与运算符(&)
    参加运算的两个数据,按二进制位进行“与”运算。
    运算规则:0&0=0;  0&1=0;   1&0=0;    1&1=1;
        即:两位同时为“1”,结果才为“1”,否则为0
          
    按位或运算符(|)
    参加运算的两个对象,按二进制位进行“或”运算。
    运算规则:0|0=0;  0|1=1;  1|0=1;   1|1=1;
        即 :参加运算的两个对象只要有一个为1,其值为1。
         
    异或运算符(^)
    参加运算的两个数据,按二进制位进行“异或”运算。
    运算规则:0^0=0;  0^1=1;  1^0=1;   1^1=0;
    即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
    

    最后计算7天内登录过的活跃用户:

        127.0.0.1:6379> bitop OR result Monday Tuesday Wednesday Thursday Friday Saturday Sunday
    
    bitop operation rs key1 [key2..]    
    对key1 key2做opecation并将结果保存在rs上
    opecation可以是AND(与) OR(或) NOT(非) XOR(异或)
    

    8298191 1|0|1|0|1|1|1 = 1
    8892198 1|1|1|0|1|0|0 = 1
    8987129 0|0|0|0|0|0|0 = 0

    这里计算的结果假设3个uid都是连续的话就是 110,其实真实的存储位置是
    ...1.....1....0......
    也就是本周有两个活跃用户登录过。

    就这样,一个上亿访问量的日志统计,在redis的bitmap方式轻松解决。

    相关文章

      网友评论

        本文标题:用redis的bitmap方式统计上亿访问量的周活跃用户

        本文链接:https://www.haomeiwen.com/subject/asndcftx.html