Redis 实用小技巧——神奇的 bitmap(下)
简介
在上一篇文章《Redis实用小技巧——神奇的 bitmap (上)》中,我们介绍了 bitmap 相关的原理知识,在这一篇文章中,我们来聊一下 Redis 中 bitmap 相关的内容。
命令
我们都知道,Redis 操作都是基于内存的,所以运算效率很高。再加上 Redis 本身支持一系列 bit 相关的操作命令,更让其成为处理 bitmap 的不二之选。
接下来,我们就一起来看一下 Redis 中 bitmap 相关的操作命令吧。
SETBIT
语法:
SETBIT key offset value
可用版本:>= 2.2.0
时间复杂度:O(1)
返回值:指定偏移量原始存储的 bit 值
对 key
所储存的字符串值,设置或清除指定偏移量上的 bit 值。
位的设置或清除取决于 value
参数,可以是 0
也可以是 1
。
当 key
不存在时,自动生成一个新的字符串值。
字符串会进行扩展以确保它可以将 value
保存在指定的偏移量上。当字符串值进行扩展时,空白位置以 0
填充。
offset
参数必须大于或等于 0
,小于 2^32 。
小技巧:
2^32 bit = (2^32 / 8 / 1024 / 1024) MB = 512 MB 。所以,String 类型的值的大小限制为 512 MB 。
当设置一个超出最大限制 2^32 长度的偏移量时,会提示一个 offset
超出范围的错误:
> SETBIT BITMAP 4294967296 1
(error) ERR bit offset is not an integer or out of range
当我们给一个 key
最大的偏移量赋值以后,会发现值的大小瞬间超过了 512 MB,而我们再给其他的偏移量赋值的时候,发现值的大小并不会发生变化。这是因为 String 类型的值仅受偏移量影响,而具体分配的内存大小则和最大偏移量有关。
> SETBIT BITMAP 4294967295 1
(integer) 0
注意:
当生成一个很长的字符串时,Redis 需要分配内存空间,该操作有时候可能会造成服务器阻塞。在 2010 年的 Macbook Pro上,设置偏移量为 2^32 - 1(512 MB 内存分配),耗费约 300 毫秒。2^30 -1(128 MB 内存分配),耗费约为 80 毫秒。2^28 -1(32 MB 内存分配),耗费约为 30 毫秒。2^26 -1(8 MB 内存分配),耗费约为 8 毫秒。但是一旦第一次内存分配完毕,随后的offset
范围内的SETBIT
操作将不会再重复分配内存。
GETBIT
语法:
GETBIT key offset
可用版本:>= 2.2.0
时间复杂度:O(1)
返回值:指定偏移量存储的 bit 值
对 key
所储存的字符串值,获取指定偏移量上的 bit 值。
对不存在的 key 或者不存在的 offset 进行 GETBIT, 返回 0 。
BITCOUNT
语法:
BITCOUNT key [start end [BYTE | BIT]]
可用版本:>= 2.6.0
时间复杂度:O(N)
返回值: bit 位的值被设置成 1 的数量
计算给定字符串中,bit 位被设置为 1
的数量。
一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start
或 end
参数,可以让计数只在特定的区间进行。
start
和 end
参数可以使用负数值:比如 -1
表示最后一个位,而 -2
表示倒数第二个位,以此类推。
不存在的 key
被当成是空字符串来处理,因此对一个不存在的 key
进行 BITCOUNT
操作,结果为 0
。
以上三个命令就是 Redis 处理 bitmap 中用的最多的「三大命令」。SETBIT 可以对字符串值的固定偏移量上的 bit 值进行设置,而 GETBIT 则可以取出固定偏移量上的 bit 值,BITCOUNT 则可以统计指定区间内的 bit 位上设置了 0 或者 1的个数。在处理 bitmap 相关的问题中,使用这三个命令基本上足够了。
当然除了这几个命令之外,Redis 处理 bit 相关的命令还包括:BITPOS,BITOP,BITFIELD 和 BITFIELD_RO,但是这些命令要么受 Redis 版本限制,要么应用的场景有限,因此我们这里不再对其展开一一进行讨论。
总结
通过以上内容的介绍,我们了解到了 Redis 中 bitmap 相关的内容。有了前两篇文章的理论基础,在下一系列的文章中,我们将带大家进入到实战阶段,看一下 bitmap 有哪些典型的应用场景。
感谢大家的持续关注~
本作品采用《CC 协议》,转载必须注明作者和本文链接
很棒。
:+1:
:clap:
学习了~
:+1: :+1: :+1:
bitmap改天试试
66