文章目录
一、Bitmap 位操作
通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。
1. SETBIT key offset value
设置一个字符串型键指定位置的二进制的值,返回该位置的旧值,如果当前键值的长度小于二进制位的偏移量,Radis会自动分配内存并将健值的当前长度到偏移量的位置都设置为0
127.0.0.1:6379> setbit mybit 5 1
2. GETBIT key offset
获得一个字符串型键指定位置的二进制的值(0或1),超出长度的返回0,当offset超出了字符串长度的时候,这个字符串就被假定为由0比特填充的连续空间。当key不存在的时候,它就认为是一个空字符串,所以offset总是超出范围,然后value也被认为是由0比特填充的连续空间。到内存分配。
127.0.0.1:6379> getbit mybit 5
3. BITCOUNT key [start] [end]
获得一个字符串型键中值是1的二进制个数。
一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的***字符位***上进行。所以start=0 并且 end=2是指前三个字节范围内查找。
start 和 end 参数的设置和 GETRANGE 命令类似,都可以使用负数值:比如 -1 表示最后一个位,而 -2 表示倒数第二个位,以此类推。
不存在的 key 被当成是空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0 。
127.0.0.1:6379> bitcount mybit 0 3
4. BITOP operation destkey key [key …]
BITOP命令对多个字符串类型健进行位元操作,并将结果存在destkey参数指定的键中。
BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数:
- BITOP AND destkey srckey1 srckey2 srckey3 … srckeyN ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。
- BITOP OR destkey srckey1 srckey2 srckey3 … srckeyN,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。
- BITOP XOR destkey srckey1 srckey2 srckey3 … srckeyN,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。
- BITOP NOT destkey srckey,对给定 key 求逻辑非,并将结果保存到 destkey 。
除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入。执行结果将始终保持到destkey里面。
127.0.0.1:6379> bitop or deskbit mybit1 mybit2
4. BITPOS key bit [start] [end]
$ BITPOS key 0|1 [start] [end]
获得指定键的第一个位置是0或1的位置,类似于indexof
返回一个位置,把字符串当做一个从左到右的字节数组,第一个符合条件的在位置0,其次在位置8,等等
默认情况下整个字符串都会被检索一次,只有在指定start和end参数(指定start和end位是可行的),该范围被解释为一个字节的范围,而不是一系列的位。所以start=0 并且 end=2是指前三个字节范围内查找。
注意,返回的位的位置始终是从0开始的,即使使用了start来指定了一个开始字节也是这样。
和GETRANGE命令一样,start和end也可以包含负值,负值将从字符串的末尾开始计算,-1是字符串的最后一个字节,-2是倒数第二个,等等。
不存在的key将会被当做空字符串来处理。
$ BITPOS key 0|1 [start] [end]
二、Bitmap 使用场景一:用户签到
如果要对用户一年内的签到情况进行统计,如果使用bitmap我们怎么做?
我们可以为每一位用户产生一个365 位的bitmap,当用户在一年中的第几天有签到,设置对应的bitmap位为1。到年底,可以用用 bitcount 进行统计。
key = 年份#用户id
offset = day of year
127.0.0.1:6379> setbit 2020#user1 0 1
(integer) 0
127.0.0.1:6379> setbit 2020#user1 2 1
(integer) 0
127.0.0.1:6379> setbit 2020#user1 3 1
(integer) 0
127.0.0.1:6379> setbit 2020#user1 100 1
(integer) 0
# 统计用户一年内的签到
127.0.0.1:6379> bitcount 2020#user1
(integer) 4
# 查看用户某天是否有签到
127.0.0.1:6379> getbit 2020#user1 2
(integer) 1
三、Bitmap 使用场景二:统计活跃用户
使用时间作为 key,然后用户ID为 offset,如果当日活跃过就设置为1
命令 BITOP operation destkey key [key ...]
127.0.0.1:6379> setbit 20200801 1 1
(integer) 0
127.0.0.1:6379> setbit 20200801 100 1
(integer) 0
127.0.0.1:6379> setbit 20200801 102 1
(integer) 0
127.0.0.1:6379> setbit 20200801 302 1
(integer) 0
127.0.0.1:6379> setbit 20200802 302 1
(integer) 0
127.0.0.1:6379> setbit 20200803 302 1
(integer) 0
127.0.0.1:6379> setbit 20200802 102 1
(integer) 0
127.0.0.1:6379> setbit 20200803 52 1
(integer) 0
# 20200801 活跃用户
127.0.0.1:6379> bitcount 20200801
(integer) 4
# 20200801~20200803 总活跃用户(至少有一天登录过,同一个人多次登录只算一次)
127.0.0.1:6379> bitop or 202008 20200801 20200802 20200803
(integer) 38
127.0.0.1:6379> bitcount 202008
(integer) 5
# 20200801~20200803 统计每都有登录的用户数
127.0.0.1:6379> bitop and 202008and 20200801 20200802 20200803
(integer) 38
127.0.0.1:6379> bitcount 202008and
(integer) 1