You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多时间区间事件计数Leaderboard构建咨询:Redis方案是否最优?

多时间窗口事件排行榜最优实现方案

核心思路:时间分片Sorted Set + 按需合并查询

针对不同时间窗口,采用匹配窗口粒度的分片策略维护Sorted Set,既避免单键数据过大,又减少键的数量,同时兼顾统计效率和查询性能。

1. 分片规则设计

每个时间窗口对应一组分片Sorted Set,分片粒度与窗口大小匹配,避免不必要的细粒度键:

  • 1min窗口:按1分钟分片,键名格式leaderboard:1min:yyyyMMddHHmm(如leaderboard:1min:202405201435)
  • 5min窗口:按5分钟分片,键名格式leaderboard:5min:yyyyMMddHHmm(取整到最近5分钟,如14:33对应14:30)
  • 15min/30min/60min窗口同理,分片粒度分别设为15/30/60分钟

2. 事件统计操作

当事件触发时,计算当前时间对应的各窗口分片键,执行ZINCRBY累加事件次数:

# 示例:当前时间2024-05-20 14:35:20,事件为eventA
ZINCRBY leaderboard:1min:202405201435 1 eventA
ZINCRBY leaderboard:5min:202405201430 1 eventA
ZINCRBY leaderboard:15min:202405201430 1 eventA
ZINCRBY leaderboard:30min:202405201430 1 eventA
ZINCRBY leaderboard:60min:202405201400 1 eventA

3. Top10查询操作

查询某窗口的Top10时,先找出该窗口内所有未过期的分片键,用ZUNIONSTORE合并为临时键,再取Top10,最后删除临时键:

# 示例:查询60min窗口Top10,当前时间14:35,合并最近12个5min分片(覆盖60分钟范围)
ZUNIONSTORE temp_leaderboard_60min 12 leaderboard:5min:202405201330 leaderboard:5min:202405201335 ... leaderboard:5min:202405201430
# 获取Top10及对应次数
ZREVRANGE temp_leaderboard_60min 0 9 WITHSCORES
# 清理临时键
DEL temp_leaderboard_60min

4. 过期分片清理

给每个分片键设置EXPIRE过期时间,比如1min分片设为2分钟过期,5min分片设为10分钟过期,60min分片设为70分钟过期,让Redis自动清理过期数据,无需额外定时任务。


替代方案:单Sorted Set + 滑动窗口过滤(低并发场景适用)

如果并发量不高,可给每个时间窗口维护一个单Sorted Set,元素score为事件触发时间戳,同时用Hash记录事件累计次数:

  • 事件触发时:
    HINCRBY event_counts eventA 1
    ZADD leaderboard:60min current_timestamp eventA
    
  • 查询Top10时:
    # 过滤60分钟外的过期事件
    ZREMRANGEBYSCORE leaderboard:60min -inf (current_timestamp - 3600)
    # 结合Hash的次数排序取Top10(需业务层二次排序,效率略低)
    

这种方案键数量少,但高并发下频繁过滤过期数据会阻塞Redis,仅适合小流量场景。


方案对比与选择

  • 分片方案:适合高并发场景,查询性能稳定,键数量可控,清理逻辑简单,是当前需求的最优选择。
  • 单键方案:适合低并发、快速实现的场景,缺点是高并发下性能瓶颈明显。

内容的提问来源于stack exchange,提问作者rtuna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 14:18:15