BitMaps
1.1 BitMaps简介
redis在2.2.0 版本之后添加了bitmaps操作,bitmaps事实上并不是一种新的数据类型,而是基于字符串位操作的集合,由于字符串是二进制安全的,并且最长可支持512M,所以它们可以用来存储2的32次方(512 * 1024 * 1024 * 8 )不同位的数据。
bitmaps的位操作分成两组:
1)固定时间的单个位操作,比如把字符串的某个位设置为1或者0,或者获取某个位上的值
2)对于一组位的操作,对给定的比特范围内,统计设定值为1的数目。
bitmaps最大的优势是在存储数据时可以极大的节省空间,比如在一个项目中采用自增长的id来标识用户,就可以仅用512M的内存来记录40多亿用户的信息
Bitmaps本身不是一种数据结构,他实际上就是一个可以进行位运算的字符串
1.2 BitMaps位图原理
刚刚我们了解到,bitmaps不是一种新的数据类型,其实是以一种位运算的方式来操作原有的字符串而已。
假设我们存储了asd
字符串在redis当中,a的ASCII为97,对应的为115、100,那么对应的二进制数据图如下:
getbit key offset
- 说明:获取指定key偏移量位置的二进制值。
- offset:偏移量
getbit命令示例:
127.0.0.1:6379> set test1 asd
OK
127.0.0.1:6379> getbit test1 0
(integer) 0
127.0.0.1:6379> getbit test1 1
(integer) 1
127.0.0.1:6379> getbit test1 2
(integer) 1
127.0.0.1:6379> getbit test1 3
(integer) 0
127.0.0.1:6379> getbit test1 4
(integer) 0
127.0.0.1:6379> getbit test1 5
(integer) 0
127.0.0.1:6379> getbit test1 6
(integer) 0
127.0.0.1:6379> getbit test1 7
(integer) 1
127.0.0.1:6379> getbit test1 8
(integer) 0
127.0.0.1:6379>
图解:
setbit key offset value
- 说明:设置key的指定偏移量上的值
- offset:索引偏移量(从0开始计算)
- value:具体的值(只能是0或1)
示例:
127.0.0.1:6379> setbit test2 0 1
(integer) 0
127.0.0.1:6379> setbit test2 1 1
(integer) 0
127.0.0.1:6379> setbit test2 8 1
(integer) 0
127.0.0.1:6379> setbit test2 10 1
(integer) 0
127.0.0.1:6379> setbit test2 12 1
(integer) 0
127.0.0.1:6379>
图解:
咱们看上图能分析,如果偏移量间隔过大,那么势必会造成中间补0现象较大
例如:
setbit test2 300 1
注意:在第一次setbit时, 如果偏移量非常大, 那么意味着前面的空出都需要0位来补充, 因此会造成Redis的阻塞。
bigcount key [start end]
- 说明:统计指定key的二进制位上的1的个数,不指定start和end就获取全部
- start:其实索引
- end:终止索引
127.0.0.1:6379> bitcount test2
(integer) 6
127.0.0.1:6379>
bitop operation destkey key [key...]
- 说明:用于多个BitMap做交集(and)、并集(or)、非(not)、异或(xor)操作,并将其结果计算保存到新的key中
- operation:操作类型
- and:交集
- or:并集
- not:非
- xor:异或
- destkey:存储计算的结果
and
与(&),取交集,有假为假
127.0.0.1:6379> setbit test3 0 1
(integer) 0
127.0.0.1:6379> setbit test3 1 1
(integer) 0
127.0.0.1:6379> setbit test3 2 1
(integer) 0
127.0.0.1:6379> setbit test3 3 0
(integer) 0
127.0.0.1:6379> setbit test4 0 1
(integer) 0
127.0.0.1:6379> setbit test4 1 0
(integer) 0
127.0.0.1:6379> setbit test4 2 1
(integer) 0
127.0.0.1:6379> setbit test4 3 1
(integer) 0
127.0.0.1:6379> getbit and-test 0
(integer) 1
127.0.0.1:6379> getbit and-test 1
(integer) 0
127.0.0.1:6379> getbit and-test 2
(integer) 1
127.0.0.1:6379> getbit and-test 3
(integer) 0
127.0.0.1:6379> getbit and-test 4
or
或(|),按位非操作只能指定一个key,代表对哪个key进行”按位非”操作,有真为真
127.0.0.1:6379> bitop or or-test test3 test4
(integer) 1
127.0.0.1:6379> bitcount or-test
(integer) 4
127.0.0.1:6379> getbit or-test 0
(integer) 1
127.0.0.1:6379> getbit or-test 1
(integer) 1
127.0.0.1:6379>
not
非(~),按位取反,1为0,0为1,按位取反时如果不够8的整数位后面的均会以0补齐
127.0.0.1:6379> bitcount not-test
(integer) 5
127.0.0.1:6379> getbit not-test 0
(integer) 0
127.0.0.1:6379> getbit not-test 1
(integer) 0
127.0.0.1:6379> getbit not-test 2
(integer) 0
127.0.0.1:6379> getbit not-test 3
(integer) 1
127.0.0.1:6379> getbit not-test 4
(integer) 1
127.0.0.1:6379> getbit not-test 5
(integer) 1
127.0.0.1:6379> getbit not-test 6
(integer) 1
127.0.0.1:6379> getbit not-test 7
(integer) 1
127.0.0.1:6379>
xor
异或(^),相同为1,不同为0
127.0.0.1:6379> bitop xor xor-test test3 test4
(integer) 1
127.0.0.1:6379> bitcount xor-test
(integer) 2
127.0.0.1:6379> getbit xor-test 0
(integer) 0
127.0.0.1:6379> getbit xor-test 1
(integer) 1
127.0.0.1:6379> getbit xor-test 2
(integer) 0
127.0.0.1:6379> getbit xor-test 3
(integer) 1
127.0.0.1:6379>
1.3 bitmaps应用场景
- 统计每天、每月网站的用户登录数量
- 统计每天、每月网站的用户访问数量
- 统计每天、每月文件被下载数
- 统计xxx-xxx时间内网站登录用户
- 统计本月未打卡人数
- …
案例:统计周期内用户登录的人数
setbit 登录日期 用户id 是否登录
127.0.0.1:6379> setbit pv:2020-0101 0 1
(integer) 0
127.0.0.1:6379> setbit pv:2020-0101 3 1
(integer) 0
127.0.0.1:6379> setbit pv:2020-0101 6 1
(integer) 0
127.0.0.1:6379> setbit pv:2020-0101 9 0
(integer) 0
127.0.0.1:6379> setbit pv:2020-0102 2 1
(integer) 0
127.0.0.1:6379> setbit pv:2020-0102 5 0
(integer) 0
127.0.0.1:6379> setbit pv:2020-0102 8 1
(integer) 0
统计2020年1月1日到2020年1月2日有多少用户登录过。
127.0.0.1:6379> bitop or pv:01-02 pv:2020-0101 pv:2020-0102
(integer) 2
127.0.0.1:6379> bitcount pv:01-02
(integer) 5
127.0.0.1:6379>
1.4 BitMap总结
bitmap操作起来这么复杂,为什么我们还要使用它呢?
因为bitmap存储单位是”位”,咱们计算机最小的存储单位都是byte(字节),而一个字节是8个位,因此存储效率明显是bitmap高多了,而实际开发中id往往是Long类型进行存储(8个字节),8*8=64。因此存储效率可想而知,但由于bitmap直接操作的是”位”,操作起来不方便,在开发中操作”位”给开发者带来一定的困难,需要花费一定的时间来操作,因此在数据结构的角度上来看,bitmap实质上是采取时间换空间的操作
- 优点:存储效率高
- 缺点
- 操作不便,给开发者带来一定的困难
- setbit偏移量较高时,需要补零,造成redis阻塞。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/131846.html