【Redis系列8:Bitmap实现亿万级数据计算】Redis系列1:深刻理解高性能Redis的本质Redis系列2:数据持久化提高可用性Redis系列3:高可用之主从架构Redis系列4:高可用之Sentinel(哨兵模式)Redis系列5:深入分析Cluster 集群模式追求性能极致:Redis6.0的多线程模型追求性能极致:客户端缓存带来的革命
1 前言我们在第一篇 深刻理解高性能Redis的本质 的时候就介绍过Redis的几种基本数据结构,它是基于不同业务场景而设计的:
- 动态字符串(REDIS_STRING):整数(REDIS_ENCODING_INT)、字符串(REDIS_ENCODING_RAW)
- 双端列表(REDIS_ENCODING_LINKEDLIST)
- 压缩列表(REDIS_ENCODING_ZIPLIST)
- 跳跃表(REDIS_ENCODING_SKIPLIST)
- 哈希表(REDIS_HASH)
- 整数集合(REDIS_ENCODING_INTSET)
2 BitMap介绍BitMap (位图)的底层数据结构使用的是String类型的的 SDS 数据结构来保存 。因为一个字节8个bit位,为了有效的将字节的8个bit都利用到位,使用数组模式存储 。并且每个bit都使用二值状态表示,要么0,要么1 。所以,BitMap 是通过一个 bit 位来表示某个元素对应的值或者状态,它的结构如下,key 对应元素本身;offset即是偏移量,固定整型,一般存数组下表或者唯一值;value存储的是二值(要么0要么1),一般用来表示状态,如性别、是否登录、是否打卡等 。
文章插图
从上面可以看出这边使用一个字节表示1行,每1行存储8个bit,就是可以存储8个状态位,极大的提高了空间利用 。这也是BitMap的优势,我们可以使用很少的字节 , 存储大量的在线状态、打卡标记等状态信息 , 非常有效果 。
我们可以使用 setbit, getbit, bitcount 等几个相关命令来管理BitMap 。语法如下:
SETBIT key offset value
上面说过了 , key是元素名称,offset 必须是数值类型,value 只能是 0 或者 1,如果我们存储一个用户的在线状态,用户,代码如下://设置在线状态// $redis->setBit('online', $uid, 1);$redis->setBit('online', 5, 1);$redis->setBit('online', 9, 1);
则具体体现为:bytebit0bit1bit2bit3bit4bit5bit6bit7buf[0]00000100buf[1]01000000可以看出用户ID为5和9被打上1的标志,代表在线状态,其他未设置值默认为0,是离线状态 。除了Set之外,还有getBit、bitCount等语法,如下:
// 获取是否在线的状态$isOnline = $redis->getBit('online', $uid); // 获取在线人数 统计$onlineNum = $redis->bitCount('online');
3 BitMap的主要应用场景上面介绍了BitMap的原理和状态存储的优势 。那我们存储了bit位,其实目的还是为了高效的计算,而不是简单的状态记录 。而在实际的应用场景中 , 他主要解决如下几个类型的需求:3.1 状态统计上面其实我们已经演示过了,这种场景最常见,因为值只能是1或者0,所以所有的二值状态的,所有存在是否对照关系的场景都可以使用 。如在线(1) 离线(0),打卡(1) 未打卡(0),登录(1) 未登录(0),群聊消息已阅(1) 未阅(0) 等等 。我们以用户 离线/在线 为例子,看看如何使用 Bitmap 在海量的用户数据之中判断某个用户是否是在线状态 。假设我们使用一个
online_statu
来作为key,用来存储 用户登录后的状态集合,而用户的ID则为offset,online的状态就用1表示,offline的状态就用0表示 。- 如果1024用户登录系统,那么设置ID为1024的用户为在线的代码如下:
SETBIT online_statu 1024 1
- 如果想看1024的用户是否是在线状态(这边注意,key可能不存在,代表没有这个用户,这时候默认返回0),代码如下:
GETBIT online_statu 1024
- 如果1024的用户退出系统,则为他执行下线,代码如下:
SETBIT online_statu 1024 0
- 空间上的有效利用,1亿 人的状态存储只需要100000000/8/1024/1024 = 11.92 M,简单的数据结构也保证了性能上的优势 。
基于上面的讨论 , 我们可以总结出一个预评估公式 , 根据实际的数据量获取存储空间:( offset / 8 / 1024 / 1024 ) M
3.2 固定周期的签到情况统计(周/月/年)固定周期可能是年/月/周,按照不同维度,可能有 365,31,7的bit位的统计周期 。假设这时候我们如果对于某个用户(如1024)全年的签到情况做统计,可以这么设计:
推荐阅读
- .NET性能系列文章二:Newtonsoft.Json vs. System.Text.Json
- 五 Selenium4+Python3系列 - 多窗口处理之句柄切换
- 学习ASP.NET Core Blazor编程系列九——服务器端校验
- iQOO8Pro续航能力怎么样_iQOO8Pro续航实测
- 说说 Redis 事务
- 17 基于SqlSugar的开发框架循序渐进介绍-- 基于CSRedis实现缓存的处理
- JAVA系列之JVM内存调优
- 31 《吐血整理》高级系列教程-吃透Fiddler抓包教程-Fiddler如何抓取Android系统中Flutter应用程序的包
- iphone13系列电池容量_iphone13系列续航对比
- 元芳你怎么看怎么幽默回复(神回复系列搞笑评论)