首页/数据/数据库速查/ZPOPMIN / ZPOPMAX 弹出极值(延时队列消费)
Redis 命令96 条

ZPOPMIN / ZPOPMAX 弹出极值(延时队列消费)

弹出分数最小/最大的成员(可选 count);是「到期任务」与「榜单淘汰」的原子消费方式。

数据库速查数据更新于 2026-10-13

弹出极值是什么

从有序集合中弹出分数最小或最大的成员,并把它从集合中移除,一次可弹多个。它是「到期任务消费」与「榜单淘汰」的原子操作:取走与删除在同一步完成,不会出现两个消费者拿到同一条任务的竞态。

基本信息

弹最小ZPOPMIN 键 [数量],按分数从小到大
弹最大ZPOPMAX 键 [数量],按分数从大到小
返回结构成员与分数交替出现的数组
阻塞版本BZPOPMIN 与 BZPOPMAX 在没有元素时等待指定秒数
版本要求弹出多个成员需 Redis 6.2 及以上

典型使用场景

  • 延时队列消费:分数存到期时间戳,到期时间最小的任务先被弹出执行
  • 榜单淘汰:分数最低的成员达到淘汰条件时批量弹出
  • 超时任务回收:把超时时间作为分数,定期弹出已超时的任务
  • 限时优惠到期:到点后批量弹出失效条目
  • 竞争消费:多个消费者同时弹出,天然不会重复取到同一条

示例

示例
ZADD delay:jobs 1700000001 job1 1700000002 job2
ZPOPMIN delay:jobs             # 弹出分数最小的 job1 及其分数
ZPOPMAX delay:jobs 2           # 一次弹出分数最大的两个成员
ZRANGE delay:jobs 0 -1 WITHSCORES   # 查看剩余成员
# 阻塞式消费:没有元素时最多等 5 秒
BZPOPMIN delay:jobs 5
# 只弹到期的任务(用 Lua 保证判断与弹出原子)
EVAL "local t = redis.call('ZRANGEBYSCORE', KEYS[1], '-inf', ARGV[1], 'LIMIT', 0, 1); if #t > 0 then redis.call('ZREM', KEYS[1], t[1]); return t[1] end; return false" 1 delay:jobs 1700000005

输出逐列读法

返回含义注意
成员与分数交替数组弹出的成员及其分数客户端解析时按两两一组处理
空数组集合为空或键不存在阻塞版本会转为等待
阻塞超时超时返回空值消费循环要处理这种情况并继续等待
延时队列的常见实现:分数存到期时间戳,弹出前先用区间查询确认分数已到期,再把判断与弹出合并到一个脚本里保证原子。
弹出即从集合移除:任务被弹出后处理失败就彻底丢失,关键任务需要额外保留副本或改用带确认机制的消息结构。

易错点

  • 弹出前不检查分数是否到期:尚未到期的任务被提前取走执行
  • 多消费者直接弹出不处理失败:任务弹出后处理异常即永久丢失
  • 用弹出命令替代可靠消费:没有确认与重试机制,不适合关键业务
  • 在低版本实例上使用带数量的弹出:参数不支持,直接报错

数据来源与参考

  • Redis 官方文档: ZPOPMIN
  • Redis 官方文档: BZPOPMIN

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌