Table of Contents generated with DocToc
Redis提供了SETBIT
、GETBIT
、BITCOUNT
、BITOP
四个命令用于处理二进制位数组。
SETBIT
,为位数组指定偏移量上的二进制位设置值0或1。GETBIT
,获取位数组指定偏移量上的二进制位的值。BITCOUNT
,统计位数组中1的个数。BITOP
,既可以对多个位数组进行按位与、按位或、按位异或运算,也可以对给定位数组取反。
Redis使用字符串来表示位数组,并使用SDS结构的操作函数来处理位数组。
redisObject.type
的值为REDIS_STRING
,表示字符串对象。sdshdr.len
值为1,表示这个SDS保存了一个一字节长的位数组。buf
数组的buf[0]
字节保存了一个一字节长的位数组。buf
数组的buf[1]
字节保存了SDS程序自动追加到值的末尾的'\0'。
GETBIT
用于返回位数组bitarray
在offset
偏移量上的二进制位的值:
- 计算
byte = (offset / 8)
,byte
记录了offset
偏移量指定的二进制保存在位数组的哪个字节。 - 计算
bit = (offset mode 8) + 1
,bit
记录offset
指定的二进制位是byte
字节的第几个二进制位。 - 根据
byte
和bit
值,在位数组bitarray
中定位offset
指定的二进制位,并返回这个位的值。
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
的值。
BITCOUNT
用于统计给定位数组中,值为1
的二进制位的个数。它的实现用到了查表和variable-precision SWAR两种算法:
- 查表算法使用键长为8的表,记录了从
0000 0000
到1111 1111
在内的汉明重量。 - variable-precision SWAR算法方面,
BITCOUNT
在每次循环时载入128个二进制,调用四次32位variable-precision SWAR算法来计算这个128个二进制位的汉明重量。
根据二进制位的长度是否大于128,来决定使用哪种算法。
# 一个表,记录了所有8位长位数组的汉明重量
# 程序将8位长的位数组转换为无符号整数,并在表中进行索引
# 例如,对于输入0000 0011,程序将二进制转换为无符号整数 3
# 然后取出 weight_in_byte[3]的值 2,2 就是 0000 0011 的汉明重量
weight_in_byte = [0, 1, 1, 2, 1, 2, 2, ..., 7, 7, 8]
def BITCOUNT(bits):
# 计算位数组中包含了多少个二进制位
count = count_bit(bits)
# 初始汉明重量为0
weight = 0
# 如果未处理的二进制位大于等于 128 位
# 那么使用 variable-precision SWAR 算法
while count >= 128:
# 4个swar调用,每个调用计算32位二进制位的汉明重量
# 注意:bits[i:j]中的索引j是不包含在取值范围之内的
weight += swar (bits[0:32])
weight += swar (bits[32:64])
weight += swar (bits[64:96])
weight += swar (bits[96:128])
# 移动指针,略过已处理的位
bits = bits[128:]
# 减少未处理位的长度
count -= 128
# 如果执行到这里,说明未处理的位数量不足128,那么使用查表法
while count:
index = bits_to_unsigned_int(bits[0:8])
weight += weight_in_byte[index]
# 移动指正,略过未处理的位
bits = bits[8:]
# 减少未处理位的长度
count -= 8
return weight
BITOP
命令直接使用C语言的逻辑运算。
上一章:21、排序
下一章:23、慢查询日志