Redis之BitMaps

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 Redis之BitMaps,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

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

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!