Bitmap 是什么
Bitmap 不是独立的数据类型,而是把 String 当成位数组使用:SETBIT 把指定偏移量的位设为 0 或 1,GETBIT 读取单个位,BITCOUNT 统计为 1 的位数。它适合「大量对象的两态标记」场景,例如签到、活跃、开关位,因为每个对象只占一位。一年 365 天的签到,用日期做偏移量只需约 46 字节,用用户 ID 做偏移量则内存取决于最大 ID。
基本信息
| 底层类型 | String,按位寻址,offset 从 0 开始 |
|---|---|
| 内存公式 | 总字节数约等于最大 offset 除以 8,向上取整 |
| 常用命令 | SETBIT / GETBIT / BITCOUNT / BITOP / BITPOS / BITFIELD |
| 统计范围 | BITCOUNT 可只统计指定 BYTE 或 BIT 区间 |
| 多键运算 | BITOP AND|OR|XOR|NOT 把多个位图合并到目标键 |
典型使用场景
- 连续签到统计:一个用户一条键,日期做偏移量,BITCOUNT 直接得月签到天数
- 日活留存分析:每天一个位图,BITOP AND 求多日连续活跃,OR 求周活跃
- 功能开关批量管理:按用户或设备编号标记是否开启某项实验能力
- 去重标记:对象 ID 范围密集且状态只有两种时,位图比 Set 省一个数量级内存
- 漏斗与留存报表的中间计算:把每日位图保留若干天后合并,避免每次重算
签到与活跃示例
签到与活跃示例
redis-cli SETBIT sign:20261012 10001 1 # 用户 10001 在当天签到
redis-cli GETBIT sign:20261012 10001 # 判断该用户是否签到
redis-cli BITCOUNT sign:20261012 # 当天签到总人数
redis-cli BITCOUNT sign:20261012 0 3 # 只统计前 4 个字节的范围
redis-cli BITOP AND active:week d:1 d:2 d:3 # 三天连续活跃的用户
redis-cli BITCOUNT active:week # 连续活跃人数
redis-cli BITPOS sign:20261012 0 # 第一个未签到用户的位偏移命令与适用面
| 命令 | 作用 | 注意点 |
|---|---|---|
| SETBIT | 设置某一位为 0 或 1 | offset 过大会一次性把键扩到对应长度 |
| GETBIT | 读取某一位 | 越界返回 0,不报错 |
| BITCOUNT | 统计为 1 的位数 | 支持按字节或位区间限定 |
| BITOP | 多键按位运算并写结果 | 目标键可以不是源键之一 |
| BITPOS | 查找第一个指定值的位 | 常用来找最早的未标记对象 |
稀疏位的代价:位图会按最大 offset 分配内存,如果用户 ID 是十几亿量级的稀疏编号,直接拿 ID 当 offset 会浪费巨量内存。工程上先做一层紧凑 ID 映射(编号从 0 递增),或改用 Hash 存活跃用户列表,按密度决定方案。
BITFIELD 可以把位图当作一组小整数使用,支持按指定宽度的有符号或无符号整数做自增与读写,适合在一段位里紧凑存放多个计数区间,避免为每个计数单独建键。