Skip to content

第六章:崩溃恢复与任务丢失 ​

本章导读 ​

本章围绕“崩溃恢复与任务丢失”展开,先交代适用场景,再说明核心原理,随后给出典型示例,最后补充小结与延伸阅读。

阅读顺序: 结论 → 原理 → 场景 → 代码 → 小结

Q17:Worker 从 BRPOP 取出任务后、执行前崩溃了,这个任务会怎样? ​

答:

任务会永久丢失。因为 BRPOP 是"弹出即删除",取出后任务已从 Redis 队列消失。

python
result = redis_client.brpop("task:queue", timeout=5)
_, task_id = result
# ← 如果 Worker 在这里崩溃,task_id 已从队列消失但未执行
run_task(int(task_id))

解决方案:RPOPLPUSH 模式,弹出时同时放入"处理中"队列:

python
# 弹出并转入"处理中"队列
task_id = redis_client.rpoplpush("task:queue", "task:processing")

# 处理完成后从"处理中"队列删除
redis_client.lrem("task:processing", 1, task_id)

# Worker 启动时扫描"处理中"队列,重新推回 task:queue
def recover_stuck_tasks():
    stuck = redis_client.lrange("task:processing", 0, -1)
    for task_id in stuck:
        redis_client.lpush("task:queue", task_id)
        redis_client.lrem("task:processing", 1, task_id)
参数类型说明
srcstr源队列名,从右端弹出
dststr目标队列名,推入左端
参数类型说明
keystr要操作的列表名
countint正数:从头部开始删 count 个;负数:从尾部开始删;0:删除全部匹配项
valuestr要删除的元素值

Q18:本项目如何监控队列积压?多少个任务算积压? ​

答:

用 LLEN 命令检查队列长度:

python
queue_len = redis_client.llen("task:queue")
if queue_len > 50:
    logger.warning("任务队列积压: %s 个待处理", queue_len)
积压数量严重程度说明
0-5正常Worker 能及时消费
5-20注意可能需要增加 Worker
20-50警告用户等待时间明显增加
50+严重需要立即增加 Worker 或检查是否有任务卡住

LLEN 的时间复杂度是 O(1),Redis 直接读取列表的长度字段,不遍历列表。