每位代表一天,每个用户每月仅占约4字节;采用按月分key的位图设计,如sign:202605:10086,offset从0开始对应当月第几天,配合setbit、getbit、bitcount等o(1)命令实现高效签到与统计。

用位图(Bitmap)压缩亿级用户签到状态,核心就一句话:**每位代表一天,每个用户每月只占约4字节**。不存记录、不建索引、不走SQL,靠一个bit直接映射“签没签”,1亿用户一个月的数据仅需约12.5MB内存。
按月分Key,避免单Key膨胀
不能把所有用户塞进同一个key,否则会拖慢响应、难以清理、还可能触发Redis单key限制。推荐key格式:sign:{YYYYMM}:{user_id},比如 sign:202605:10086 表示用户10086在2026年5月的签到位图。
- 每月独立key,天然支持TTL自动过期或定时删除
- 写入、查询、统计都限定在单月范围内,无跨月干扰
- 运维友好:可按月归档、迁移或冷备
偏移量用“当月第几天−1”
5月1日对应offset=0,5月23日对应offset=22——从0开始计数,完全对齐数组逻辑,也和Redis命令行为一致。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 无需维护全局日期映射表,计算简单、无误差
- 31天最多占31位(4字节),哪怕闰年2月也只需29位
- 客户端可直接算出offset,不依赖服务端查表
高频操作全靠原生命令,O(1)完成
签到、查询、统计都不需要遍历或聚合,全由Redis底层位运算秒级响应:
- SETBIT sign:202605:10086 22 1 —— 用户当天签到,幂等安全,重复执行无副作用
- GETBIT sign:202605:10086 22 —— 判断是否已签,毫秒返回布尔值
- BITCOUNT sign:202605:10086 —— 统计本月签了多少天,结果直接给出
- BITPOS sign:202605:10086 0 —— 找第一个未签日,适合判断连续奖励资格
复杂逻辑也能拆解到位操作
连续签到这类需求,不用扫库、不查历史记录,靠位移+与运算就能搞定:
- 用 BITFIELD sign:202605:10086 GET u31 0 一次性读出整月31位状态
- 要查是否连续7天,就构造掩码
0x7F(二进制1111111),左移到起始日位置 - 再用 & 运算,结果等于掩码即表示达标
- 也可用Lua脚本封装,一次网络往返完成全部逻辑
不复杂但容易忽略。










