Redis学习(8)--位图

183 阅读3分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路。

位图

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

Python获取字符的ASCII码的二进制:

>>> bin(ord('h'))
'0b1101000'

零存零取,整存零取,整存整取,零存整取

setbit key 1 1 #将key的第二位设置为1

get key #整体获取key的值

getbit key 5 #获取某个具体位置的值 0/1

set key h # 整存

统计和查找

Redis提供了位图统计指令bitcount和位图查找指令bitpos。bitcount用来统计指定位置范围内1的个数,bitpos用来查找指定范围内出现的第一个0或1

> set w hello
Ok
> bitcount w
(integer) 21
> bitcount w 0 0 # 第一个字符中1的位数
(integer) 3
> bitpos w 0 # 第一个0位
(integer) 0
> bitpos w 1 #第一个1位
(integer) 1
> bitpos w 1 1 1 #从第二个字符算起,第一个1位 
(integer) 9

魔术指令bitfield

Redis3.2版本以后新增加了一个功能强大的指令bitfield,可以进行多个位的操作.

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

> set w hello
OK
> bitfield w get u4 0 #从第一个位开始取4个位,结果是无符号数(u)
(integer) 6
> bitfield w get u3 2 #从第三个位开始取3个位,结果是无符号数(u)
(integer) 5
> bitfield w get i4 0 #第一个位开始取4个位,结果是有符号数(i)
1) (integer) 6
> bitfield w get i3 2 #第三个位开始取3个位,结果是有符号数(i)
1) (integer) -3 
> bitfield w set u8 8 97 #从第9个位开始,将接下来的8个位用无符号数97替换
1) (integer) 101

关于incrby指令,默认的溢出行为是折返 。就是如果出现了溢出,就将溢出的符号位丢到。如果是8位无符号数255,加1后就会溢出,会全部变零。如果是8位有符号数127,加1后就会溢出变成-128.

bitfield指令提供了溢出策略子指令overflow,用户可以选择溢出行为,默认是折返(wrap),还可以选择失败(fail)--报错不执行,以及饱和截断(sat)--超过了范围就停留在最大或最小值。overflow指令只影响接下来的第一条指令,这条指令执行完后溢出策略会变成默认值折返(wrap)

> bitfield w overflow sat incrby u4 2 1 #从第三个位开始,对接下来的4位无符号数+1,若溢出则保持最大值
> bitfield w overflow fail incrby u4 2 1 #从第三个位开始,对接下来的4位无符号数+1,若溢出则不执行