Redis BitMap介绍及使用

    Redis允许使用二进制数据的Key(binary keys) 和二进制数据的Value(binary values)。Bitmap就是二进制数据的value。Redis的 setbit(key, offset, value)操作对指定的key的value的指定偏移(offset)的位置1或0,时间复杂度是O(1)。

    Redis BitMaps的操作命令:

  • SETBIT key offset value  

    对指定的key的value的指定偏移(offset)的位置1或0

  •  GETBIT key offset

    获取offset设置的值,未设置过默认返回0

  • BITCOUNT key [start end]  

    统计指定key位置为1的数量(区间统计不建议使用,bitcount用的是byte来计算位数,其他setbit和getbit用的是bit,详见:http://blog.linuxphp.org/archives/1627/)

  • BITOP operation destkey key [key ...]

        Bit运算,BITOP 支持四种表达式运算: AND(交集), OR(并集), XOR(异或) 和NOT(取非), 用法如下:
        BITOP AND destkey srckey1 srckey2 srckey3 ... srckeyN
        BITOP OR destkey srckey1 srckey2 srckey3 ... srckeyN
        BITOP XOR destkey srckey1 srckey2 srckey3 ... srckeyN
        BITOP NOT destkey srckey

  •  BITPOS key bit [start] [end]

     返回设置为1或0的一个字符串中的第一个点的位置

  1. 活跃用户统计

    活跃用户是项目中经常需要统计的一个项目,我们之前的做法是:

  •     直接从用户的登录日志中计算提取 (需要脚本定时计算,比较耗时)

  •     将每天的登录用户的uid存在Redis的SET结构中 (用户基数大的情况下,开销大)

    以上做法固然没有什么问题,但是当用户规模特别大的时候,就显得笨拙或者开销比较大,于是Redis bitmaps就上场了。

    为统计某一天的用户登陆数量,首先以当天的日志加固定的前缀作为key,建立一个bitmap。例如:userlogin:2016-01-15,每一位二进制的位做为一个用户ID的标识(offset)。当用户访问时,就把bitmap中标识此用户的二进制(value)从0置为1。

Redis BitMap介绍及使用_第1张图片

   用户登录时执行一次SETBIT(key, userId, 1),将bitmap中对应位置的位置为1。当统计某一天用户活跃数时,直接bitcount那天对应的key,当然还可以用bitop计算出如最近7天,一月个的用户活跃数。代码如下:

Redis BitMap介绍及使用_第2张图片 

2. 用户行为统计

    网站一般经常有个场景就是,判断用户是否操作过某个动作,比如是否点击过某个按钮(根据是否点击改变按钮颜色),是否领取过优惠券(是否领取过展示逻辑不同)。

    这些场景其实也可以运用到bitMap,但是前提是不大关注行为的人,因为bitMap并不能计算出用户的uid。

    之所以选择用bitmap,就是因为bitmap的操作非常快,而且也比较节省资源。

  Redis BitMap介绍及使用_第3张图片

    扩展下,其实如点赞喜欢的判断逻辑也可以用bitmap来实现,当然关系逻辑还是存在mysql中(因为这些关系有时候很重要),用bitmap来加速判断逻辑。

     最后,说一下bitmap的两个容易采坑的地方:

  •  第一个,就是bitcount命令,在使用start,end的时候一定要注意,setbit和getbit命令操作的是bit,但是bitcount用的是byte来计算位数,两者差了8倍,因此这点很容易采坑,也不建议用。

  • setbit的offset是用大小限制的,在0到 232(最大使用512M内存)之间,即0~4294967296之前,超过这个数会自动将offset转化为0,因此使用的时候一定要注意。

参考:

Redis官网

Bitmap的秘密

 使用REDIS BITMAPS进行活跃用户的统计

使用redis的setbit和bitcount来进行区间统计的坑

 

你可能感兴趣的:(redis,bitmap,phpredis)