BitMap#

BitMap 原本的含义是用一个比特位来映射某个元素的状态。由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间。

在 Redis 中,可以把 Bitmaps 想象成一个以比特位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmaps 中叫做偏移量。

需要注意的是:BitMap 在 Redis 中并不是一个新的数据类型,其底层是 Redis 实现。

BitMap 相关命令#

Copy

# 设置值,其中value只能是 0 和 1 setbit key offset value # 获取值 getbit key offset # 获取指定范围内值为 1 的个数 # start 和 end 以字节为单位 bitcount key start end # BitMap间的运算 # operations 位移操作符,枚举值 AND 与运算 & OR 或运算 | XOR 异或 ^ NOT 取反 ~ # result 计算的结果,会存储在该key中 # key1 … keyn 参与运算的key,可以有多个,空格分割,not运算只能一个key # 当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0。返回值是保存到 destkey 的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。 bitop [operations] [result] [key1] [keyn…] # 返回指定key中第一次出现指定value(0/1)的位置 bitpos [key] [value]

BitMap 占用的空间#

在弄清 BitMap 到底占用多大的空间之前,我们再来重申下:Redis 其实只支持 5 种数据类型,并没有 BitMap 这种类型,BitMap 底层是基于 Redis 的字符串类型实现的。

我们通过下面的命令来看下 BitMap 占用的空间大小:

Copy

# 首先将偏移量是0的位置设为1 127.0.0.1:6379> setbit csx:key:1 0 1 (integer) 0 # 通过STRLEN命令,我们可以看到字符串的长度是1 127.0.0.1:6379> STRLEN csx:key:1 (integer) 1 # 将偏移量是1的位置设置为1 127.0.0.1:6379> setbit csx:key:1 1 1 (integer) 0 # 此时字符串的长度还是为1,以为一个字符串有8个比特位,不需要再开辟新的内存空间 127.0.0.1:6379> STRLEN csx:key:1 (integer) 1 # 将偏移量是8的位置设置成1 127.0.0.1:6379> setbit csx:key:1 8 1 (integer) 0 # 此时字符串的长度编程2,因为一个字节存不下9个比特位,需要再开辟一个字节的空间 127.0.0.1:6379> STRLEN csx:key:1 (integer) 2

通过上面的实验我们可以看出,BitMap 占用的空间,就是底层字符串占用的空间。假如 BitMap 偏移量的最大值是 OFFSET_MAX,那么它底层占用的空间就是:

Copy

(OFFSET_MAX/8)+1 = 占用字节数

因为字符串内存只能以字节分配,所以上面的单位是字节。

但是需要注意,Redis 中字符串的最大长度是 512M,所以 BitMap 的 offset 值也是有上限的,其最大值是:

Copy

8 * 1024 * 1024 * 512 = 2^32

由于 C语言中字符串的末尾都要存储一位分隔符,所以实际上 BitMap 的 offset 值上限是:

Copy

(8 * 1024 * 1024 * 512) -1 = 2^32 - 1

使用场景#

1. 用户签到

很多网站都提供了签到功能,并且需要展示最近一个月的签到情况,这种情况可以使用 BitMap 来实现。
根据日期 offset = (今天是一年中的第几天) % (今年的天数),key = 年份:用户id。

如果需要将用户的详细签到信息入库的话,可以考虑使用一个一步线程来完成。

2. 统计活跃用户(用户登陆情况)

使用日期作为 key,然后用户 id 为 offset,如果当日活跃过就设置为1。具体怎么样才算活跃这个标准大家可以自己指定。

假如 20201009 活跃用户情况是: [1,0,1,1,0]
20201010 活跃用户情况是 :[ 1,1,0,1,0 ]

统计连续两天活跃的用户总数:

Copy

bitop and dest1 20201009 20201010 # dest1 中值为1的offset,就是连续两天活跃用户的ID bitcount dest1

统计20201009 ~ 20201010 活跃过的用户:

Copy

bitop or dest2 20201009 20201010

3. 统计用户是否在线

如果需要提供一个查询当前用户是否在线的接口,也可以考虑使用 BitMap 。即节约空间效率又高,只需要一个 key,然后用户 id 为 offset,如果在线就设置为 1,不在线就设置为 0。

4. 实现布隆过滤器

参考#

  • https://cloud.tencent.com/developer/news/387248
  • https://springboot.io/t/topic/272
  • https://blog.csdn.net/u011489043/article/details/78990162
  • https://www.cnblogs.com/wuhaidong/articles/10389484.html
  • https://segmentfault.com/a/1190000008188655

作者: 程序员自由之路

出处:https://www.cnblogs.com/54chensongxia/p/13794391.html

版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际」知识共享许可协议进行许可。

Redis 中 BitMap 的使用场景相关推荐

  1. Redis中bitmap的妙用

    在Redis中我们经常用到set,get等命令,细心的你有没有发现,还有几个相似的命令叫setbit,getbit,它们是用来干嘛的? BitMap是什么 就是通过一个bit位来表示某个元素对应的值或 ...

  2. Redis中bitmap的妙用 1

    https://segmentfault.com/a/1190000008188655 BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8 ...

  3. Redis 中 bitmap 的原理和使用

    原理 先声明一下:Redis 有5种数据类型,而 BitMap 在 Redis 中并不是一个新的数据类型,其底层是 Redis 实现. 通常情况下,我们在 redis 中存储一个字符串,如:" ...

  4. Redis中的set应用场景

    抽奖 随机获取元素 spop myset 点赞.签到.打卡 这条微博的ID 是t1001,用户ID 是u3001. 用like:t1001 来维护t1001 这条微博的所有点赞用户. 点赞了这条微博: ...

  5. 一看就懂系列之 详解redis的bitmap在亿级项目中的应用

    前言 这是一篇拖了很久的总结,项目中引入了redis的bitmap的用法,感觉挺高大上的,刨根问底,故留下总结一篇当作纪念. 说清楚几个问题: 1.bitmap的原理.用法. 2.bitmap的优势. ...

  6. Redis中ZSet的底层数据结构跳跃表skiplist,你真的了解吗?

    欢迎大家关注我的微信公众号[老周聊架构],Java后端主流技术栈的原理.源码分析.架构以及各种互联网高并发.高性能.高可用的解决方案. 一.前言 老周写这篇文章的初衷是这样的,之前项目中有大量使用 R ...

  7. redis 中一个字段 修改map_Redis中bitmap的妙用

    在Redis中我们经常用到set,get等命令,细心的你有没有发现,还有几个相似的命令叫setbit,getbit,它们是用来干嘛的? BitMap是什么 就是通过一个bit位来表示某个元素对应的值或 ...

  8. redis的bitmap使用场景

    BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间. Redis中的 ...

  9. redis中的事务、lua脚本和管道的使用场景

    https://blog.csdn.net/fangjian1204/article/details/50585080 事务 redis中的事务并不像mysql中那么完美,只是简单的保证了原子性.re ...

最新文章

  1. linux 测试环境启用jar_Linux下用java -jar运行可执行jar包的方法教程
  2. 主流Java数据库连接池分析(C3P0,DBCP,TomcatPool,BoneCP,Druid)
  3. 【NLP-NER】什么是命名实体识别?
  4. 2020年AI领域有哪些让人惊艳的研究?
  5. VSftp常规服务配置
  6. K8s 应用管理之道 - 有状态服务
  7. Java 泛型(generics)
  8. 骑马与砍杀服务器修复,骑马与砍杀修复存档损坏的办法
  9. 教你编写高质量的 Java 代码!
  10. java中的轻重量级组件_java Swing AWT 轻量级组建 和 重量级组件
  11. 前照灯检测仪_前照灯检测仪
  12. GitHub 优秀的 Android 开源项目和框架
  13. Python dataframe绘制饼图_Python可视化29|matplotlib-饼图(pie)
  14. 戴尔笔记本电脑XPS15-9560混盘更换成SM961与SATA3固盘的步骤和方法
  15. 年会活动必备微信墙3D签到配置教程
  16. Python中except用法和作用
  17. 【Crypto】BUGKU-抄错的字符
  18. Vue组件库 View UI 来看看这80种奇奇怪怪的按钮
  19. jQuery颜色选择器ColorPicker
  20. navicat数据库表结构对比

热门文章

  1. 触发父组件变量_Vue组件之间的传值
  2. python做带数据库的登录界面_Python3 Tkinkter + SQLite实现登录和注册界面
  3. 手机必备OCR文字识别软件:福昕扫描王使用攻略
  4. 吃鸡决赛圈直播却卡屏的我心好痛,立马找来开发刚了一波
  5. T-SQL:毕业生出门需知系列(七)
  6. 好程序员大数据点睛:关于HDFS的二三事
  7. Nova: 虚机的块设备总结 [Nova Instance Block Device]
  8. oracle 审计(二)
  9. [转]Java Web基础——Action+Service +Dao三层的功能划分
  10. 解决: libcimtd.lib not found, rpcndr.lib not found