「Redis」BitMap 再絮叨

不积跬步,无以至千里;不积小流,无以成江海。

之前写过一篇关于 BitMap 的文章,写的并不通透,在大数据下 BitMap 优势还是显而易见的,所以决定重写,面试的时候你能掌握以下绝对是你的加分项。

在我们平时开发过程中,难免会有一些 <strong>bool 型 数据需要存取

比如以下场景:

  • 某个用户是否点赞过某篇文章
  • 某个用户今天是否登陆过
  • 某个用户的签到情况
  • 统计产品的月活
什么是 BitMap

位图 并不是特殊的数据结构,它的内容其实就是普通的字符串,也就是 <strong>byte数组,用二进制表示,只有 0 和 1

我们可以使用普通的 <strong>get/set 直接获取和设置 整个位图 的内容也可以使用位图操作 <strong>getbit/setbit 等将 <strong>byte 数组 看成<strong>「位数组」来处理。

如下:

「Redis」BitMap 再絮叨


用法


「Redis」BitMap 再絮叨

居然不支持 MarkDown, 只有截图上来了。

优势
  1. 基于最小的单位 bit 进行存储,节省空间。
  2. set 时间复杂度 O(1)、get 时间复杂度 O(n),操作是非常快的。
  3. 二进制数据的存储,进行相关计算的时候非常快。
  4. 自动扩容,如果设置了某个偏移位置超出了现有的内容范围,就会 自动 将位数组进行零扩充。
弊端
  1. redis中bit映射被限制在512MB之内,所以最大是2^32位,再大时需要分片存取。建议每个key的位数都进行控制,因为读取时候时间复杂度O(n),越大的串读的时间花销越多。
  2. offset 稀疏时不建议用,浪费大量内存
空间、时间粗略计算方式

在一台 2010MacBook Pro上,offset 为 2^32-1(分配512MB)需要~300ms,


offset为2^30-1(分配128MB)需要~80ms,


offset为2^28-1(分配32MB)需要~30ms,


offset为2^26-1(分配8MB)需要8ms。

大概的空间占用计算公式是:($offset/8/1024/1024)MB

使用场景
用户签到

记录用户每天签到情况,同时能快速知道用户某天是否签到

伪代码:


「Redis」BitMap 再絮叨


活跃用户

统计某段时间内的活跃用户 只需要一个key,然后用户id为偏移量offset,如果登陆过就设置为1,反之就设置为0,

伪代码:

「Redis」BitMap 再絮叨

视频属性的无限延伸

一个拥有亿级数据量的短视频app,视频存在各种属性(是否加锁、是否特效等等),需要做各种标记。数据量大又无限延伸, BitMap可能会达到瓶颈,我们考虑用分片来处理。

key:由属性id+视频分片id组成。value:按照视频id对分片 来决定偏移量offset


「Redis」BitMap 再絮叨


以上只是举了几个典型的例子,具体情况具体分析该如何设计key 和 offset。

避坑

bitcout bitpos 的 start end 都是 <strong>字节索引

有图有真相:


「Redis」BitMap 再絮叨


点关注 不迷路

以上就是这篇的全部内容,能看到这里的都是 <strong>人才。

如果你从本篇内容有收获,求 <strong>点赞,求 <strong>关注

,求 <strong>转发 ,让更多的人学习到。


如果本文有任何错误,请批评指教,不胜感激 !


分享到:


相關文章: