什么是BitMap
BitMap,即位图,其实也就是 byte 数组,用二进制表示,只有 0 和 1 两个数字。
大小
首先占多少大小是根据里面bit偏移量而来。
那么有个小问题,一个bitmap能存多少位。 实际上, redis只支持5种数据类型. 并没有bitmap. 也就是bitmap是基于redis的字符串类型的. 而一个字符串类型最多存储512M.
8 bit = 1byte
1024 byte = 1kb
1024 kb = 1Mb
8bit = 1b(字节) = 0.001kb
其次:
我们使用的bitmap指令SETBIT key offset value, 这个指令就是将第offset设置成0或1. 比如 SETBIT ss 1000 1 //就是将1000位置为1. 1 bit就是1位, 所以我们只要将512M换算成bit, 那么就知道bitmap支持的最大设置长度了. 计算如下
8 * 1024 * 1024 * 512 = 2^32
统计日活数
原始写法
以时间建立一个key set类型,也就是说每天一个key。把每天登录的userId放到里面。如果取连续活跃用户或者计算留存。就取出来就行交并集。
缺点:set 一位就是2byte,而1024位bitmap才1024/8 =128byte可见占用大小。
优化
所以我们可以这么写,使用bitmap。key还是每天的日期。以userid作为偏移量。
涉及到的语法。
- 添加
RBitSet appidBitSet = redissonClient.getBitSet("key");
appidBitSet.set(serialNum);
- 删除
RBitSet bitSet = redissonClient.getBitSet("key");
bitSet.delete();
- 求bitmap中为1的和
RBitSet bitSet = redissonClient.getBitSet("key");
long cardinality = bitSet.cardinality();
- 交集
RBitSet bitSetFirst = redissonClient.getBitSet("k1");
RBitSet bitSetTarget = redissonClient.getBitSet("k2");
BitSet bitSetAnd = bitSetFirst.asBitSet();
bitSetAnd.and(bitSetTarget.asBitSet());
int cardinality = bitSetAnd.cardinality();
统计签到数
原写法
查库,写sql。计算本月一共签到了多少天,连签多少天。
优化
一个用户每月一个key(month+userId),根据月内的天数偏移量设为1。比如这个月第五天,那就第五位变成1。