比特菲尔德
BITFIELD key [GET encoding offset | [OVERFLOW <WRAP | SAT | FAIL>] <SET encoding offset value | INCRBY encoding offset increment> [GET encoding offset | [OVERFLOW <WRAP | SAT | FAIL>] <SET encoding offset value | INCRBY encoding offset increment> ...]]
- 从以下位置开始可用:
- 3.2.0
- 时间复杂度:
- O(1) 对于每个指定的子命令
- ACL 类别:
-
@write
,@bitmap
,@slow
,
该命令将 Redis 字符串视为位数组,并且能够寻址具有不同位宽和任意(必要)对齐偏移量的特定整数字段。实际上,使用此命令,例如,可以将位偏移量为 1234 的有符号 5 位整数设置为特定值,从偏移量 4567 中检索 31 位无符号整数。同样,该命令处理指定整数的递增和递减,从而提供用户可以配置的有保证且指定明确的溢出和下溢行为。
BITFIELD
能够在同一命令调用中使用多个位字段进行作。它需要一个要执行的作列表,并返回一个回复数组,其中每个数组都与参数列表中的相应作匹配。
例如,以下命令在位偏移量 100 处递增 5 位有符号整数,并在位偏移量 0 处获取 4 位无符号整数的值:
> BITFIELD mykey INCRBY i5 100 1 GET u4 0
1) (integer) 1
2) (integer) 0
请注意:
- 寻址
GET
超出当前字符串长度的 bits (包括 key 根本不存在的情况),导致要执行的作,如 missing part all 由设置为 0 的 bits 组成。 - 寻址
SET
或INCRBY
当前字符串长度之外的位将放大字符串,并根据触及的最远位,根据需要为所需的最小长度进行零填充。
支持的子命令和整数编码
以下是支持的命令列表。
- 获取
<encoding>
<offset>
-- 返回指定的位字段。 - 设置
<encoding>
<offset>
<value>
-- 设置指定的位字段并返回其旧值。 - INCRBY
<encoding>
<offset>
<increment>
-- 递增或递减(如果给出负增量)指定的位字段并返回新值。
还有另一个子命令,它只改变 successive 的行为INCRBY
和SET
subcommands调用:
- 溢出
[WRAP|SAT|FAIL]
在需要整数编码的情况下,可以通过在i
对于有符号整数和u
对于无符号整数,替换为我们的整数编码的位数。例如,u8
是 8 位的无符号整数,i16
是一个
16 位的有符号整数。
支持的编码包括:有符号整数最高 64 位,有符号整数最高 63 位 unsigned 整数。无符号整数的这种限制是由于 当前 Redis 协议无法返回 64 位无符号整数 作为回复。
位和位置偏移量
有两种方法可以在 bitfield 命令中指定偏移量。 如果指定了不带任何前缀的数字,则将其用作从 0 开始的数字 字符串内的 bit offset 值。
但是,如果偏移量以字符为前缀,则指定的偏移量
乘以整数编码的 width,例如:#
BITFIELD mystring SET i8 #0 100 SET i8 #1 200
将第一个 i8 整数设置在偏移量 0 处,第二个整数设置在偏移量 8 处。 这样,你就不必在客户端内部自己做数学运算,如果 你想要的是一个给定大小的整数的普通数组。
溢出控制
使用OVERFLOW
命令,则用户能够微调
增量或减量溢出(或下溢),通过指定以下值之一
以下行为:
- WRAP:环绕,包含有符号和无符号整数。对于无符号整数,换行就像对整数可以包含的最大值执行取模运算(C 标准行为)。使用有符号整数时,换行意味着溢出会向最负的值重新开始,并向最正的值下溢,因此,如果
i8
integer 设置为值 127,将其增加 1 将产生-128
. - SAT:使用饱和算法,即在下溢时,该值设置为最小整数值,在溢出时设置为最大整数值。例如,递增
i8
从值 120 开始且增量为 10 的整数将得到值 127,进一步的增量将始终保持值 127。下溢也会发生同样的情况,但 towards 该值在最负的值处被阻止。 - FAIL:在此模式下,不对检测到的溢出或下溢执行任何作。相应的返回值设置为 NULL 以向调用方发出条件信号。
请注意,每个OVERFLOW
语句仅影响INCRBY
和SET
在子命令列表中紧随其后的命令,直到下一个OVERFLOW
陈述。
默认情况下,如果未另行指定,则使用 WRAP。
> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 1
2) (integer) 1
> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 2
2) (integer) 2
> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 3
2) (integer) 3
> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer) 0
2) (integer) 3
以下是OVERFLOW FAIL
返回 NULL。
> BITFIELD mykey OVERFLOW FAIL incrby u2 102 1
1) (nil)
动机
此命令的动机是能够存储许多小整数 因为单个大位图(或分割几个键以避免拥有巨大的键)具有极高的内存效率,并为 Redis 的应用开辟了新的用例,尤其是在实时分析领域。以受控方式指定溢出的能力支持此用例。
有趣的事实:Reddit 的 2017 年愚人节项目 r/place 是使用 Redis BITFIELD 命令构建的,以便采用协作画布的内存中表示。
性能注意事项
通常BITFIELD
是一个快速命令,但请注意,对当前短字符串的远位进行寻址将触发分配,这可能比对已存在的位执行命令的成本更高。
位顺序
使用的表示形式BITFIELD
将位图视为具有
位号 0 是第一个字节的最高有效位,依此类推,因此
例如,将 5 位无符号整数设置为偏移量 7 处的值 23 到
Bitmap 之前设置为全零,将产生以下表示形式:
+--------+--------+
|00000001|01110000|
+--------+--------+
当偏移量和整数大小与 bytes 边界对齐时,这是 与 big endian 相同,但是当这种对齐不存在时,它很重要 )来了解字节内的位是如何排序的。
RESP2 回复
以下选项之一:
- Array reply:每个条目都是在相同位置给出的子命令的相应结果。
- Nil 回复:如果给出了 OVERFLOW FAIL 并且检测到溢出或下溢。
RESP3 回复
以下选项之一:
- Array reply:每个条目都是在相同位置给出的子命令的相应结果。
- 空回复:如果给出了 OVERFLOW FAIL 并且检测到溢出或下溢。