- 用法
-
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 〉 ] ... ]
- 复杂度
- 每个子命令 O(1)
- 始于
- 3.2.0
- ACL 类别
- @bitmap, @write, @slow
- 使用
!GET
寻址当前字符串长度之外的位(包括键根本不存在的情况),操作会像缺失部分全部由设置为 0 的位组成一样执行。 - 使用
!SET
或!INCRBY
寻址当前字符串长度之外的位会根据最远的触及位,按所需最小长度来扩大字符串并用零填充。 - GET
<encoding>
<offset>
-- 返回指定的位域。 - SET
<encoding>
<offset>
<value>
-- 设置指定的位域并返回其旧值。 - INCRBY
<encoding>
<offset>
<increment>
-- 增加或减少(如果给定负增量)指定的位域并返回新值。 - OVERFLOW
[WRAP|SAT|FAIL]
- WRAP: 环绕,适用于有符号和无符号整数。对于无符号整数,环绕就像执行操作对整数能包含的最大值取模(C 标准行为)。而对于有符号整数,环绕意味着溢出重新开始朝向最负值,下溢重新开始朝向最正值。例如,如果一个
i8
整数被设置为值 127,将其加 1 将得到-128
。 - SAT: 使用饱和算术,即在下溢时将值设置为最小整数值,在溢出时设置为最大整数值。例如,将一个
i8
整数从 120 开始,增量为 10,结果将是 127,并且进一步的增量将始终使值保持在 127。下溢时也发生同样的情况,但是值会被限制在最负值。 - FAIL: 在此模式下,检测到溢出或下溢时不会执行任何操作。相应的返回值被设置为 NULL 以向调用者发出条件信号。
该命令将字符串视为位数组,能够寻址具有不同位宽和任意非(必要)对齐偏移量的特定整数域。实际上,使用此命令,您可以设置例如在位偏移量 1234 处设置一个有符号的 5 位整数到特定值,或从偏移量 4567 处检索一个 31 位无符号整数。同样,该命令处理指定整数的增量和减量,提供用户可配置的、有保证且明确定义的溢出和下溢行为。
BITFIELD
能够在同一命令调用中操作多个位字段。它接受要执行的操作列表,并返回一个回复数组,其中每个数组都与参数列表中对应的操作匹配。
例如,以下命令将位偏移量 100 处的 5 位有符号整数递增 1,并获取位偏移量 0 处的 4 位无符号整数的值:
> BITFIELD mykey INCRBY i5 100 1 GET u4 0
1) (integer) 1
2) (integer) 0
请注意
支持的子命令和整数编码
以下是支持的命令列表。
还有另一个子命令,它仅通过设置溢出行为来改变后续 !INCRBY
和 !SET
子命令调用的行为
当预期整数编码时,它可以通过为有符号整数加上 i
前缀和为无符号整数加上 u
前缀以及整数编码的位数组成。因此,例如 u8
是一个 8 位的无符号整数,i16
是一个 16 位的有符号整数。
支持的编码有符号整数最高可达 64 位,无符号整数最高可达 63 位。无符号整数的这个限制是由于目前 Valkey 协议无法返回 64 位无符号整数作为回复。
位和位置偏移量
在 bitfield 命令中指定偏移量有两种方式。如果指定了一个没有前缀的数字,它就直接用作字符串内基于零的位偏移量。
然而,如果偏移量前面加上了 #
字符,则指定的偏移量会乘以整数编码的宽度,例如
BITFIELD mystring SET i8 #0 100 SET i8 #1 200
将在偏移量 0 处设置第一个 i8 整数,在偏移量 8 处设置第二个 i8 整数。这样,如果您想要的是给定大小的普通整数数组,就不必在客户端中自己进行计算了。
溢出控制
使用 OVERFLOW
命令,用户可以通过指定以下行为之一来微调增量或减量溢出(或下溢)的行为:
请注意,每个 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)
动机
此命令的动机是,能够将许多小整数存储为单个大位图(或通过少数键分段以避免大键)可以极大提高内存效率,并为 Valkey 开启新的应用场景,尤其是在实时分析领域。这些用例得到了以受控方式指定溢出的能力的支持。
趣闻:Reddit 2017 年愚人节项目 r/place 是 使用 BITFIELD 命令构建的,用于存储协作画布的内存表示。
性能考量
通常 BITFIELD
是一个快速命令,但请注意,寻址当前短字符串的远端位会触发一次分配,这可能比在已存在位上执行命令更耗时。
位的顺序
BITFIELD
使用的表示方式将位图的第 0 位视为第一个字节的最高有效位,依此类推。因此,例如将一个 5 位无符号整数在偏移量 7 处设置为值 23,在先前全部置零的位图中,将产生以下表示:
+--------+--------+
|00000001|01110000|
+--------+--------+
当偏移量和整数大小与字节边界对齐时,这与大端序相同,但是当不存在这种对齐时,理解字节内部位的排序也很重要。
RESP2 回复
以下之一
RESP3 回复
以下之一