Skip to content

延迟队列

实现方式

ZSET方案

lua
-- 生产者:添加延迟任务
local delay = tonumber(ARGV[1])
local job_id = ARGV[2]
local score = os.time() + delay
redis.zadd("delay_queue", score, job_id)

-- 消费者:获取可执行任务
local jobs = redis.zrangebyscore("delay_queue", 0, os.time(), "LIMIT", 0, 10)
for _, job in ipairs(jobs) do
    -- 执行任务
    redis.zrem("delay_queue", job)
end

核心逻辑

  1. 添加任务:score设为未来某个时间戳
  2. 轮询获取:0点至当前时间戳的任务可执行
  3. 执行并删除:处理后从zset中移除

消息可靠性

1. 消费确认

lua
-- 取出任务后移到处理中队列
redis.zrem("delay_queue", job)
redis.zadd("processing_queue", os.time() + 300, job)  -- 5分钟超时

2. 失败重试

lua
-- 处理失败,重新入队
redis.zadd("delay_queue", os.time() + 60, job)  -- 1分钟后重试

3. 消息去重

lua
-- 使用唯一ID
local job_id = md5(message)
redis.setex("job:"..job_id..":processed", 3600, 1)

面试考点

Q: 为什么用ZSET?

  • score支持范围查询
  • 自动按时间排序
  • O(logN)添加和获取

Q: vs 其他MQ?

Redis延迟队列优点:简单、灵活 缺点:无ACK、无重试机制、无消息积压能力

最后更新: