欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > 基于redis的位图实现签到功能

基于redis的位图实现签到功能

2025/3/10 9:57:29 来源:https://blog.csdn.net/qq_63358493/article/details/145954722  浏览:    关键词:基于redis的位图实现签到功能

基于Redis位图实现签到功能是一种高效且节省内存的方法。以下是分步实现的详细方案:

1. 键设计策略

采用 sign:<userId>:<YYYYMM> 格式存储每月签到数据

# 示例:用户1001在2023年8月的签到数据
sign_key = "sign:1001:202308"

2. 核心操作实现

2.1 用户签到
# 命令格式
SETBIT key offset 1# 示例:8月3日签到(偏移量从0开始计算)
SETBIT sign:1001:202308 2 1
# Python伪代码
def sign(user_id):today = datetime.now()offset = today.day - 1  # 日期转0-based偏移量key = f"sign:{user_id}:{today.strftime('%Y%m')}"redis.setbit(key, offset, 1)
2.2 查询签到状态
# 命令格式
GETBIT key offset# 示例:查询8月3日是否签到
GETBIT sign:1001:202308 2
def check_sign(user_id, date):offset = date.day - 1key = f"sign:{user_id}:{date.strftime('%Y%m')}"return redis.getbit(key, offset)
2.3 统计当月签到次数
# 命令格式
BITCOUNT key# 示例:统计8月总签到次数
BITCOUNT sign:1001:202308
2.4 获取连续签到天数
def get_continuous_days(user_id):today = datetime.now()key = f"sign:{user_id}:{today.strftime('%Y%m')}"max_offset = today.day - 1consecutive = 0for offset in range(max_offset, -1, -1):if redis.getbit(key, offset):consecutive += 1else:break# 检查跨月情况if consecutive == today.day:last_day = today - timedelta(days=today.day)prev_key = f"sign:{user_id}:{last_day.strftime('%Y%m')}"prev_bits = redis.bitcount(prev_key)if prev_bits == last_day.day:consecutive += prev_bitsreturn consecutive

3. 高级功能扩展

3.1 签到日历生成
def get_sign_calendar(user_id, year_month):key = f"sign:{user_id}:{year_month}"value = redis.get(key) or b'\x00'# 将二进制数据转换为位列表bits = bin(int.from_bytes(value, byteorder='big'))[2:]return [bool(int(bit)) for bit in bits.zfill(32)]  # 最多显示31天
3.2 月度统计报告
# 获取当月首次签到日期
BITPOS key 1# 获取当月最后签到日期
BITPOS key 1 -1

4. 性能优化步骤

  1. 数据分片:对活跃用户使用多个位图分段存储
  2. 缓存策略:对频繁访问的统计结果进行短期缓存
  3. 异步处理:非实时统计任务使用后台进程处理
  4. 数据归档:定期将历史数据转存到持久化存储

5. 异常处理机制

  1. 日期有效性验证:
def validate_date(year, month, day):try:datetime(year, month, day)return Trueexcept ValueError:return False
  1. 偏移量范围检查:
max_day = calendar.monthrange(year, month)[1]
if offset >= max_day:raise InvalidOffsetError("超出当月天数范围")

6. 数据可视化示例

生成签到日历JSON:

{"202308": {"total": 18,"continuous": 5,"calendar": [{"day": 1, "signed": true},{"day": 2, "signed": false},...]}
}

7. 内存使用估算

假设:

  • 每月最大31天
  • 每个用户每月占用4字节(31位)
  • 10万活跃用户

总内存消耗:100,000用户 × 12月 × 4字节 ≈ 4.8MB

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词