LabHub
学习 学习路径 课程

队列与异步 API

队列是一件用来买时间的工具

在 LabHub 中继续学习

一句话总结

Q不会提高处理速度。将接收请求的速度和处理速度分开, 瞬间狂奔被吸收为时间。

概念图: 接受延迟,享受可用性。 · 平均流入量大于平均处理能力的情况 · 如果λ > μ持续的话,需要的不是队列,而是增加工作者或限制流入。 · 非线性地爆炸

为什么需要这个?

假设有图像上传API。保存原件,制作三个缩略图, 提取元数据,放入搜索索引中。全部以动机为前提的话,需要4秒钟才能回复。 平时可以忍受。但是促销日上传量增加一倍的话,4秒的请求 积攒了十倍,步行线程全部被绑定,甚至连健康检查都失败了。

插入队列后,API只会保存原始数据,并回复“已接收”。200ms。其余的 Worker以自己的速度处理。即使发生暴涨,API也会继续以200ms的响应速度,只有队列深度 会增加。增加的深度会导致处理延迟——原本需要4秒的时间可能需要3分钟。 有。但系统不会死。

这次交换就是全部。接受延迟,享受可用性。

稳定条件只有一个不等式

有三个条件可以使用队列。第一,工作不需要立即结束吗?第二,请求 速度是否可以比处理速度瞬间更快。第三,失败时以后再 可以做吗?如果三个都对,那么Q就对了。

相反,也有明确的应该不插入队列的情况。用户必须立即看到结果的查询, 而且平均流入量大于平均处理能力的情况。误解后者的人 很多。Q可以吸收冲击,但无法解决慢性过度负荷。

λ = 초당 유입 건수      μ = 워커 하나의 초당 처리 건수 × 워커 수

λ < μ  →  큐 깊이가 0 근처로 돌아온다 (안정)
λ = μ  →  깊이가 무작위로 떠돈다 (경계 — 운영하면 안 되는 지점)
λ > μ  →  깊이가 선형으로 자란다 (터진다)

从数字上看很清楚。μ = 100/s,λ平时是60/s,30分钟内变为90/s。 如果是的话,在这个区间中每秒消失的余地是10个。30分钟的话,剩下的队列是 没有,而且很容易吸收。但是λ上升到110/s的话,每秒积累10件,30分钟就积累18,000件。 可以。如果这个状态没有结束,内存或磁盘都会用完然后爆炸。

如果λ > μ持续的话,需要的不是队列,而是增加工作者或限制流入。

延迟与利用率不成正比

这里人们经常忽略的一个点是,等待时间与利用率(ρ = λ/μ)成正比。 不会增加,而是非线性地爆炸。用大概的感官来说就是这样。

利用率ρ 等待时间排泄率(1/(1−ρ)) 意思
0.5 2倍 宽裕
0.8 5倍 渐渐露出了痕迹
0.9 10倍 再涨一点就会急剧变差
0.95 20倍 难以运营
0.99 100倍 实际上障碍

所以不能把步行者容量“刚好适合平均流入”来控制。以利用率70~80%为目标 抓住,上面接受自动扩展或流入限制。

在现场相遇的样子

加入队列后会产生新的运营指标。队列深度和消费者延迟(consumer lag) 是。如果把这两个放在仪表板上,**Q就会变成一个安静的黑洞。**用户 举报说上传了但没有显示出来,API仪表板都是绿色的。问题是 堆积在API后面。

光看深度是不够的。深度1000是否严重取决于处理速度。 不同。深度÷处理率=耗尽时间要一起看才能判断。每秒100件 处理的话是10秒,每秒1件的话是17分钟。警报也是以这个值设置的。

再加一个警报。**深度从0不动的也是异常信号。**消费者全部 死了,如果没有人拿出来的话,就只能堆积流入量,如果连生产者都死了的话,深度从0开始 平坦。如果处理完成件数为0,深度为0,那么整个管道就会停止。

而且,如果放入队列的话,还需要用户体验设计。如何处理“已接受”的状态。 会不会给我看,要等多久,如果失败了该怎么通知。不确定这个,就只排队。 输入后,用户会看到消失的请求。至少要确定三个。

在选择Q之前要回答的四个问题

选择工具是最后一步。在前面,首先要确定四个特性,把这个 不确定就选择Redis或Kafka的话,以后都会重新制作全部。

保证传递。至少一次(at-least-once)是基本条件。准确地说一次是队列给的 不是,而是消费者公平地获得的。记录处理的作业ID。 如果同样的东西再次出现,我会绕过。

**顺序。**遵守顺序的队列不能并行处理。在实际工作中,通常以键单位 顺序就足够了——只要同一个用户的工作按顺序进行,与其他用户的工作顺序 没关系。如果将分区键设置为用户ID,就会得到这个。

**重新尝试和放弃。**尝试几次,决定间隔如何增加,什么时候放弃。 如果在指数百折扣中不加入震动,失败的工作会在同一时间集中起来重新尝试。

**死去的信队列(DLQ)。**是写完再试的作业的地方。如果没有DLQ,那个作业是 永远循环或安静消失。DLQ中积累的数量一定会发出警报—— 这里堆积的是人们应该看到的。

将在下面的测验中确认

这个模块只涉及概念。从下一个模块开始,直接用Redis列表和流创建队列。 制作后,逐一再现顺序、重复、丢失在哪里发生的。