一、关于bitmap
BitMap 原本的含义是用一个比特位来映射某个元素的状态。由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间。
在 Redis 中,可以把 Bitmaps 想象成一个以比特位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmaps 中叫做偏移量。
BitMap 在 Redis 中并不是一个新的数据类型,底层是基于 Redis 的字符串类型实现的。:
二、使用场景
1、可作为简单的布隆过滤器来判断用户是否执行过某些操作;
2、可以计算用户日活、月活、留存率的统计;
3、可以统计用户在线状态和人数;
三、优点
1、节省空间:通过一个bit位来表示某个元素对应的值或者状态,其中key就是对应元素的值。实际上8个bit可以组成一个Byte,所以是及其节省空间的。
2、效率高:setbit和getbit的时间复杂度都是O(1),其他位运算效率也高。
三、redis中针对bitmap的操作
# 设置值,其中value只能是 0 和 1
setbit key offset value
# 获取值
getbit key offset
# 获取指定范围内值为 1 的个数
# start 和 end 以字节为单位
bitcount key start end
# BitMap间的运算
# operations 位移操作符,枚举值
AND 与运算 &
OR 或运算 |
XOR 异或 ^
NOT 取反 ~
# result 计算的结果,会存储在该key中
# key1 … keyn 参与运算的key,可以有多个,空格分割,not运算只能一个key
# 当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0。返回值是保存到 destkey 的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。
bitop [operations] [result] [key1] [keyn…]
# 返回指定key中第一次出现指定value(0/1)的位置
bitpos [key] [value]
四、使用bitmap统计日活
@Test
void test3(){
String key = "DAU";
User user = new User(1, "rabbit");
User user2 = new User(13, "messi");
User user3 = new User(88, "lucas");
serializableRedisTemplate.opsForValue().setBit("DAU", user.getId(), true);
serializableRedisTemplate.opsForValue().setBit("DAU", user2.getId(), true);
serializableRedisTemplate.opsForValue().setBit("DAU", user3.getId(), true);
Long count = serializableRedisTemplate.execute((RedisCallback<Long>) con -> con.bitCount(key.getBytes()));
log.info("dau:{}", count);
}