Redis Bitmap 实现海量用户签到,核心是将“用户+日期”映射为 bit 位,1 表示已签到、0 表示未签到;采用按月分 key(如 sign:123456:202607)、offset=日期日-1 设计,避免大偏移与单 key 膨胀;支持签到、查询、月签到统计及连续签到位运算;亿级用户需分片(如 userId%10)与 TTL 自动清理,内存占用不足传统方案的 1/8。

用 Redis Bitmap 实现海量用户签到,核心是把“用户+日期”映射成一个 bit 位,1 表示当天已签到,0 表示未签到。它不存具体数据,只记“有或无”,内存极省、读写极快,适合亿级用户场景。
Key 和 offset 设计要合理
不能直接用用户 ID 当 offset(比如用户 ID 是 10000000000,偏移量太大浪费空间),也不能把所有用户塞进同一个 key(单 key 膨胀后 bitCount 变慢)。推荐分维度设计:
-
按月分 key:key 格式为
sign:{userId}:{yyyyMM},例如sign:123456:202607,表示用户 123456 在 2026 年 7 月的签到记录 - offset = 日期日 - 1:7 月 1 日 → offset 0,7 月 25 日 → offset 24(因为 offset 从 0 开始)
- 避免大 offset:单个 bitmap 最多用 31 位(对应一个月),不会撑爆内存,也规避了超长偏移导致的性能抖动
签到与查询用基础命令
Java 中通过 RedisTemplate 操作即可,无需额外依赖:
-
签到:
redisTemplate.opsForValue().setBit("sign:123456:202607", 24L, true)—— 设置第 25 天为已签 -
查是否签过:
redisTemplate.opsForValue().getBit("sign:123456:202607", 24L)返回 Boolean -
查当月总签到天数:
redisTemplate.execute((RedisCallback<long>) conn -> conn.bitCount("sign:123456:202607".getBytes()))</long>
连续签到和跨日统计靠位运算
单月内连续签到可用 BITPOS 查首个 0;跨多日(如连续 3 天)需合并多个 key:
立即学习“Java免费学习笔记(深入)”;
- 假设 key 分别为
sign:123456:20260701、sign:123456:20260702、sign:123456:20260703 - 用
BITOP AND resultKey key1 key2 key3得到三天都为 1 的用户集合 - 再对
resultKey执行bitCount,就是连续 3 天签到人数 - Java 中调用
redisTemplate.execute(RedisCallback)封装 BITOP 命令,或用 Lettuce/LettuceCluster 更易管理
亿级用户必须分片 + 过期控制
单实例扛不住 1 亿用户?得拆:
-
用户 ID 分片:取
userId % 10决定写入哪台 Redis,key 变为sign:shard{0-9}:{yyyyMM} - 自动清理离线状态:签到 key 设 TTL(如 90 天),避免历史数据堆积
- 聚合走定时任务:每 5 秒并行扫 10 个分片的 bitCount,汇总为 DAU;不用实时算,延迟可控且稳定
不复杂但容易忽略:offset 必须对齐日期逻辑、key 生命周期要配 TTL、分片后聚合不能漏片。做好这三点,千万级日活轻松支撑,内存占用不到传统方案的 1/8。


















