bitmap在redis中通过setbit命令存签到数据,以日期为key(如sign:20240410)、用户id映射的非负整数为offset、签到状态(0或1)为值;offset必须是紧凑唯一整数,禁用字符串或稀疏id以防错误或空间浪费;统计当日签到人数用bitcount key,亿级用户需按日分片、合理设置过期并避免单key过大。

BitMap在Redis里怎么存签到数据
直接用 SETBIT 存,用户ID作为偏移量(offset),当天是否签到为值(0 或 1)。比如用户ID为12345,今天是今年第100天,就执行:
SETBIT sign:20240410 12345 1。注意:
sign:20240410 是key,按日期分片;12345 是偏移量,不是用户ID字符串,必须转成整数且全局唯一、非负、尽量紧凑。
为什么不能直接用用户ID字符串当offset
因为 SETBIT 的 offset 参数只接受非负整数,最大支持约 2³²−1(约42亿),但必须是数字类型。如果用户ID是UUID或带字母的字符串,SETBIT 会报错 (error) ERR bit offset is not an integer or out of range。常见踩坑点:
- 用
hash(userId) % N做映射 → 可能冲突,导致A和B用户签到互相覆盖 - 用数据库自增ID直接当offset → 看似可行,但如果ID稀疏(比如删过大量用户),位图空间浪费严重,1亿用户实际占用可能远超12.5MB
- 没做ID归一化,不同业务线用户ID重复 → offset 冲突,签到状态错乱
如何统计某天有多少人签到
用 BITCOUNT 最直接:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
BITCOUNT sign:20240410。它返回该key下所有bit为1的数量,就是当日签到总人数。但要注意:
- 如果key不存在,
BITCOUNT返回0,不会报错,适合日常统计 - 不要对超大key(比如偏移量跨度几亿)频繁调用
BITCOUNT,虽然O(N)但N是内存中已分配的字节长度,不是逻辑用户数;若用户ID稀疏,Redis仍需扫描整个分配区域 - 想查「连续签到7天」?不能只靠单个key,得组合多个日期key用
BITOP AND,再BITCOUNT,但要注意key数量多时延迟上升
亿级用户下Key设计和内存控制的关键点
一个key存一天,比用一个key存所有日期更可控。否则单key位图过大(比如存365天 × 1亿用户 ≈ 4.5GB),不仅内存爆炸,BITCOUNT 和 BITOP 都变慢,且无法过期清理某天数据。
- key命名建议用
sign:{yyyymmdd},方便用SCAN批量清理过期key - 每天凌晨用
EXPIRE sign:20240409 2592000(30天)自动过期,避免手动删 - 如果用户量真到上亿,且ID不连续,可考虑分桶:比如按
userId % 100分100个子key,sign:20240410:00到sign:20240410:99,查总数时用BITOP OR合并再统计,平衡单key大小与操作复杂度
真正难的不是命令怎么写,而是ID映射策略和key生命周期管理——这两处出问题,后面所有统计都不可信。










