一、关于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);
    }

参考

https://www.cnblogs.com/54chensongxia/p/13794391.html

https://spring.hhui.top/spring-blog/2018/12/25/181225-SpringBoot%E5%BA%94%E7%94%A8%E7%AF%87%E4%B9%8B%E5%80%9F%E5%8A%A9Redis%E5%AE%9E%E7%8E%B0%E6%8E%92%E8%A1%8C%E6%A6%9C%E5%8A%9F%E8%83%BD/