22 二进制数组
Redis提供了SETBIT、GETBIT、BITCOUNT、BITOP四个命令用于处理二进制位数组。
SETBIT,为位数组指定偏移量上的二进制位设置值0或1。GETBIT,获取位数组指定偏移量上的二进制位的值。BITCOUNT,统计位数组中1的个数。BITOP,既可以对多个位数组进行按位与、按位或、按位异或运算,也可以对给定位数组取反。
22.1 位数组的表示
Redis使用字符串来表示位数组,并使用SDS结构的操作函数来处理位数组。

redisObject.type的值为REDIS_STRING,表示字符串对象。sdshdr.len值为1,表示这个SDS保存了一个一字节长的位数组。buf数组的buf[0]字节保存了一个一字节长的位数组。buf数组的buf[1]字节保存了SDS程序自动追加到值的末尾的’\0’。
22.2 GETBIT命令的实现
GETBIT
用于返回位数组bitarray在offset偏移量上的二进制位的值:
- 计算
byte = (offset / 8),byte记录了offset偏移量指定的二进制保存在位数组的哪个字节。 - 计算
bit = (offset mode 8) + 1,bit记录offset指定的二进制位是byte字节的第几个二进制位。 - 根据
byte和bit值,在位数组bitarray中定位offset指定的二进制位,并返回这个位的值。
22.3 SETBIT命令的实现
SETBIT
用于将位数组bitarray在offset偏移量上的二进制位设置为value:
- 计算
len = (offset / 8) + 1,len记录了offset指定的二进制位至少需要多少个字节。 - 检查
bitarray键保存的位数组长度是否小于len。如果是,扩展,并将新空间的二进制位置为0。 - 计算
byte = (offset / 8),byte记录了offset偏移量指定的二进制保存在位数组的哪个字节。 - 计算
bit = (offset mode 8) + 1,bit记录offset指定的二进制位是byte字节的第几个二进制位。 - 根据
byte和bit值,在位数组bitarray中定位offset指定的二进制位,首先将现在的值保存在oldvalue变量,然后将value设置为新值。 - 向客户端返回
oldvalue的值。
22.4 BITCOUNT命令的实现
BITCOUNT用于统计给定位数组中,值为1的二进制位的个数。它的实现用到了查表和variable-precision SWAR两种算法:
- 查表算法使用键长为8的表,记录了从
0000 0000到1111 1111在内的汉明重量。 - variable-precision SWAR算法方面,
BITCOUNT在每次循环时载入128个二进制,调用四次32位variable-precision SWAR算法来计算这个128个二进制位的汉明重量。
根据二进制位的长度是否大于128,来决定使用哪种算法。
1 | # 一个表,记录了所有8位长位数组的汉明重量 |
22.5 BITOP命令的实现
BITOP命令直接使用C语言的逻辑运算。
导航
上一章:21. 排序
下一章:23. 慢查询日志
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Estom的博客!










