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 的基本命令。
将提供的偏移量的一个位设置为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 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让你对一个或多个字符串进行位操作,将结果存储到目标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 进行参考。