Redis - Bitmap

什么是Bitmap

操作String数据类型的key所存储的字符串指定偏移量上的位,返回原位置的值
优点:

  • 节省空间通过一个bit位来表示某个元素对应的值或者状态,其中key就是对应元素的值。实际上8个bit可以组成一个Byte,所以是及其节省空间的
  • 效率高setbit 和 getbit的时间复杂度都是O(1),其他位运算效率也高

缺点:

  • 不在意业务数据本质上位只有0和1的区别,所以用位做业务数据记录,就不需要在意value的值、

位图不是特殊的数据结构,它的内容其实就是普通字符串,也就是 byte 数组。我们可以使用普通的 get/set直接获取和设置整个位图的内容,也可以使用位图操作 getbit/setbit 等将 byte 数组看成 [位数组] 来处理。

用法

setbit

说明:给一个指定key的值第offset位赋值位value
参数:key offset value: bool or int(1 or 0)
返回值:LONG:0 or 1

127.0.0.1:6379> setbit bit 1 1
(integer) 0

getbit

说明:返回一个指定key的二进制信息
参数:key offset
返回值:LONG:0 or 1

127.0.0.1:6379> getbit bit 1
(integer) 1

bitcount

说明:返回一个指定key中位的值为1的个数
参数:key offset start end
返回值:LONG:0 or 1

127.0.0.1:6379> bitcount bit 0 -1
(integer) 2

bitfield

bitfield 有三个子指令,分别是get/set/incrby,它们都可以对指定位片段进行读写,但是最多只能处理64个连续对位,如果超过64位,就得使用多个子指令,bitfield 可以一次执行多个子指令

127.0.0.1:6379> set w hello
OK
127.0.0.1:6379> bitfield w get u4 0 # 从第一个位开始取 4 个位,结果是无符号数 (u)
(integer) 6
127.0.0.1:6379> bitfield w get u3 2 # 从第三个位开始取 3 个位,结果是无符号数 (u)
(integer) 5
127.0.0.1:6379> bitfield w get i4 0 # 从第一个位开始取 4 个位,结果是有符号数 (i)
1) (integer) 6
127.0.0.1:6379> bitfield w get i3 2 # 从第三个位开始取 3 个位,结果是有符号数 (i)
1) (integer) -3

执行多个子指令:

127.0.0.1:6379> bitfield w get u4 0 get u3 2 get i4 0 get i3 2
1) (integer) 6
2) (integer) 5
3) (integer) 6
4) (integer) -3

使用 incrby:

127.0.0.1:6379> set w hello
OK
127.0.0.1:6379> bitfield w incrby u4 2 1 # 从第三个位开始,对接下来的 4 位无符号数 +1
1) (integer) 11
127.0.0.1:6379> bitfield w incrby u4 2 1
1) (integer) 12
127.0.0.1:6379> bitfield w incrby u4 2 1
1) (integer) 13
127.0.0.1:6379> bitfield w incrby u4 2 1
1) (integer) 14
127.0.0.1:6379> bitfield w incrby u4 2 1
1) (integer) 15
127.0.0.1:6379> bitfield w incrby u4 2 1 # 溢出折返了
1) (integer) 0

饱和截断 SAT:

127.0.0.1:6379> set w hello
OK
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (integer) 11
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (integer) 12
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (integer) 13
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (intege) 14
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1
1) (integer) 15
127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1 # 保持最大值
1) (integer) 15

失败不执行 FAIL:

127.0.0.1:6379> set w hello
OK
127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1
1) (integer) 11
127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1
1) (integer) 12
127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1
1) (integer) 13
127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1
1) (integer) 14
127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1
1) (integer) 15
127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1 # 不执行
1) (nil)