You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

54 lines
2.7 KiB

# 一、介绍
举个例子用户一年的签到记录签了是1没签是0要记录365天。如果使用kv存储那么需要365条。当用户数量过亿的时候需要的存储空间就太大了。
为了解决这个问题redis提供了bitmap数据结构这样每天的签到记录只占用1位365天就是365位一共46个字节。位图的最小单位是比特(bit)每个bit的取值只能是0或1
![[Snipaste_2023-02-23_10-00-41 21.png]]
位图的内容就是普通字符串byte数组1byte=8bit。redis的位数组是自动扩展如果设置了某个偏移位置超出了现有的范围就会自动补零
# 二、基本用法
**零存** 使用setbit对位值进行逐个设置
**整存**:使用字符串一次性填充所有位数组
**零取**使用getbit获取位数组的值
## 2.1 零存整取
使用位操作符将字符串设置为hello先得到hello的ASCII码
![[Snipaste_2023-02-23_17-24-34.png]]
转换为8为ASCII码为
h:01101000
e:01100101
l:01101100
l:01101100
o:01101111
以h字符为例只需要设置为1的位置h字符有1/2/4位需要设置
![[Snipaste_2023-02-23_17-24-34 1.png]]
命令如下
![[Snipaste_2023-02-23_17-24-34 2.png]]
![[Snipaste_2023-02-23_17-24-34 3.png]]
## 2.2零存零取
![[Snipaste_2023-02-23_17-24-34 4.png]]
## 2.3整存零取
![[Snipaste_2023-02-23_17-24-34 5.png]]
## 2.4 统计和查找
位图统计指令bitcount用来统计指定位置范围内1的个数
位图查找指令bitpos用来查找指定范围内出现的第一个0或1
可以通过bitcount统计用户一共签到了多少天通过bitpos指令查找用户从哪一天开始第一次签到。如果指定了范围参数[startend],就可以统计在某个时间范围内用户签到了多少天,用户自某天以后的哪天开始签到。**注意start和end参数是字节索引也就是指定的位范围必须是8的倍数而不能任意指定。**
因为这个设计导致无法直接计算某个月内用户签到了多少天,而必须将这个月所覆盖的字节内容全部取出来在内存中统计
### bitcount
例: bitcount w 0 0 统计第一个字符中1的位数
![[Snipaste_2023-02-23_17-24-34 6.png]]
### bitpos
bitpos w 0 第一个0位
![[Snipaste_2023-02-23_17-24-34 7.png]]
bitpos w 1 0 1 从第一个字符算起第一个1位
![[Snipaste_2023-02-23_17-24-34 8.png]]
### bitfield
bitfield w get u4 0 从第一位开始取4个位结果为6对应4位二进制为0110
![[Snipaste_2023-02-23_17-24-34 9.png]]
bitfield w get u3 2 从第三位开始取3个位结果为5对应3位编码为101前面补零为0101=5
![[Snipaste_2023-02-23_17-24-34 10.png]]
# 三、使用场景
+ 用户签到统计