BITFIELD
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> ...]]
- Available since:
- 3.2.0
- Time complexity:
- O(1) for each subcommand specified
- ACL categories:
-
@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
位在当前字符串长度之外进行寻址(包括键根本不存在的情况),会导致操作执行时,缺失的部分都被视为由设置为0的位组成。 - 使用
SET
或INCRBY
处理超出当前字符串长度的位时,将根据需要扩大字符串,并用零填充,以达到触及的最远位所需的最小长度。
支持的子命令和整数编码
以下是支持的命令列表。
- GET
-- 返回指定的位字段。 - SET
-- 设置指定的位字段并返回其旧值。 - INCRBY
-- 增加或减少(如果给定的是负增量)指定的位字段并返回新值。
还有一个子命令,它仅通过设置溢出行为来改变后续INCRBY
和SET
子命令调用的行为:
- 溢出
[WRAP|SAT|FAIL]
在需要整数编码的地方,可以通过在整数编码的位数前加上i
表示有符号整数,加上u
表示无符号整数来组成。例如,u8
表示一个8位的无符号整数,i16
表示一个16位的有符号整数。
支持的编码对于有符号整数最多为64位,对于无符号整数最多为63位。无符号整数的这一限制是由于目前Redis协议无法返回64位无符号整数作为响应。
位和位置偏移
有两种方法可以在位域命令中指定偏移量。 如果指定了一个没有任何前缀的数字,它将被用作字符串中从零开始的位偏移量。
然而,如果偏移量以#
字符为前缀,指定的偏移量将乘以整数编码的宽度,例如:
BITFIELD mystring SET i8 #0 100 SET i8 #1 200
将在偏移量0处设置第一个i8整数,在偏移量8处设置第二个i8整数。 这样,如果你想要的是一个给定大小的整数数组,就不必在客户端内自己进行计算。
溢出控制
使用OVERFLOW
命令,用户可以通过指定以下行为之一来微调增量或减量溢出(或下溢)的行为:
- WRAP: 环绕,适用于有符号和无符号整数。对于无符号整数,环绕就像执行操作模以整数可以包含的最大值(C标准行为)。对于有符号整数,环绕意味着溢出会重新开始向最负值方向,而向下溢出则向最正值方向,例如,如果
i8
整数设置为值127,将其增加1将产生-128
。 - SAT: 使用饱和算术,即在溢出时将值设置为最大整数值,在溢出时将值设置为最小整数值。例如,从值120开始递增一个
i8
整数,增量为10,结果将是值127,进一步的递增将始终将值保持在127。同样的情况也发生在溢出时,但值被阻止在最负值。 - 失败: 在这种模式下,检测到溢出或下溢时不执行任何操作。相应的返回值设置为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 位无符号整数设置为值 23,偏移量为 7,放入先前设置为全零的位图中,将产生以下表示:
+--------+--------+
|00000001|01110000|
+--------+--------+
当偏移量和整数大小对齐到字节边界时,这与大端序相同,然而当这种对齐不存在时,理解字节内部的位序也很重要。
RESP2 回复
以下之一:
- Array reply: 每个条目都是相同位置给出的子命令的相应结果。
- Nil reply: 如果给出了OVERFLOW FAIL并且检测到溢出或下溢。
RESP3 回复
以下之一:
- Array reply: 每个条目都是相同位置给出的子命令的相应结果。
- Null reply: 如果给出了OVERFLOW FAIL并且检测到溢出或下溢。