BITFIELD

Syntax
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

请注意:

  1. 使用GET位在当前字符串长度之外进行寻址(包括键根本不存在的情况),会导致操作执行时,缺失的部分都被视为由设置为0的位组成。
  2. 使用SETINCRBY处理超出当前字符串长度的位时,将根据需要扩大字符串,并用零填充,以达到触及的最远位所需的最小长度。

支持的子命令和整数编码

以下是支持的命令列表。

  • GET -- 返回指定的位字段。
  • SET -- 设置指定的位字段并返回其旧值。
  • INCRBY -- 增加或减少(如果给定的是负增量)指定的位字段并返回新值。

还有一个子命令,它仅通过设置溢出行为来改变后续INCRBYSET子命令调用的行为:

  • 溢出 [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语句仅影响子命令列表中紧随其后的INCRBYSET命令,直到下一个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并且检测到溢出或下溢。

RATE THIS PAGE
Back to top ↑