bitmap概述
除了基本的常用的五大数据类型(string、hash、list、set、zset)之外,还有其他的五大特殊数据类型:
- bitmap:位图
- bitfield:位域
- stream:流
- geospatial:地理位置经纬度
- HyperLogLog:一种纯数学的概率算法
bitmap 数据类型是 string 类型的拓展,其本质是一个包含 0 和 1 的二进制字符串,围绕着 bitmap 的相关命令都是对这个字符串二进制位的操作。
这种二进制字符串有三个属性:
- key:
- offset:由于 bitmap 本质是一个二进制字符串,因此字符串中的每个字符都有其对应的索引编号(从 0 开始记数)。为了准确对应每个字符的位置,就使用索引编号的偏移量 offset 来实现,其范围为 [0,2^32-1]
- bitValue:当你使用 offset 指定了字符的位置时,bitValue 就是用来指定这个位的值,要么 0 ,要么 1
bitmap 数据类型主要用在一些大数据量的二值性统计场景中,比如:
- 平台的在线用户统计、平台的活跃用户统计等(二值,在线或不在线)
- 员工考勤统计(二值,打卡或未打卡)
- IP地址管理
- 二进制数据压缩(bit 已经是最小单位的存储)
- …
相关命令
setbit
命令
指定 offset,给特定的 bit 设置值,值只能是 0 或 1;也可以更新已有偏移量位置的 bitValue 。
192.168.100.3:6379> select 6
OK
192.168.100.3:6379[6]> keys *
(empty array)
# 在第一个 bit 设置值为 0
192.168.100.3:6379[6]> setbit status:emp 0 0
(integer) 0
# 在第一个 bit 更新值为 1
192.168.100.3:6379[6]> setbit status:emp 0 1
(integer) 0
# 获取特定 bit 的值
192.168.100.3:6379[6]> getbit status:emp 0
(integer) 1
# 查看 key 的类型
192.168.100.3:6379[6]> type status:emp
string
请注意!在使用 setbit
命令时,当给不存在的 offset 设置值时,bitmap 会执行 自动伸展,以确保可以将值保存在特定的 offset 上。而之所以需要 自动伸展,主要是为了性能考虑,这样可以避免频繁地分配内存过程。所以,在生产环境下通常是先给大的 offset 设置值,比如说:
192.168.100.3:6379[6]> setbit company 199999999 0
getbit
命令
指定 offset 偏移量并获取其值。
bitcount
命令
用来统计给定字符串中设置为 1 的 bit 位数量。可以用 start 和 end 可选参数来指定范围,默认情况下,范围的单位是 byte,当然,你也可以指定为 bit。
- 当为 byte 单位时,0 表示第一个 byte。也可以使用负数表示, -1 表示最后一个 byte,-2 表示倒数第二个 byte,以此类推。
- 当为 bit 单位时,0 表示第一个 bit。也可以使用负数表示, -1 表示最后一个 bit,-2 表示倒数第二个 bit,以此类推。
注:1byte=8bit
# 添加 8 个bit数据
192.168.100.3:6379[6]> setbit status:emp 5 1
(integer) 0
192.168.100.3:6379[6]> setbit status:emp 7 1
(integer) 0
192.168.100.3:6379[6]> setbit status:emp 9 1
(integer) 0
192.168.100.3:6379[6]> setbit status:emp 11 1
(integer) 0
192.168.100.3:6379[6]> setbit status:emp 13 1
(integer) 0
192.168.100.3:6379[6]> setbit status:emp 17 1
(integer) 0
192.168.100.3:6379[6]> setbit status:emp 20 1
(integer) 0
192.168.100.3:6379[6]> setbit status:emp 25 1
(integer) 0
# 不指定范围,则统计所有设置为 1 的 bit 位数量
192.168.100.3:6379[6]> bitcount status:emp
(integer) 9
# 指定 2byte 的范围
## 见下图所示
192.168.100.3:6379[6]> bitcount status:emp 0 1 byte
(integer) 6
# 使用 bit 单位
192.168.100.3:6379[6]> bitcount status:emp 0 15 bit
(integer) 6
bitpos
命令
pos 即 position,位置的意思。bitpos 用来指定第一次出现 0 或 1 的位置。你也可以使用 start 和 end 可选参数来指定范围,单位可以是 bit ,也可以是 byte。命令返回的是 offset 偏移量位置。
# 不指定范围,第一次出现 1 的位置
192.168.100.3:6379[6]> bitpos status:emp 1
(integer) 0
# 不指定范围,第一次出现 0 的位置
192.168.100.3:6379[6]> bitpos status:emp 0
(integer) 1
# 指定bit范围
## 返回 offset 为 17,表示在这个位置范围第一次出现了 1
192.168.100.3:6379[6]> bitpos status:emp 1 14 20 bit
(integer) 17
bitop
命令
对一个或多个 bitmap 的 key 执行二进制位运算,并将结果保存到新的目标 key 上。用法为——BITOP AND|OR|XOR|NOT destkey key [key ...]
二进制位运算有:
- and: 与,即都为 1 时,才输出 1,否则输出 0
- or:或,即都为 0 时,才输出 0,否则输出 1
- xor: 异或,即相同时输出 0,不同时输出 1。顺带提一句,在 Raid 当中,磁盘的数据恢复常用 简单异或逻辑算法。
- not:非,取反
使用说明:
- not 运算只能针对一个 key,其他运算的可以针对多个 key
- 当多个 key 的长度不同时,较短的 key 会使用 0 作为填充
# 创建两个新的 key ,写入一些新的数据
192.168.100.3:6379[6]> setbit tmp:1 0 1
192.168.100.3:6379[6]> setbit tmp:1 3 1
# 示意图如下:
----- ----- ----- -----
tmp:1 | 1 | 0 | 0 | 1 |
----- ----- ----- -----
offset 0 1 2 3
192.168.100.3:6379[6]> setbit tmp:2 0 1
192.168.100.3:6379[6]> setbit tmp:2 1 1
192.168.100.3:6379[6]> setbit tmp:2 2 1
192.168.100.3:6379[6]> setbit tmp:2 3 1
# 示意图如下:
----- ----- ----- -----
tmp:2 | 1 | 1 | 1 | 1 |
----- ----- ----- -----
offset 0 1 2 3
执行逻辑与运算,并将结果保存到 d1 这个 key 上:
192.168.100.3:6379[6]> bitop and d1 tmp:1 tmp:2
# 示意图如下:
----- ----- ----- -----
d1 | 1 | 0 | 0 | 1 |
----- ----- ----- -----
offset 0 1 2 3
执行逻辑或运算,并将结果保存到 d2 这个 key 上:
192.168.100.3:6379[6]> bitop or d2 tmp:1 tmp:2
# 示意图如下:
----- ----- ----- -----
d2 | 1 | 1 | 1 | 1 |
----- ----- ----- -----
offset 0 1 2 3
执行逻辑异或运算,并将结果保存到 d3 这个 key 上:
192.168.100.3:6379[6]> bitop xor d3 tmp:1 tmp:2
# 示意图如下:
----- ----- ----- -----
d3 | 0 | 1 | 1 | 0 |
----- ----- ----- -----
offset 0 1 2 3
执行逻辑非运算,并将结果保存到 d4 这个 key 上:
192.168.100.3:6379[6]> bitop not d4 tmp:1
# 示意图如下:
----- ----- ----- -----
d4 | 0 | 1 | 1 | 0 |
----- ----- ----- -----
offset 0 1 2 3