1. Bitmap简介
由英文即可看出,Bitmap 是一个合成词,由 Bit 和 Map 组合而成 (Bitmap = Bit + Map)。因此想要理解 Bitmap 就首先需要理解 Bit 和 Map。
Bit 的含义: 代表计算机科学中的最小单位 (即: 0 或 1),在逻辑上可以表示为 “是/否” 或 “有/无” (A bit is a basic unit of information used in computing that can have only one of two values either 0 or 1.);
Map 的含义: 表示一种组织事物的特定方式 (a map can be termed as a way of organizing things);
因此,作为合成词, Bitmap 的含义可以通过其基本词语组成单元清晰理解,即: 将一系列表示有无状态的二值组织起来的一种数据结构 (Bitmap is a kind of data structure that organizes a series of binary values that indicates the status of either existing or not – Definition given by the writter)。
Bit-map的基本思想就是用一个bit位来标记某个元素对应的Value,而Key即是该元素。由于采用了Bit为单位来存储数据,因此在存储空间方面,可以大大节省。
假设有这样一个需求:
在20亿个随机整数中找出某个数m是否存在其中,并假设32位操作系统,4G内存
在Java中,int占4字节,1字节=8位(1 byte = 8 bit)
如果每个数字用int存储,那就是20亿个int,因而占用的空间约为 (2000000000*4/1024/1024/1024)≈7.45G
如果按位存储就不一样了,20亿个数就是20亿位,占用空间约为 (2000000000/8/1024/1024/1024)≈0.233G
2. Bitmap的操作命令
设置位
- SETBIT key offset value: 将 key 对应的 Bitmap 中的偏移量 offset 处的位设置为 value。
- value 可以是 0 或 1。
- offset 从 0 开始,最大值为 2^32 - 1。
SETBIT mybitmap 10 1
获取位
- GETBIT key offset: 获取 key 对应的 Bitmap 中的偏移量 offset 处的位的值。
- 返回值可以是 0 或 1。
GETBIT mybitmap 10
统计位
- BITCOUNT key [start end]: 统计 key 对应的 Bitmap 中,从 start 到 end 范围内的值为 1 的位的数量。
- start 和 end 都是可选参数,默认值为 0 和 -1,表示统计整个 Bitmap 中的位。
BITCOUNT mybitmap
查找位
- BITPOS key bit [start]: 查找 key 对应的 Bitmap 中,第一个值为 bit 的位的偏移量。
- bit 可以是 0 或 1。
- start 是可选参数,默认值为 0,表示从 Bitmap 的开头开始查找。
BITPOS mybitmap 1
位操作
- BITOP operation destkey srckey1 srckey2 [srckey3 …]: 对多个 Bitmap 进行位操作,并将结果存储到 destkey 中。
- operation 可以是 AND、OR、XOR 或 NOT。
- srckey1、srckey2 和 srckey3 都是源 Bitmap 的 key。
BITOP AND resultkey mybitmap1 mybitmap2
整数操作
- BITFIELD key offset type value [overflow [destination]]: 将 key 对应的 Bitmap 看作由多个整数组成的,对其中的整数进行操作。
- type 可以是 u8、u16、u32、u64、i8、i16、i32 或 i64,表示操作的整数类型。
- value 是要设置的值。
- overflow 可以是 WRAP 或 FAIL,表示溢出时的处理方式。
- destination 是可选参数,表示将结果存储到的目标位置。
BITFIELD mybitmap 10 u8 1
使用 Bitmap 操作命令的注意事项
- Bitmap 的容量: Bitmap 的容量是有限的,需要根据实际需求来设置 Bitmap 的容量。
- Bitmap 的过期时间: Bitmap 可以设置过期时间,如果 Bitmap 没有设置过期时间,则会一直占用内存。
- Bitmap 的并发访问: Bitmap 在并发访问时可能会出现竞争条件,需要使用锁来避免竞争条件。
3. Bitmap的应用场景
3.1 统计访问量
可以使用 Bitmap 来统计网站的访问量,例如每天访问网站的独立用户数。
假设我们想统计每天访问网站的独立用户数。我们可以使用一个 Bitmap 来存储每个用户的 ID。每天访问网站时,我们就将该用户的 ID 对应的位设置为 1。一天结束后,我们可以使用 BITCOUNT 命令来统计 Bitmap 中值为 1 的位的数量,即访问网站的独立用户数。
3.2 去重
可以使用 Bitmap 来进行去重,例如判断一个用户是否已经访问过某个页面。
假设我们想判断一个用户是否已经访问过某个页面。我们可以使用一个 Bitmap 来存储所有访问过该页面的用户的 ID。当用户访问该页面时,我们就将该用户的 ID 对应的位设置为 1。如果该用户的 ID 对应的位已经是 1,则表示该用户已经访问过该页面。
3.3 签到
可以使用 Bitmap 来实现签到功能,例如记录用户每天是否签到。
假设我们想实现一个签到功能,记录用户每天是否签到。我们可以使用一个 Bitmap 来存储每个用户的签到记录。每天签到时,我们就将该用户的 ID 对应的位设置为 1。如果该用户的 ID 对应的位已经是 1,则表示该用户已经签到。
3.4 缓存
可以使用 Bitmap 来实现缓存,例如判断某个数据是否在缓存中。
假设我们想实现一个缓存,判断某个数据是否在缓存中。我们可以使用一个 Bitmap 来存储所有缓存数据的 ID。当数据被缓存时,我们就将该数据的 ID 对应的位设置为 1。如果该数据的 ID 对应的位已经是 1,则表示该数据已经在缓存中。