Redis 扩展模块 -- RedisRoaring 的安装方法
摘要
- 本文介绍 Redis 扩展模块 – RedisRoaring 的安装方法
- 本文基于
redis-7.4.7,springboot-3.5.8 - 操作系统:
Amazon Linux 2023(内核 6.1) - Redis官网:https://redis.io/
- Redis 命令文档:https://redis.io/docs/latest/commands/
RedisRoaring 简介
-
RedisRoaring是一个开源的 Redis 模块(Redis Module),由 Antonio Guilherme Ferreira Viggiano 维护,目的是将 Roaring Bitmap 数据结构原生集成到 Redis 中作为新的数据类型与命令集。
-
它基于 CRoaring 库实现压缩位图(Roaring Bitmap)功能,这是一种高效、压缩的位图数据结构,适合处理大规模整数集合。
-
兼容 Redis 6.0 及以上版本,在不同版本中对命令元数据、ACL 分类等功能有自动适配支持。
原生的redis bitmap有哪些问题?
-
结论先行:Redis 原生 Bitmap 的核心问题是「空间不可控 + 大规模位运算性能随最大偏移线性增长」,而 redis-roaring 通过 Roaring Bitmap 解决了稀疏数据内存浪费和大范围扫描效率问题。
-
Bitmap 是连续数组,不支持稀疏压缩, 其必须 从 0 到最大 bit offset 全部连续分配内存。你只要设置了 bit=1 的最大下标是 N,那么 Redis 至少要分配 N/8 字节内存。
-
假设你要存储用户ID集合,但是存储的ID范围较大,比如 1-2000000000,那么就会导致Bitmap的bit offset非常大,导致Bitmap的存储空间非常大。
-
另外如果数据比较稀疏,极端情况下只存储了2个ID,ID1:1,ID2:2000000000,那么Bitmap就要按照最大的 offset进行分配空间,导致Bitmap的存储空间非常大,但是中间的空间又被浪费了。
1 | SETBIT user:bitmap 1 1 |
Roaring Bitmap实现思路
-
将32位的int类型数据进行
高16位、低16位划分,高16位就被划分成2^16=65536个大桶(容器),低16位最多被划分成2^16=65536个小桶(元素) -
把要统计的数字拆分位高16位和低16位,高16位用作容器的索引、用于定位数字在哪个容器;低16位用作容器内元素的索引、用作定位数字在容器内的位置。
-
高16位和低16位的计算
1 | 公式:x = high * 2^16 + low |
-
容器有三种不同类型:
ArrayContainer、BitmapContainer和RunContainer,根据要统计的数字的数量和数字的连续性自动选择合适的容器。
| 类型 | 说明 |
|---|---|
| ArrayContainer | 稀疏(少量整数),元素为short类型的有序数组 最多存储 65536 个 short 元素,占用 128 KB 内存 |
| BitmapContainer | 密集 ,使用bitmap存储数据,固定占用 8kB 内存 |
| RunContainer | 连续区间,使用Run-Length Encoding方式压缩存储的元素,对连续数据的压缩效果特别好。 它的原理是,对于连续出现的数字,只记录初始数字和后续数量。即: 对于数据集:5,会压缩为5, 0 对于数据集:5, 6, 7, 8, 9, 10,会压缩为5, 5 对于数据集:5, 7, 9, 11, 12,会压缩为5, 0, 7, 0, 9, 0, 11, 1 最好情况:全部是连续数字,只会存储 2 个 short ,占用 4 bytes 最坏情况:0~65535的范围内填充所有的奇数位或偶数位,需要 65536 个short,占用 128 KB |
容器的使用及容器之间的转换
-
Roaring 的目标是:在保证操作性能的前提下,使内存占用最小。
-
因此:插入、删除、合并、运算后,会评估当前 container 的“最优类型”,必要时自动转换
-
✅ Array → Bitmap,触发条件:容器中元素数量 > 4096
1 | 原因: |
-
✅ Bitmap → Array,触发条件:容器中元素数量 <= 4096,一般在大量删除或 AND 运算后触发。
-
✅ RunContainer ↔ Array / Bitmap,Run 没有固定阈值,而是 动态评估内存模型,基于如下三个指标:
- run_count : 当前 RunContainer 中有多少个连续区间
1
2
3例如集合:{1,2,3,4,5, 10,11,12, 100}
连续区间:[1..5], [10..12], [100..100]
因此:run_count = 3
| run_count | 数据形态 | 适合 Run 吗 |
|---|---|---|
| 很小(1~几十) | 大段连续 | 极其适合 |
| 中等(几百) | 稍碎 | 可能适合 |
| 很大(上千) | 高度碎片化 | 不适合 |
-
run_total_coverage : run 覆盖的总元素数量(本质就是元素的数量)
1 | [1..5] → 5 个 |
| run_count | coverage | 平均长度 | 形态 | 适合 Run 吗 |
|---|---|---|---|---|
| 1 | 60,000 | 60,000 | 超长连续 | 极适合 |
| 10 | 50,000 | 5,000 | 大段连续 | 适合 |
| 5,000 | 50,000 | 10 | 碎片连续 | 非常不适合 |
-
estimated_memory : 估算内存占用,这是核心决策指标
1 | memory_run: 如果用 RunContainer,需要多少内存, ≈ run_count × RUN_ENTRY_SIZE(4 bytes) |
| 转换方向 | 触发条件 |
|---|---|
| Array → Bitmap | 元素数量 > 4096 |
| Bitmap → Array | 元素数量 ≤ 4096 |
| 任意 → Run | 连续区间压缩明显 |
| Run → Array / Bitmap | run 碎片化或内存劣化 |
| 批量运算 | 根据结果自动选择 |
| optimize | 强制重新评估 |
-
✅ 在 Roaring 的自动选择机制下,正常情况下单个 container 的内存占用会被控制在 ≈ 8KB 左右或更小,在“理论极限完全填满65535个 container”情况下,大约占 520 MB 内存(除了数据本身还有一些元数据)
| 项目 | 估算 |
|---|---|
| Bitmap 数据 | ~512 MB |
| Container 元数据 | ~4 MB |
| 索引结构 | ~1 MB |
| Redis Key 自身 | ~0.1 MB |
| 合计 | 约 517 MB |

-
直观对比表
| 维度 | Redis Bitmap | redis-roaring |
|---|---|---|
| 存储结构 | 连续 bit array | 压缩 bitmap(分块) |
| 稀疏数据内存 | 极差 | 极优 |
| 最大 offset | 越大内存越爆 | 几乎无影响 |
| BITCOUNT / BITOP | 扫描整个 bitmap | 只扫描有效 container |
| 扩容成本 | 可能大规模 realloc | 局部 container 扩展 |
| 单 bit 读写 | 极快 | 略慢(结构层) |
| 模块依赖 | 原生 | Redis Module |
| 运维复杂度 | 最低 | 稍高 |
RedisRoaring核心价值与优势
-
- 内存效率更高
- Roaring Bitmap 会根据数据稀疏/密集自动选择最优表示方式(数组、位图或运行长度编码),显著减少内存占用,相比传统 Redis Bitmap 在稀疏数据上能节省大量空间。
-
- 高性能位操作
- 对单个位的操作保持 O(1) 性能,与 Redis 原生位图操作一致。
- 对于大规模操作(例如 BITOP AND/OR/XOR)性能显著优于原生位图,某些操作可达到 8 倍性能提升。
-
- 结构丰富的命令集
- 除了传统位图命令之外,redis-roaring 提供更丰富的数据操作命令,支持批量和分析型用例。
安装 RedisRoaring
安装时需要科学上网,主要是安装依赖时需要从海外网下载,如果要部署在国内服务器,可能会连接失败。
可以在海外的相同配置的服务器上进行编译,之后将编译好的redistimeseries.so上传到国内服务器即可。
1 | mkdir -p /usr/local/soft/modules/ |
-
实际上
redis-roaring在构建后会在dist目录下生成好 Redis 相关命令和配置文件,如果没有安装Redis则可以直接使用。v1.7.1版本提供的Redis的版本为8.2.1,但此时是不带 Stack 相关模块的。
Redis 启用模块
-
将生成的
libredis-roaring.so拷贝到 redis 的 modules 目录下(非必须),目录不存在则创建
1 | # 注意 .so 文件需要包含可执行权限 |
-
本文采用
loadmodule加载模块
1 | # 将 libredis-roaring.so 添加到 redis.conf 中,需要重启 redis |