Redis BitMaps(位图)

BitMap 原本的含义是用一个比特(bit)位来映射某个元素的状态。由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限。但是使用 bit 位的优势是能大量的节省内存空间。

Redis 中的位图(bitmaps)是字符串数据类型的一个扩展,它让你把字符串当作一个位向量。你也可以对一个或多个字符串进行位操作。位图使用场景的一些例子如下:

(1)表示集合中对象的有效状态,例如:有个对象集合大小为100,可以使用 0-99 位置的位(bit)的 0 和 1 来表示对象的有无效状态。

(2)对象权限,其中每个位表示一个特定的权限,类似于文件系统存储权限的方式。例如:一个字节 Byte 拥有 8 个 bit 位,我们可以将每一位当做一个权限,当对应位置的位为1表示拥有某个权限。

在 Redis 中,可以把 Bitmaps 想象成一个以 bit 位为单位的数组,数组的每个单元只能存储 0 和 1,数组的下标在 Bitmaps 中叫做偏移量(offset)。如下:

Key                                   Value
+---------+    +-------------------------------------------------------+
|  myKey  |    | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
+---------+    +-------------------------------------------------------+

实例

假设你有 1000 个部署在现场的传感器,标记为 0-999。你想快速确定一个给定的传感器是否在一小时内 ping 过服务器。你可以用一个位图来表示这种情况,这个位图的键引用了当前的小时。

(1)传感器 123 在 2024 年 1 月 1 日 的 00:00 小时内对服务器进行 ping。

127.0.0.1:6379> SETBIT pings:2024-01-01-00:00 123 1
(integer) 1

(2)传感器 123 是否在 2024 年 1 月 1 日 的 00:00 小时内 ping 到了服务器?

127.0.0.1:6379> GETBIT pings:2024-01-01-00:00 123
(integer) 1

(3)服务器 456 是否在 2024 年 1 月 1 日 的 00:00 小时内 ping 到了服务器?

127.0.0.1:6379> GETBIT pings:2024-01-01-00:00 456
(integer) 0

Redis BitMaps 命令

下面列出了 Redis BitMaps 的基本命令。

SETBIT命令

将提供的偏移量的一个位设置为0或1。语法如下:

SETBIT key offset value

注意:当 key 不存在时,会创建一个新的字符串值。字符串被增长,以确保它能容纳偏移处的一个位。偏移量参数需要大于或等于 0,并且小于 2^32(这将位图限制在 512MB)。当 key 处的字符串被增长时,增加的位被设置为 0。

警告:当设置最后一个可能的位(偏移量等于2^32 -1),并且存储在key处的字符串值还没有持有字符串值,或者持有一个小的字符串值,Redis需要分配所有的中间内存,这可能会阻塞服务器一段时间。在2010年的MacBook Pro上,设置位号2^32-1(512MB分配)需要~300ms,设置位号2^30-1(128MB分配)需要~80ms,设置位号2^28-1(32MB分配)需要~30ms,设置位号2^26-1(8MB分配)需要~8ms。请注意,一旦完成了第一次分配,以后对同一键的SETBIT的调用将不会有分配的开销。

实例:

127.0.0.1:6379> SETBIT mykey 7 1
(integer) 0
127.0.0.1:6379> SETBIT mykey 7 0
(integer) 1
127.0.0.1:6379> GET mykey
""

GETBIT命令

返回一个位在给定偏移处的值。语法如下:

GETBIT key offset

注意:当偏移量超过字符串的长度时,字符串被认为是一个0比特的连续空间。当key不存在时,它被认为是一个空字符串,所以offset总是超出范围,值也被认为是一个0比特的连续空间。

实例:

127.0.0.1:6379> SETBIT mykey 7 1
(integer) 0
127.0.0.1:6379> GETBIT mykey 0
(integer) 0
127.0.0.1:6379> GETBIT mykey 7
(integer) 1
127.0.0.1:6379> GETBIT mykey 100
(integer) 0

BITOP命令

让你对一个或多个字符串进行位操作,将结果存储到目标KEY中。语法如下:

BITOP <AND | OR | XOR | NOT> destkey key [key ...]

BITOP 命令支持四种位操作。AND, OR, XOR和NOT,因此调用该命令的有效形式是:

BITOP AND destkey srckey1 srckey2 srckey3 ... srckeyN
BITOP OR destkey srckey1 srckey2 srckey3 ... srckeyN
BITOP XOR destkey srckey1 srckey2 srckey3 ... srckeyN
BITOP NOT destkey srckey

正如你所看到的,NOT 很特别,因为它只需要一个输入键,因为它执行位的反转,所以它只作为一个单数运算符才有意义。

不同长度字符串的处理

当在具有不同长度的字符串之间进行操作时,所有比集合中最长的字符串短的字符串被视为零填充,直到最长的字符串的长度。

对于不存在的键也是如此,它们被视为零字节流,直到最长的字符串的长度。

注意:

BITOP 是一个潜在的慢速命令,因为它以 O(N) 时间运行。在对长的输入字符串运行时,应该注意。

对于涉及大量输入的实时指标和统计数据,一个好的方法是使用一个副本(启用 replica-read-only 选项),在这个副本中进行位操作以避免阻塞主实例。

实例:

127.0.0.1:6379> SET key1 "foobar"
"OK"
127.0.0.1:6379> SET key2 "abcdef"
"OK"
127.0.0.1:6379> BITOP AND dest key1 key2
(integer) 6
127.0.0.1:6379> GET dest
"`bc`ab"

更多命令请访问 https://redis.io/commands  进行参考。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号