软件架构考试之夜提供了证据,不是容量保证——NovaCommerce 第五篇
两场真实考试、一次缩容失误和一个规划模型。最后一篇把观察、外推、运维成本与尚欠测试分清楚。
快速响应可能掩盖未完成业务。按新增到达和积压配置worker,保留已接受记录,让重试有责任、有边界。
作者
Anichur Rahaman

早上9:00,考试平台已持久接受1,000份答案,但评分尚未完成。学生应看到“已收到,待评分”,不是编造的成绩。这个教学情境也适用于ERP生成发票或订单生成运单:接受请求与完成后台义务是不同事件。
队列吸收到达不均,却不创造处理能力,也不证明业务动作结束。Engineering for High Volume第2篇沿权威记录、有限worker池、不确定外部结果与受控恢复追踪责任。本文不声称个人测试或客户成效。
界面说已收到前,经过验证的提交必须能保存下来。不要把答案、订单或审批的唯一副本放在可丢弃队列。记录接受内容、授权人和待办义务,评分、通知及外部交付分别跟踪。
Laravel队列文档解释事务提交后分发,避免读取未提交数据或事务回滚后仍执行工作。但业务提交与另一队列发布若是两次写入,提交后崩溃仍可能没有消息。
关键义务使用适当原子队列/数据库设计,或以事务outbox将发布意图与所属变更一起存储,再由可恢复relay发布。重复、保留及运维故障仍须控制,仅after commit不是不丢失保证。
每类工作设完成/时效目标。提交、支付对账、通知、图片和报表可能有不同紧迫性、成本与故障行为。分队列帮助路由,不会自动预留CPU、内存、数据库或服务商配额。
需要独立容量时设明确supervisor/池预算。一个worker先看高队列仍一次执行一个job,也可能饿死后续队列。专用容量不会抢占正在跑的长job,低优先工作仍会争用同一数据库。
分离web和worker计算资源可保护预算,容器/cgroup或独立节点都可适用。共享数据库、缓存与网络故障仍会影响两侧,“迁出worker后页面永不受影响”不可信。
假设起点瞬间有B=1,000个就绪job,平均worker占用s=0.12秒/job,含相关I/O等待。现有工作共120worker秒。没有新增时,12个完美均衡worker的流体下界是10秒;即使job全同且不可分,也需要84轮×0.12=10.08秒,分发、偏斜、重试和争用还会增加。
现在持续每秒新增50个就绪job。w个worker理想吞吐w÷0.12,超过50才会减少积压,理想清理时间B÷(w÷s−50)。表格是规划模型,不是实测基准或截止保证。
这种到达下10秒目标的流体下界是w≥s×(50+B÷10)=18。仍需为变异、故障和依赖留实测余量,不能将job数除运行时间直接称为worker数,单位和时间目标都重要。
| Workers | 理想吞吐job/s | 净清积压job/s | 1,000个的流体清理时间 |
|---|---|---|---|
| 6 | 50 | 0 | 不会净减少 |
| 12 | 100 | 50 | 20秒 |
| 18 | 150 | 100 | 10秒 |
增加worker终会碰到共享瓶颈。测有效完成、最老合格就绪年龄、占用时间分布、数据库/锁等待与服务商限制。就绪队列短可能仍有许多保留/卡住工作,故意未来执行的延迟job不应抬高就绪告警。
当前Laravel13 Horizon指南区分simple分配进程、auto分配及按顺序处理的false模式,后者仍可能扩进程数。Auto不按数组顺序保证严格优先级。检查安装版本,不要将false当成统一固定池开关。
Horizon管理Redis队列worker,当前文档不支持Redis Cluster。可跑在多个计算节点,但不会自己供应这些节点。跨队列、supervisor和副本合计最小、最大与资源,一处supervisor上限不会自动变成全局上限。
KEDA2.21可围绕Kubernetes工作负载提供事件扩缩容信号,HPA改变副本。可用计算、轮询/指标新鲜度、激活、镜像、就绪及缩容规则决定反应;pod与进程均无通用秒/分钟保证,也不免计算和运维成本。
指标须符合实际驱动。Redis列表长度可能只计就绪,不含保留/延迟。已知突发前准备合理最低容量,响应式扩容保持在验证范围,不让第二套控制循环互相对抗。
虚构Horizon/Redis时间预算为:外部调用期限10秒,job45,supervisor60,连接retry_after90。这不是已交付设置。Horizon超时应高于job,并与retry_after保持安全距离;验证实际驱动、运行时扩展与退出行为。
retry_after不是应用重试间隔,它控制预留job未正确完成/释放时何时可重新就绪。若原worker仍在运行而另一worker接到它,就可能重复作用。SQS可见性及其他驱动各有约定。
| 示例边界 | 秒 | 用途 |
|---|---|---|
| 外部调用 | 10 | 限定实际调用 |
| Job超时 | 45 | 限定一次执行 |
| Horizon supervisor超时 | 60 | 大于job,小于预留到期 |
| Redis retry_after | 90 | 预留就绪时间,不是退避 |
设次数和总年龄上限,明确异常/释放语义,并按需退避和抖动。权限或数据无效需要修正,不是无限重试。失败存储必须有告警、负责人及复核后的重试/取消入口;写一行不是恢复。部分middleware释放会消耗尝试次数,应检查实际语义。
开头检查已经完成可能与另一worker竞态,也可能在保存回执前崩溃。本地数据库作用须将限定范围唯一操作认领、业务变更及结果原子提交。队列唯一性或重叠锁不能证明外部支付/邮件只发生一次。
外部调用保留持久业务引用,使用支持的幂等和状态查询。Stripe幂等约定说明键范围、参数和保留的重要性。结果未知先查原操作并对账,再考虑替代;新键可能产生新扣款。
已付发票的PDF失败需要恢复文档,不是再次收款。邮件请求被接收不证明送入收件箱。尝试、服务商结果与业务完成分开,重放须尊重批准的当前状态,不要清空全部去重键。

计算常驻worker/runtime、保留内存、重job峰值及共享/容器基础。示例10worker×128MiB私有/增量预算=1,280MiB=1.25GiB,尚未算其他开销/余量,不能证明2GiB容器够用。混合池按各自worker×内存加总,测试峰值共存。
流式/分块可减少内存,但库仍可能缓冲,拆任务也改变顺序/恢复。应测前后,别编造288→128MiB节省。适时回收长进程,没有证据就加RAM/worker可能保留原瓶颈。
只传必要且有限数据,ID不是永久读取许可。所属服务重查权限与业务状态,保护broker传输/存储、payload、失败记录、看板和导出。Payload加密不保护全部元数据与通用日志。OWASP日志指南支持保留有用证据而不倾倒密钥、工资或客户文档。
发布兼容代码/结构/payload,并优雅替换受监督长进程,无需清空全部队列。在验证的退出/可见性限制内完成或恢复当前工作,旧任务处理前保留版本兼容。最后启动scheduler不能单独修复不兼容任务或重复调度。
Laravel调度指南支持共享原子锁协调单服务器工作,固定cron节点不是唯一拓扑。验证过期、重叠、故障切换和漏跑恢复,并保留业务幂等。周期relay可以合理,长进程不是内存压力的通用药。
演练提交前后崩溃、发布失败、并发重复、超时未知、错误payload、撤销权限、重job峰值及中途发布。隔离真实外部扣款/消息。按相同范围、时间、状态核对待办与实际作用,不只看队列深度零。
有用的9:00看板能说清答案已收、评分待办/完成、通知已接受/确认、异常归谁。准确完成目标仍须整合测试。请供应商,包括StoreConsole,在所售版本与模块上展示流程、权限及有限恢复。
审阅于2026年11月5日。Anichur Rahaman,StoreConsole创建者。提交、容量、时间与内存为示例,不是客户基准或已安装软件保证。
系列
高并发系统工程作者简介
Anichur Rahaman
继续阅读