java中用redis zset实现排行榜和延时队列,核心是分别以业务分数和时间戳为score;推荐spring data redis(lettuce),支持响应式与同步操作。

Java 中使用 Redis 的 ZSet 实现排行榜和延时队列,核心在于合理利用 ZSet 的 score 排序能力:排行榜用业务热度/分数作 score,延时队列则用时间戳(毫秒)作 score。推荐使用 Spring Data Redis(基于 Lettuce 客户端),简洁稳定,支持响应式与同步操作。
排行榜:按分数动态排序 + 分页查询
ZSet 天然适合实时排行榜——插入、更新、查 TopN、查排名、查某用户名次等操作都是 O(log N) 时间复杂度。
-
存入用户分数:用用户 ID 作 member,score 为积分/热度值
// 示例:用户 u1001 当前积分 8520redisTemplate.opsForZSet().add("rank:score", "u1001", 8520.0); -
获取 Top 10(降序):
ZREVRANGE rank:score 0 9 WITHSCORESSet<zsetoperations.typedtuple>> top10 = redisTemplate.opsForZSet().reverseRangeWithScores("rank:score", 0, 9);</zsetoperations.typedtuple> -
查询某用户排名(从 1 开始):
ZREVRANKLong rank = redisTemplate.opsForZSet().reverseRank("rank:score", "u1001"); // 返回 0 表示第 1 名
// 注意:reverseRank 返回的是 0-based 索引,+1 即真实名次 - 更新分数并自动重排序:再次 add 同一个 member 会覆盖旧 score,无需手动删除
-
分页查区间(如第 21~30 名):
reverseRangeWithScores("rank:score", 20, 29)
延时队列:用时间戳当 score,轮询拉取到期任务
ZSet 不是原生延时队列,但可模拟轻量级方案:把任务内容序列化为 member,score 设为执行时间戳(毫秒)。消费者定时用 ZRANGEBYSCORE 拉取已到期任务。
-
添加延时任务(例如 30 秒后执行):
long delayMs = System.currentTimeMillis() + 30_000;redisTemplate.opsForZSet().add("delay:queue", JSON.toJSONString(task), (double) delayMs); -
拉取所有已到期任务(原子性取出并删除):
使用 Lua 脚本保证「查 + 删」原子性(避免多实例重复消费):
// Lua 脚本示例(传入 key 和当前时间戳)EVAL "local tasks = redis.call('zrangebyscore', KEYS[1], '-inf', ARGV[1]); redis.call('zremrangebyscore', KEYS[1], '-inf', ARGV[1]); return tasks" 1 delay:queue 1717023456789
Spring 中可用redisTemplate.execute()执行该脚本。 -
消费者轮询建议**:
• 初始延迟 100ms,无任务时指数退避(如最多 1s)
• 避免高频空轮询(如每 5ms 查一次)
• 任务处理失败应记录日志,并考虑是否重放(ZSet 本身不提供重试机制)
注意事项与优化点
-
score 精度问题:若同一时刻多个任务,score 相同会导致顺序不确定;可在时间戳后拼随机数或序列号(如
timestamp + "." + seq),转 double 时注意科学计数法丢失精度 → 改用String类型 +ZRANGEBYLEX,或直接用long时间戳(毫秒足够区分常规业务) -
内存控制:过期任务要及时清理;可定期用
ZREMRANGEBYSCORE key -inf (now-3600000)删除 1 小时前的已处理/过期任务(加括号表示开区间) -
分布式安全:延时队列多实例消费时,必须用 Lua 或 Redisson 的
RDelayedQueue保证取任务原子性;纯 ZSet + 应用层判断易丢任务或重复执行 - 替代方案参考:高可靠场景建议用专业工具(如 RabbitMQ 延迟插件、Apache RocketMQ 的定时消息、Redis Streams + consumer group),ZSet 更适合低延迟、中低并发、允许少量误差的内部服务
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











