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