Appearance
延迟队列
实现方式
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核心逻辑
- 添加任务:score设为未来某个时间戳
- 轮询获取:0点至当前时间戳的任务可执行
- 执行并删除:处理后从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、无重试机制、无消息积压能力
