Redis bitmaps学习笔记
简介
Bitmaps are not an actual data type, but a set of bit-oriented operations defined on the String type which is treated like a bit vector. Since strings are binary safe blobs and their maximum length is 512 MB, they are suitable to set up to 2^32 different bits.
引用自官方文档。简单来说就是这个bitmaps不是一个实际的数据类型,而是字符串类型上定义的一组面向bit位操作,最大长度为512MB,可以存储2^32个不同的位。
基本命令
根据文档得知Bitmaps一共有7个操作命令,分别是:BITCOUNT BITFIELD BITFIELD_RO BITOP BITPOS GETBIT SETBIT,这里先详细介绍一下常用的几个命令。
- ✨SETBIT
- 语法:SETBIT key offset value
- 用途:将key的bit下标为offset的值设为value
- 文档:redis.io
-- 将key1的bit下标为3位(后面简称第0位,第3位...)设值为1
SETBIT key1 3 1
(integer) 0
-- 这里回显的是该位修改之前的数据值
可以看到从左到右第3位的值为1,其余位为0
如果此时
setbit key1 8 1
,则会自动扩容一个字节,扩容后的值为:
- ✨GETBIT
- 语法:GETBIT key offset
- 用途:获取key的bit下标位offset的值
- 文档:redis.io
-- 获取第3位的值
[db15] > getbit key1 3
(integer) 1
-- 获取第8位的值
[db15] > getbit key1 8
(integer) 1
-- 获取第0位的值
[db15] > getbit key1 0
(integer) 0
- ✨BITCOUNT
- 语法:BITCOUNT key [start end [BYTE | BIT]]
- 用途:统计所有或指定区间区间内1的数量
- 文档:redis.io
-- 再设置几位,便于举例
[db15] > setbit key1 2 1
(integer) 0
[db15] > setbit key1 9 1
(integer) 0
[db15] > setbit key1 12 1
(integer) 0
[db15] > setbit key1 18 1
(integer) 0
[db15] > setbit key1 19 1
(integer) 0
[db15] > setbit key1 20 1
(integer) 0
[db15] > setbit key1 28 1
(integer) 0
[db15] > setbit key1 34 1
(integer) 0
[db15] > setbit key1 36 1
(integer) 0
-- 现在key1的二进制值为 00110000 11001000 00111000 00001000 00101000 便于查看每个字节中间有空格隔开
-- 第一字节有2个1,第二字节有3个1,第三字节有3个1,第四个字节有1个1,第五个字节有2个1,所以总共有11个1
-- 获取所有1的数量
[db15] > bitcount key1
(integer) 11
-- 获取第一字节中1的数量 等同于 bitcount key1 0 0 byte
[db15] > bitcount key1 0 0
(integer) 2
[db15] > bitcount key1 0 0 byte
(integer) 2
-- 获取第0位到第7位的1的数量
[db15] > bitcount key1 0 7 bit
(integer) 2
-- 获取倒数第二字节到倒数第一字节1的数量 注意:一定要是从左往右的顺序
[db15] > bitcount key1 -2 -1
(integer) 3
-- 获取倒数第4位到倒数第1位1的数量 由此可得 正向下标是从0开始计数,而倒数是从1开始计数
[db15] > bitcount key1 -4 -1 bit
(integer) 1
- ✨BITPOS
- 语法:BITPOS key bit [start [end [BYTE | BIT]]]
- 用途:获取所有或指定区间内第一个指定bit值[0 | 1]的下标
- 文档:redis.io
-- key1: 00110000 11001000 00111000 00001000 00101000
-- 获取第一个0值的下标
[db15] > bitpos key1 0
(integer) 0
-- 获取第一个1值的下标
[db15] > bitpos key1 1
(integer) 2
-- 从第1位开始到第四位的第一个1的下标 这里的下标还是总数据的下标
[db15] > bitpos key1 1 1 4 bit
(integer) 2
-- 如果没有则返回-1 如果key不存在也返回-1
[db15] > bitpos key1 1 4 6 bit
(integer) -1
-- 从第二字节到第二字节的第一个1的下标
[db15] > bitpos key1 1 2 2 byte
(integer) 18
- ✨BITOP
- 语法:BITOP <AND | OR | XOR | NOT> destkey key [key …]
- 用途:对多个key进行位运算(与 &,或 |,异或 ^,非或者叫取反 ~),结果保存到destkey中
- 文档:redis.io
[db15] > setbit op1 1 1
(integer) 0
[db15] > setbit op1 3 1
(integer) 0
[db15] > setbit op1 5 1
(integer) 0
[db15] > setbit op2 4 1
(integer) 0
[db15] > setbit op2 6 1
(integer) 0
[db15] > bitop and d1 op1 op2
(integer) 1
-- op1: 01010100
-- op2: 00001010
-- d1: 00000000
[db15] > bitop or d2 op1 op2
(integer) 1
-- d2: 01011110
[db15] > bitop xor d3 op1 op2
(integer) 1
-- d3: 01011110
[db15] > bitop not d4 op1
(integer) 1
-- d4: 10101011
实际应用
由上述的操作命令可以看出,Bitmaps的应用场景主要是统计和判断,比如签到,活跃用户,用户在线状态等等。这里以签到为例,假设有一个用户id为1,每天签到一次,那么可以用一个key来存储用户的签到情况,比如key为sign:1,可以处理的场景大概有:
- 用户签到
- 查询用户某天是否签到
- 统计指定用户的累计签到天数
- …… 自己发挥想象
-- 用户签到 记录用户ID为1的用户第一天签到
[db15] > setbit sign:1 0 1
-- 用户签到 记录用户ID为1的用户第二天签到 后面以此类推
[db15] > setbit sign:1 1 1
-- 查询用户ID为1的用户第一天是否签到
[db15] > getbit sign:1 0
-- 统计用户ID为1的用户的累计签到天数
[db15] > bitcount sign:1
-- 统计用户ID为1的用户在前七天的签到情况
[db15] > bitcount sign:1 0 6
留个坑等后面填
BITFIELD 和 BITFIELD_RO 的详细使用暂时没有介绍,等后续有时间再补充!
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Eber的小窝!
评论