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 的数量。

一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 startend 参数,可以让计数只在特定的区间进行。

startend 参数可以使用负数值:比如 -1 表示最后一个位,而 -2 表示倒数第二个位,以此类推。

不存在的 key 被当成是空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0

以上三个命令就是 Redis 处理 bitmap 中用的最多的「三大命令」。SETBIT 可以对字符串值的固定偏移量上的 bit 值进行设置,而 GETBIT 则可以取出固定偏移量上的 bit 值,BITCOUNT 则可以统计指定区间内的 bit 位上设置了 0 或者 1的个数。在处理 bitmap 相关的问题中,使用这三个命令基本上足够了。

当然除了这几个命令之外,Redis 处理 bit 相关的命令还包括:BITPOSBITOPBITFIELDBITFIELD_RO,但是这些命令要么受 Redis 版本限制,要么应用的场景有限,因此我们这里不再对其展开一一进行讨论。

总结

通过以上内容的介绍,我们了解到了 Redis 中 bitmap 相关的内容。有了前两篇文章的理论基础,在下一系列的文章中,我们将带大家进入到实战阶段,看一下 bitmap 有哪些典型的应用场景。

感谢大家的持续关注~

本作品采用《CC 协议》,转载必须注明作者和本文链接
你应该了解真相,真相会让你自由。
本帖由系统于 8个月前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 7

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!