BITFIELD

对字符串执行任意位域整数运算。

语法

BITFIELD key [GET encoding offset | [OVERFLOW ] [GET encoding offset | [OVERFLOW ] ...]]

引入版本:3.2.0

复杂度摘要:O(1)

该命令将 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. 使用当前字符串长度之外的 SET 或 INCRBY 位进行寻址将放大字符串,并根据需要对其进行零填充,根据所触及的最远位,以获得所需的最小长度。

必需参数

key

保存字符串的键的名称。

可选参数

BITFIELD 调用可以链接多个按顺序应用的以下操作。

GET encoding offset

返回 offset 处的值,用 encoding 解释(例如 u8 或 i16)。

SET encoding offset value

将 offset 处的值(用 encoding 解释)设置为 value 并返回其先前的值。

INCRBY encoding offset increment

将 offset 处的值(用 encoding 解释)增加 increment 并返回新值。

OVERFLOW WRAP | SAT | FAIL

设置以下 SET 和 INCRBY 操作的溢出行为:WRAP(默认)、SAT(饱和到最小/最大值)或 FAIL(溢出时返回 nil)。

详细说明

支持的子命令和整数编码

以下是支持的命令列表。

  • GET <encoding> <offset> —— 返回指定的位字段。
  • SET <encoding> <offset> <value> -- 设置指定的位字段并返回其旧值。
  • INCRBY <encoding> <offset> <increment> —— 递增或递减(如果给出负增量)指定的位字段并返回新值。

还有另一个子命令,仅通过设置溢出行为来更改连续 INCRBY 和 SET 子命令调用的行为:

  • OVERFLOW [WRAP|SAT|FAIL]

如果需要整数编码,则可以通过在有符号整数前加上 i 前缀,在无符号整数前加上 u 前缀以及整数编码的位数来组成。例如,u8 是 8 位无符号整数,i16 是 16 位有符号整数。

支持的编码有符号整数最高为 64 位,无符号整数最高为 63 位。无符号整数的这种限制是由于当前 Redis 协议无法返回 64 位无符号整数作为回复。

位和位置偏移

有两种方法可以在位域命令中指定偏移量。如果指定了没有任何前缀的数字,则它仅用作字符串内基于零的位偏移量。

但是,如果偏移量以 # 字符为前缀,则指定的偏移量将乘以整数编码的宽度,例如:

BITFIELD mystring SET i8 #0 100 SET i8 #1 200

将第一个 i8 整数设置在偏移量 0 处,第二个 i8 整数设置在偏移量 8 处。这样,如果您想要的是给定大小的普通整数数组,则不必在客户端内部自己进行数学计算。

溢出控制

使用 OVERFLOW 命令,用户可以通过指定以下行为之一来微调递增或递减溢出(或下溢)的行为:

  • WRAP:环绕,有符号和无符号整数。对于无符号整数,换行就像执行对整数可以包含的最大值取模的运算(C 标准行为)。使用有符号整数而不是换行意味着上溢重新开始向最大负值方向重新开始,下溢向最大正值方向重新开始,因此,例如,如果 i8 整数设置为值 127,则将其递增 1 将产生 -128。
  • SAT:使用饱和算术,即下溢时将值设置为最小整数值,上溢时将值设置为最大整数值。例如,从值 120 开始递增 i8 整数,增量为 10,将得到值 127,进一步的增量将始终使该值保持在 127。下溢时也会发生同样的情况,但在最大负值处会阻止该值。
  • 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/地点 是 使用Redis BITFIELD命令构建,以便在内存中表示协作画布。

性能考虑

通常 BITFIELD 是一个快速命令,但请注意,寻址当前短字符串的远位将触发分配,该分配可能比在已存在的位上执行命令的成本更高。

位顺序

BITFIELD 使用的表示形式将位图视为第一个字节的最高有效位为 0,依此类推,因此,例如,将 5 位无符号整数设置为先前设置为全零的位图中偏移量 7 处的值 23,将产生以下表示形式:

+--------+--------+
|00000001|01110000|
+--------+--------+

当偏移量和整数大小与字节边界对齐时,这与大端字节序相同,但是当不存在这种对齐时,了解字节内的位的排序方式也很重要。

Redis Software 与 Redis Cloud 兼容性

Redis
软件
Redis
Cloud
说明
✅ 标准
✅ 主动-主动
✅ 标准
✅ 主动-主动

返回值

RESP2

以下之一: * 数组回复:每个条目是在同一位置给出的子命令的相应结果。 * 无回复:如果给出 OVERFLOW FAIL 并且检测到上溢或下溢。

RESP3

以下之一: * 数组回复:每个条目是在同一位置给出的子命令的相应结果。 * 空回复:如果给出 OVERFLOW FAIL 并且检测到上溢或下溢。

资料来源:Redis 官方 BITFIELD 文档;中文内容参考 Redis 文档许可。