主题
第六章:崩溃恢复与任务丢失
本章导读
本章围绕“崩溃恢复与任务丢失”展开,先交代适用场景,再说明核心原理,随后给出典型示例,最后补充小结与延伸阅读。
阅读顺序: 结论 → 原理 → 场景 → 代码 → 小结
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)| 参数 | 类型 | 说明 |
|---|---|---|
src | str | 源队列名,从右端弹出 |
dst | str | 目标队列名,推入左端 |
| 参数 | 类型 | 说明 |
|---|---|---|
key | str | 要操作的列表名 |
count | int | 正数:从头部开始删 count 个;负数:从尾部开始删;0:删除全部匹配项 |
value | str | 要删除的元素值 |
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 直接读取列表的长度字段,不遍历列表。