Redis BitMap 用户签到

Redis Bitmap
Bitmap(位图)是 Redis 提供的一种用于处理二进制位(bit)的特殊数据结构,它基于 String 类型,每个 bit 代表一个布尔值(0 或 1),可以用于存储大规模的二值状态数据,如签到、活跃用户统计、去重等。
1. Bitmap 基本原理
- Bitmap 本质上是一个二进制数组,每个 bit 仅占 1 位,相比普通的 String 存储方式(每个字符 8 位),能大幅节省空间。
- Redis 并没有单独的数据类型 Bitmap,它是基于
String结构的。 - 通过 位运算(
SETBIT、GETBIT、BITCOUNT、BITOP等)高效存取数据。
2. Bitmap 常用命令
(1)SETBIT:设置某一位的值
SETBIT key offset value
key:键名offset:bit 偏移量(从 0 开始)value:0或1
📌 示例
SETBIT user:1001 1 1 # 将 user:1001 的第 1 位设置为 1
SETBIT user:1001 2 0 # 将 user:1001 的第 2 位设置为 0
SETBIT user:1001 5 1 # 将 user:1001 的第 5 位设置为 1
假设 user:1001 初始状态是:(每个 0 代表 1 bit,总共 32 bit = 4 字节)
00000000 00000000 00000000 00000000
执行:
SETBIT user:1001 5 1 # 将 user:1001 的第 5 位设置为 1
SETBIT user:1001 5 1
结果变成:
00000100 00000000 00000000 00000000
第 5 位(从 0 开始计数,即第 6 个 bit)被设置为 1。
作用:类似于一个布尔数组,可用于表示某个用户在不同时间点的状态(如签到)。
(2)GETBIT:获取某一位的值
GETBIT key offset
key:键名offset:bit 偏移量
📌 示例
GETBIT user:1001 1 # 返回 1
GETBIT user:1001 2 # 返回 0
GETBIT user:1001 5 # 返回 1
作用:查询某个状态,如某用户是否签到。
(3)BITCOUNT:统计 bit 为 1 的个数
BITCOUNT key [start end]
key:键名[start end](可选):字节范围(默认统计整个 key)
📌 示例
BITCOUNT user:1001 # 统计 user:1001 中 bit 为 1 的个数
作用:
- 统计某个用户的签到次数
- 统计一段时间内活跃用户数量
(4)BITOP:对多个 Bitmap 进行位运算
BITOP operation destKey key1 key2 ...
operation:AND(与)OR(或)XOR(异或)NOT(非)
destKey:存储结果的 keykey1 key2 ...:参与运算的 key
📌 示例
BITOP AND active_users today yesterday # 统计连续两天都活跃的用户
BITOP OR total_active day1 day2 day3 # 统计三天内活跃过的用户
作用:
- 计算多天签到的交集、并集
- 统计活跃用户
3. Bitmap 典型应用
(1)用户签到
场景:每个用户有一个 31 位的 Bitmap(对应 31 天),bit 为 1 表示已签到,0 表示未签到。
📌 示例
SETBIT sign:1001:20240301 0 1 # 用户 1001 在 3 月 1 日签到
SETBIT sign:1001:20240302 1 1 # 3 月 2 日签到
SETBIT sign:1001:20240303 2 1 # 3 月 3 日签到
GETBIT sign:1001:20240303 2 # 查询 3 月 3 日是否签到(返回 1)
BITCOUNT sign:1001:202403 # 查询用户 1001 3 月签到次数
(2)统计活跃用户
场景:每天创建一个 Bitmap,记录活跃用户(bit 位置对应用户 ID)。
📌 示例
SETBIT active:20240301 1001 1 # 用户 1001 3 月 1 日活跃
SETBIT active:20240301 1002 1 # 用户 1002 3 月 1 日活跃
SETBIT active:20240302 1002 1 # 用户 1002 3 月 2 日活跃
BITCOUNT active:20240301 # 统计 3 月 1 日活跃用户数
BITOP AND active_both active:20240301 active:20240302 # 统计连续两天活跃的用户
(3)A/B 测试 & 用户权限控制
场景:用 Bitmap 存储用户是否属于 A/B 测试组或是否拥有某个权限。
📌 示例
SETBIT experiment:groupA 1001 1 # 用户 1001 参与 A 组测试
SETBIT experiment:groupB 1002 1 # 用户 1002 参与 B 组测试
GETBIT experiment:groupA 1001 # 查询用户 1001 是否在 A 组
4. Bitmap 优势
✅ 节省空间:1 个 bit 仅占 1/8 字节,非常适合存储大规模用户数据(如千万级别用户签到情况)。
✅ 高效查询:GETBIT 和 SETBIT 操作时间复杂度为 O(1),快速读写。
✅ 支持批量运算:BITCOUNT、BITOP 等可进行高效统计。
5. Bitmap 限制
❌ 不支持删除某个 bit(只能置 0,无法真正删除)。
❌ 不支持范围查询(需要配合 BITCOUNT 和 GETBIT)。
❌ 偏移量有限制(Redis 最大 String 长度约 512MB,即支持 2^32 个 bit)。
6. 总结
| 功能 | 命令 | 作用 |
|---|---|---|
| 设置 bit | SETBIT key offset value | 设置指定偏移量的 bit |
| 获取 bit | GETBIT key offset | 获取指定偏移量的 bit |
| 统计 1 的数量 | BITCOUNT key | 统计 key 中 bit 为 1 的个数 |
| 位运算 | BITOP operation destKey key1 key2 | 对多个 Bitmap 进行 AND/OR/XOR/NOT 运算 |
Bitmap 非常适合用于海量用户数据的布尔状态存储,如签到、活跃用户、权限控制等场景。
参考文献
[1] https://redis.io/docs/latest/develop/data-types/bitmaps/
