Redis 10亿数据量只需要100MB内存,为什么这么牛?

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: reids位操作也叫位数组操作、bitmap,它提供了SETBIT、GETBIT、BITCOUNT、BITTOP四个命令用于操作二进制位数组。

云栖号资讯:【点击查看更多行业资讯
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!

18E8FB20_DA0D_4339_8B94_D61CAB05E79B

本文主要和大家分享一下redis的高级特性:bit位操作。
本文redis试验代码基于如下环境:
操作系统:Mac OS 64位
版本:Redis 5.0.7 64 bit
运行模式:standalone mode

redis位操作

reids位操作也叫位数组操作、bitmap,它提供了SETBIT、GETBIT、BITCOUNT、BITTOP四个命令用于操作二进制位数组。
先来看一波基本操作示例:

53E82AB5_969E_4691_A800_EAE0D2C8E322

SETBIT
语法:SETBIT key offset value
即:命令 key 偏移量 0/1
setbit命令用于写入位数组指定偏移量的二进制位设置值,偏移量从0开始计数,且只允许写入1或者0,如果写入非0和1的值则写入失败:

83EBFDD2_CC9C_48c0_A395_EC896B37080D

GETBIT
语法:GETBIT key offset
即:命令 key 偏移量
gitbit命令用于获取位数组指定偏移量上的二进制值:

81D83EB5_6100_4d4a_8BEB_6BD84A79933E

BITCOUNT
语法:BITCOUNT key
即:命令 key
bitcount命令用于获取指定key的位数组中值为1的二进制位的数量,之前我们写入了偏移量0的值为1,偏移量10 的值为1,偏移量8的值为0:
9A12B771_62E4_4379_9D74_948CAF658B80

BITOP
语法:BITOP operation destkey key [key...]
即:命令 操作 结果目标key key1 key2 ...
bitop命令可以对多个位数组的key进行and(按位与)、or(按位或)、xor(按位异或)运算,并将运算结果设置到destkey中:

27F14137_C72B_4d01_B15A_23F124266066

底层数据结构分析

SDS是redis中的一种数据结构,叫做简单动态字符串(Simple Dynamic String),并且它是一种二进制安全的,在大多数的情况下redis中的字符串都用SDS来存储。
SDS的数据结构:

AD171A22_2E7A_4909_B806_600736A70355

SDS的优点:
1.时间复杂度为O(1)
2.杜绝缓冲区溢出
3.减少修改字符串长度时候所需的内存重分配次数
4.二进制安全的API操作
5.兼容部分C字符串函数

redis中的位数组采用的是String字符串数据格式来存储,而字符串对象使用的正是上文说的SDS简单动态字符串数据结构。

8C0FBEDE_D32F_47d3_82C0_381C943C3CCF

大家都知道的是一个字节用的是8个二进制位来存储的,也就是8个0或者1,即一个字节可以存储十进制0~127的数字,也即包含了所有的数字、英文大小写字母以及标点符号。

1Byte=8bit
1KB=1024Byte
1MB=1024KB
1GB=1024MB

387D0ED2_0106_4df2_9236_170D1D66A706

时间复杂度

GETBIT命令时间复杂度O(1)
STEBIT命令时间复杂度O(1)
BITCOUNT命令时间复杂度O(n)
BITOP命令时间复杂度O(n)、O(n2)
我们来看GETBIT以及SETBIT命令的时间复杂度为什么是O(1),当我们执行一个SETBIT key 10086 1的值的时候,reids的计算方式如下:
获取到要写入位数组中的哪个字节:10086÷8=1260,需要写入到位数组的下标1260的字节
获取要写入到这个字节的第几位:10086 mod 8 = 6,需要写入到这个字节的下标为6即第7位上去。
通过这两种计算方式大家可以清晰的看到,位操作的GETBIT和SETBIT都是常量计算,因此它的时间复杂度为O(1)。
而BITCOUNT命令需要对整个位数组的所有元素进行遍历算出值为1的有多少个,当然redis对于大数据了的bit执行bitcount命令会有一整套复杂的优化的算法,但是核心思路还是这个意思,无非是减少部分遍历查询次数。比如以128位为一次遍历,那么他的遍历次数就是所有的位数除以128。
BITTOP命令则是根据不同的操作有不同的执行方式。比如AND操作,则需要查看位值为1的即可。

存储空间计算

根据上面的介绍,相信大家已经知道了基于redis的位数组数据结构存储的数据占用内存大小是怎么计算的了。比如有100亿的数据,那么它需要的字节数组:
1000000000÷8÷1024÷1024≈119.21MB
也就是存储10亿的数据只需要119MB左右的内存空间,这对于现在动辄16G、32G集群版的redis,完全没有问题。
需要注意的是,如果你的数据量不大,那就不要把起始偏移量搞的很大,这样也是占空间的,比如我们只需要存储几百条数据,但是其中的偏移量却很大,这就会造成了很大的内存空间浪费。

应用场景

实际项目开发中有很多业务都适合采用redis的bit来实现。
用户签到场景
每天的日期字符串作为一个key,用户Id作为offset,统计每天用户的签到情况,总的用户签到数
活跃用户数统计
用户日活、月活、留存率等均可以用redis位数组来存储,还是以每天的日期作为key,用户活跃了就写入offset为用户id的位值1。
同理月活也是如此。
用户是否在线以及总在线人数统计
同样是使用一个位数组,用户的id映射偏移量,在线标识为1,下线标识为0。即可实现用户上下线查询和总在线人数的统计
APP内用户的全局消息提示小红点
现在大多数的APP里都有站内信的功能,当有消息的时候,则提示一个小红点,代表用户有新的消息。

【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.aliyun.com/zhibo

立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK

原文发布时间:2020-04-24
本文作者:互联网架构师
本文来自:“互联网架构师 微信公众号”,了解相关信息可以关注“互联网架构师

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
16天前
|
监控 算法 应用服务中间件
“四两拨千斤” —— 1.2MB 数据如何吃掉 10GB 内存
一个特殊请求引发服务器内存用量暴涨进而导致进程 OOM 的惨案。
|
22天前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万数据量的优化实录
【10月更文挑战第6天】 在现代互联网应用中,随着用户量的增加和业务逻辑的复杂化,数据量级迅速增长,这对后端数据库系统提出了严峻的挑战。尤其是当数据量达到百万级别时,传统的数据库解决方案往往会遇到性能瓶颈。本文将分享一次使用MySQL与Redis协同优化大规模数据统计的实战经验。
90 3
|
23天前
|
存储 缓存 NoSQL
Redis Quicklist 竟让内存占用狂降50%?
【10月更文挑战第11天】
39 2
|
2月前
|
缓存 监控 NoSQL
阿里面试让聊一聊Redis 的内存淘汰(驱逐)策略
大家好,我是 V 哥。粉丝小 A 面试阿里时被问到 Redis 的内存淘汰策略问题,特此整理了一份详细笔记供参考。Redis 的内存淘汰策略决定了在内存达到上限时如何移除数据。希望这份笔记对你有所帮助!欢迎关注“威哥爱编程”,一起学习与成长。
|
2月前
|
NoSQL 关系型数据库 MySQL
当Redis与MySQL数据一致性校验中Redis数据量小于MySQL时的全量查询处理方法
保持Redis和MySQL之间的数据一致性是一个需要细致规划和持续维护的过程。通过全量数据同步、建立增量更新机制,以及定期执行数据一致性校验,可以有效地管理和维护两者之间的数据一致性。此外,利用现代化的数据同步工具可以进一步提高效率和可靠性。
55 6
|
2月前
|
存储 Prometheus NoSQL
Redis 内存突增时,如何定量分析其内存使用情况
【9月更文挑战第21天】当Redis内存突增时,可采用多种方法分析内存使用情况:1)使用`INFO memory`命令查看详细内存信息;2)借助`redis-cli --bigkeys`和RMA工具定位大键;3)利用Prometheus和Grafana监控内存变化;4)优化数据类型和存储结构;5)检查并调整内存碎片率。通过这些方法,可有效定位并解决内存问题,保障Redis稳定运行。
|
3月前
|
存储 NoSQL 算法
Redis内存回收
Redis 基于内存存储,性能卓越,但单节点内存不宜过大,以免影响持久化或主从同步。可通过配置 `maxmemory` 限制最大内存。内存达到上限时,Redis采用两种策略:内存过期策略和内存淘汰策略。过期策略包括惰性删除和周期删除,后者分为 SLOW 和 FAST 模式。内存淘汰策略有八种,如 LRU、LFU 和随机淘汰等,用于在内存不足时释放空间。官方推荐使用 LFU 算法。
Redis内存回收
|
2月前
|
缓存 NoSQL 算法
14)Redis 在内存用完时会怎么办?如何处理已过期的数据?
14)Redis 在内存用完时会怎么办?如何处理已过期的数据?
55 0
|
2月前
|
存储 缓存 NoSQL
Redis 过期删除策略与内存淘汰策略的区别及常用命令解析
Redis 过期删除策略与内存淘汰策略的区别及常用命令解析
68 0
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
339 0
下一篇
无影云桌面