主题
第七章:超时与竞争
本章导读
本章围绕“超时与竞争”展开,先交代适用场景,再说明核心原理,随后给出典型示例,最后补充小结与延伸阅读。
阅读顺序: 结论 → 原理 → 场景 → 代码 → 小结
Q19:BRPOP 超时和 LPUSH 同时发生会怎样?会不会出现"既收到 nil 又拿到元素"的情况?
答:
不会。超时检查和 LPUSH 都在主线程的事件循环中串行执行,不可能"同时"发生。
情况 A:LPUSH 先执行
1. LPUSH 执行,发现 W1 在等待链表
2. 把元素发给 W1
3. 移除 W1
4. W1 超时定时器还在,但 W1 已不在等待链表
5. 超时触发时发现 W1 不在链表 → 跳过
结果:W1 拿到元素 ✅情况 B:超时先执行
1. 超时触发,W1 从等待链表移除
2. 返回 nil 给 W1
3. LPUSH 执行,发现等待链表空(或只有 W2)
4. 元素留在列表中
结果:W1 收到 nil,元素留给下一个 BRPOP ✅两种情况都不会出现"W1 既收到 nil 又拿到元素"或"元素丢失"。超时处理不会被 LPUSH 打断,LPUSH 也不会被超时处理打断。
Q20:LPUSH + BRPOP 实现 FIFO 队列,那 LPUSH + LPOP 是什么模型?为什么本项目不用 LPUSH + LPOP?
答:
| 推入 | 弹出 | 组合 | 效果 |
|---|---|---|---|
| LPUSH | BRPOP/RPOP | 左推右弹 | FIFO(先进先出队列) |
| LPUSH | LPOP/BLPOP | 左推左弹 | LIFO(后进先出栈) |
| RPUSH | BLPOP/LPOP | 右推左弹 | FIFO(先进先出队列) |
| RPUSH | BRPOP/RPOP | 右推右弹 | LIFO(后进先出栈) |
本项目用 LPUSH + BRPOP = FIFO 队列:
LPUSH task:queue 6 ──► [6]
LPUSH task:queue 7 ──► [7, 6]
LPUSH task:queue 8 ──► [8, 7, 6]
BRPOP ──► 取出 6(最早推入)
[8, 7]
BRPOP ──► 取出 7
[8]
BRPOP ──► 取出 8
[]如果用 LPUSH + LPOP(LIFO 栈),后提交的任务会先被消费,先提交的任务可能长时间不被处理,不公平。