我的编程空间,编程开发者的网络收藏夹
学习永远不晚

关于Redis中bitmap的原理和使用详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

关于Redis中bitmap的原理和使用详解

一、原理

先声明一下:Redis 有5种数据类型,而 BitMap 在 Redis 中并不是一个新的数据类型,其底层是 Redis 实现。

通常情况下,我们在 redis 中存储一个字符串,如:“big”,它的位图如下:

在这里插入图片描述

0.001kb = 1b = 8bit

所以,字符串“big”占3个字符,也就是24个bit位。

Redis 从 2.2.0 版本开始新增了 setbit,getbit,bitcount 等几个 bitmap 相关命令。虽然是新命令,但是并没有新增新的数据类型,因为 setbit 等命令只不过是在 set 上的扩展。

利用上述命令,Redis 可以操作二进制的位,可以取/改每一个位对应的值,简单写几个:

127.0.0.1:6379 > set hello big
"OK"
127.0.0.1:6379 > getbit hello 0
"0"
127.0.0.1:6379 > getbit hello 1
"1"
127.0.0.1:6379 > setbit hello 7 1
"0"
127.0.0.1:6379 > get hello
"cig"

通过上面的例子,我们可以发现:

  • getbit,setbit 可以对字符串进行位操作,可以获取/修改某位上的值;
  • 字符串的位修改以后,字符串本身也发生了根本变化,big -> cig。

BitMap 原本的含义是用一个 bit 位来进行0或者1的设置,映射某个元素的状态。

由于一个比特位只能表示 0 和 1 两种状态,也就是说一个 bit 能存储的最多信息量是 2,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间。

二、BitMap 相关命令

在 Redis 中,Bitmap 是一串连续的2进制数字(0或1),所以,可以把 Bitmaps 想象成一个以比特位为单位的数组,数组的每一位所在的位置为偏移(offset),数组的下标在 Bitmaps 中叫做偏移量,在 bitmap 上可执行AND,OR,XOR以及其它位操作。

# 设置值,其中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 中的 bit 位 是 字符串的映射,字符串在 value 中的存储是有上限的,所以 BitMap 的valu额存储空间可以用相同的方式计算。

Redis 中字符串的最大长度是 512M,所以 BitMap 的 offset (偏移量)最大值为:

512 * 1024 * 1024 * 8 = 2^32

四、使用场景

1. 用户签到

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

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

# 2021年第一天,用户Id = userId 的用户签到
setbit 2021:userId 1 1

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

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

假如:

  • 20220101 活跃用户情况是: [1,0,1,1,0]
  • 20220102 活跃用户情况是 :[ 1,1,0,1,0 ]

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

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

统计20220101 ~ 20220102 活跃过的用户总数:

bitop or dest2 20220101 20220102
# dest2 中值为1的offset,就是两天都活跃的用户的ID
bitcount dest2

3. 统计用户在线状态

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

# userId 登录,设置状态为1
setbit key userId 1
# 获取 userId 的状态:1 - 在线;0 - 不在线
getbit key userId

4. 实现布隆过滤器

布隆过滤器解决缓存穿透。

五、总结

  • bigmap 基于最小的单位bit进行存储,最大优势是非常省空间;
  • 设置时候时间复杂度O(1)、读取时候时间复杂度O(n),操作是非常快的;
  • 二进制数据的存储,进行相关计算的时候非常快,也能方便扩容;
  • 不要给一个很短的 bigmap 设置很长位的偏移量的值,这样有可能堵塞。

到此这篇关于关于Redis中bitmap的原理和使用详解的文章就介绍到这了,更多相关Redis的bitmap原理和使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

关于Redis中bitmap的原理和使用详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

关于Redis中bitmap的原理和使用详解

目录一、原理二、BitMap 相关命令三、BitMap 空间计算四、使用场景1. 用户签到2. 统计活跃用户(用户登陆情况)3. 统计用户在线状态4. 实现布隆过滤器五、总结一、原理先声明一下:Redis 有5种数据类型,而 BitMap
2023-05-16

详解Java中static关键字的使用和原理

static可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属于某个对象的。本文就来详细说说他的使用和原理,需要的可以参考一下
2022-11-13

关于@RequestBody和@RequestParam注解的使用详解

这篇文章主要介绍了关于@RequestBody和@RequestParam注解的使用详解,本文十分具有参考意义,希望可以帮助到你,如果有错误的地方还望不吝赐教
2023-03-24

详解Golang中Context的原理和使用技巧

GoContext原理和使用技巧GoContext用于传递请求级数据,提供上下文信息(如请求ID、超时、终止请求通道和值存储)。Context按照树形结构组织,父Context创建子Context并继承数据。Context可用于请求取消、超时和值存储。最佳实践包括创建特定于请求的Context、使用Context值存储、避免直接使用context.Background()以及使用context.Context接口。示例演示了如何使用Context进行请求取消,当请求在超时前被取消时,会输出“Request
详解Golang中Context的原理和使用技巧
2024-04-23

python 中 关于reverse() 和 reversed()的用法详解

这篇文章主要介绍了python 中 关于reverse() 和 reversed()的用法介绍,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-01-29

关于java中final关键字的使用方法详解

一、修饰类被final修饰的类不能被子类继承。//父类Animalpublic final class Animal{private int age; //年龄private String var; //品种 public void eat(){ Syst
关于java中final关键字的使用方法详解
2015-04-20

Java中ThreadLocal的用法和原理详解

这篇文章主要为大家详细介绍了Java中ThreadLocal的用法和原理,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的可以了解一下
2023-05-15

关于SpringBoot的异常回滚和事务的使用详解

这篇文章主要介绍了关于SpringBoot的异常回滚和事务的使用详解,Spring中@Transactional注解,默认情况下,只对抛出的RuntimeException异常,才会事务回滚,需要的朋友可以参考下
2023-05-19

RoaringBitmap原理及在Go中的使用详解

这篇文章主要为大家介绍了RoaringBitmap原理及在Go中的使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-28

编程热搜

目录