1 电商与大促方案要回答什么
大促方案的起点是交易承诺。用户点击下单后,页面显示的“提交成功”“等待支付”“支付成功”分别意味着什么?库存紧张时,系统可以让用户等待多久?故障发生后,商家能否解释每笔订单的去向?如果这些问题没有答案,增加服务器只能扩大同时进入系统的请求数,无法保证订单正确。本课沿用零售订单 API:用户查询商品、提交订单、发起支付,系统接收支付回调,并在订单取消或支付超时后释放库存。
先把业务要求改写成可以验收的句子。示例活动只面向指定商品,初始可售库存为 100 件;同一购买意图重试时只生成 1 笔订单;系统确认预占库存后才允许进入待支付状态;支付结果暂时未知时保留可查询状态;活动结束后能够核对库存、订单与支付记录。这里的 100 件是演练数据,正式方案还要由业务确认限购、支付期限、优惠适用范围以及退款规则。不能用系统默认值替代商业决定。
性能要求也要带上测量边界。可以约定活动峰值到达量为每秒 3000 次下单请求,其中包含重复点击和网络重试;预计每秒 300 次成为新的有效购买意图;普通时段下单响应的第 95 百分位不超过 500 毫秒。百分位表示大多数请求的体验,不能遮住少数长时间挂起的请求,因此还要约定请求最长等待时间。上述数字只是容量讨论的假设,必须通过与真实路径接近的压测确认,不能直接当作生产能力。
把目标分成正确性、体验、恢复能力和成本,方案才容易比较。正确性要求库存不出现业务意义上的超卖、重复回调不重复记账;体验允许高峰时明确排队或拒绝;恢复能力要求异常订单可查、可补偿、可审计;成本则约束活动前预热资源与活动后保留资源的时长。不同目标可能冲突,评审时应说明先保护什么。例如宁可暂时少卖,也不在库存结果未知时承诺已经买到。

架构图应把支付机构画在系统边界之外,把运营开关和核对任务画在交易路径旁边。支付接口不是自己能够随意扩容的组件,人工改规则也不是没有风险的后台动作。图中的每条依赖都要回答失败时谁负责、请求是否重试、结果从哪里查。这样才能从需求进入备选方案,而不是先选产品,再为产品寻找业务理由。
2 库存、下单与支付边界
理解交易路径,先区分可售库存、预占库存和已售库存。可售库存允许新订单竞争;预占库存暂时留给待支付订单;已售库存对应已经确认完成购买的数量。在简化模型里,可售、预占与已售数量之和应等于本次活动纳入管理的总量。补货、退货和人工调整需要单独记录原因,不能悄悄修改总量,否则看似平衡的数字也可能掩盖错误。
下单不是立即收款。订单 API 接收商品、数量和购买意图标识,验证活动资格后,尝试预占库存,成功后建立待支付订单。购买意图标识也常称为幂等键,用来识别同次操作的重试;服务端必须校验它与用户、商品、数量等内容的绑定关系。同个键换了商品应返回冲突,不能复用旧订单,更不能按新的内容再次扣库存。幂等保证的是业务效果不会重复,响应时间和返回报文不必逐字相同。
本课选择把订单记录、库存预占和幂等记录放在同个数据库事务里完成。事务意味着这些变更共同提交或共同撤销,避免留下“占了库存却找不到订单”的中间结果。库存变更必须带上“当前可售数量足够”的条件,并检查实际更新结果。先查询有货,再无条件扣减,无法阻止并发请求同时通过检查。条件更新与订单写入还要处于同个事务边界,任何失败都不能继续承诺成功。
支付属于另个边界。系统建立待支付订单后,再向支付机构发起支付;用户浏览器跳转回商店页面,并不等于商店已经确认收款。支付回调可能重复、延迟,也可能先于某次页面查询到达。接收回调时,需要按支付机构约定校验来源、签名及必要的重放约束,并核对订单、金额、币种和支付交易号。随后通过受控的状态迁移记录结果,不能因为收到“成功”字符串就改成已支付。

订单可以使用待支付、已支付、已取消、支付结果待核对等状态,但状态越多越需要说明进入条件。支付成功通常把对应预占转为已售;取消或到期则尝试释放尚未消费的预占。支付确认与取消发生竞争时,必须在同个受控状态边界内决定谁取得处理资格。若已经释放库存后才确认收款,应进入异常处理和退款流程,不能直接把订单恢复成已支付后继续发货。跨越支付边界的完整原子事务不在本课展开,先把可观察状态、重试与核对路径写清楚。
3 限流、排队与降级
大促流量常呈现短时间集中到达,容量规划不能只看全天平均值。限流的作用是在受保护资源之前控制准入,让系统在已验证的处理能力内工作。入口可以按用户、活动和接口分别约束,但这些约束不能只存在于页面。用户可能刷新、换入口或直接调用接口,最终执行下单的服务仍需要统一的规则。只按来源地址限制也容易影响共享网络中的正常用户,具体维度要结合业务身份与滥用风险决定。
限流返回应明确区分未受理和已受理。前者允许用户稍后用原购买意图重试;后者应给出可查询的受理标识,让用户查询状态。响应超时只表示调用方没有及时拿到答案,不能推导出服务端没有执行。客户端自动重试要有次数上限与逐渐延长的间隔,避免所有设备同时再次发起请求。服务端也应返回稳定的错误类别,方便页面决定提示、重试还是停止。
排队用于吸收短时波峰,前提是队列有长度上限、等待时间上限和明确的受理语义。例如队列最多保存 1200 个请求,订单处理能力为每秒 300 个有效请求,粗略排空时间为 4 秒。这只是稳定处理速率下的估算,后续到达、处理抖动和重试都会改变等待时间。队列满时必须拒绝或暂停准入;无界队列只是把过载改造成越来越长的等待,并可能让活动结束后仍在生成订单。
还要区分“排队资格”和“库存承诺”。进入队列通常只说明系统接受稍后处理,不保证有货。如果业务希望排队即锁定库存,就需要同时解决预占期限、掉队释放和重复排队等问题,复杂度明显增加。本课采用有界准入等待,正式订单创建仍执行库存条件更新。排队令牌只在服务端验证后生效,不允许客户端自己修改名次、数量或活动归属。
降级应从可舍弃的功能开始。推荐列表、个性化文案、非必要的实时统计可以暂停或使用较旧数据;库存预占、金额核验和支付状态保护必须继续执行。商品展示可以出现短暂滞后,但最后的库存承诺只能由交易路径给出。支付结果核对、订单查询和库存释放还需要保留独立的处理余量,避免所有资源都被新下单占满,导致已有交易无法收尾。
限流、排队和降级需要共同演练。单独打开限流可能使客户端更频繁地重试;单独增加队列可能推高等待时间;关闭订单查询又会迫使用户重复提交。观察时应同时看准入数量、拒绝数量、等待时长和成功订单数。只有拒绝数下降,却没有更多正确完成的订单,不能说明保护策略变好了。
4 动手:演练一次超卖防护路径
演练使用独立测试环境、虚拟商品和模拟支付,不接触真实资金。建立初始库存 10 件,每笔订单购买 1 件,准备 30 个不同购买意图,其中部分会重复提交。记录活动编号、库存初值、规则版本、请求标识和开始时间。演练目的不是追求更高请求数,而是证明并发、重试和异常出现后,库存承诺依然可解释。若环境会自动重置库存,需要暂时关闭该行为或明确标记重置事件。
按顺序发送 1 个正常请求,确认返回待支付订单,库存从可售 10 件变为可售 9 件、预占 1 件。再用相同幂等键和相同内容重发,期望得到原订单,数量不再变化。随后保持幂等键不变但更改购买数量,期望收到冲突,并且没有新增库存变更。先做这些小步骤,可以把身份识别错误与并发竞争错误分开观察,避免大批请求让证据变得模糊。
接着并发提交其余购买意图。测试程序记录每个请求的幂等键、返回状态和订单标识,不能只输出成功比例。在暂不支付、不取消且没有超时释放的观察窗口内,成功预占总量最多为 10 件,可售数量不得小于 0,所有预占都能对应到订单。失败请求应该得到库存不足或明确的准入结果。若预占会在观察期间过期,就必须计入释放和后续重新售出,不能再拿累计订单数直接与 10 比较。
再制造“提交完成但响应丢失”:让模拟网关在服务端提交后丢弃返回结果,客户端使用原幂等键查询或重试。期望找到原订单,不能产生额外预占。这个步骤验证的是未知结果恢复能力。数据库如果仍在提交中,系统可以返回处理中并要求稍后查询,但不能在缺少最终结果时宣告购买失败,让用户用新意图立即再次购买。
最后对部分待支付订单模拟支付成功,对其余订单触发到期取消,并重复发送支付回调和释放任务。确认同笔支付只推进订单 1 次,同份预占只被消费或释放 1 次。专门让到期任务和支付确认同时执行,检查是否进入预先定义的竞争处理路径。如果库存已释放且商品已售给其他用户,迟到的付款必须进入核对及退款流程,不能通过临时加库存掩盖超卖。
演练结束后保存请求记录、订单状态、库存变更和模拟支付记录,并按业务标识关联。验收应同时满足数量守恒、无重复业务效果、未知结果可查询和异常路径可收尾。清理只发生在证据保存之后,记录清理范围和结果。真实生产演练还要另行制定流量范围与退出条件,本课的测试结论只适用于当前模型和已经覆盖的故障组合。
5 吞吐与一致性取舍
吞吐表示单位时间处理多少工作,一致性在这里关注不同交易记录是否符合业务约束。把所有检查放进同个同步路径,往往更容易说明成功的含义,但每次请求要等待更多依赖。把部分处理移到后台,可以缩短入口等待,却增加“已接收、尚未完成”的状态。评审时应比较用户最终得到的承诺,不能把“接收请求每秒 3000 次”与“每秒完成 3000 笔正确订单”当作相同成绩。
可以比较 3 个入门选项。选项 A 直接在数据库事务内创建订单并预占,路径短、约束集中,适合验证基础能力。选项 B 在入口增加有界等待,后续仍执行相同事务,能够平滑短时峰值,但增加等待和队列运维成本。选项 C 把下单请求持久化后异步处理,入口更快返回受理结果,却需要受理查询、重复消费防护及过期请求处理。它们没有脱离场景的优劣,选择依据应是峰值持续时间、有效订单量和团队维护能力。
本课采用 A 作为正确性基础,在压测证明需要时加入 B。决策记录即 ADR,用简短文字保存背景、选项、选择和后果。可以写成:由于库存规模有限,优先保证预占与订单共同提交;入口只返回已创建订单或明确的等待状态;暂不引入异步下单,以减少处理中状态的维护。代价是热点商品可能使数据库争用加重,容量超过已测边界时主动限流。若后续有效订单峰值持续超出能力,再以证据重开决策。
容量估算要拆开入口流量与数据库工作量。假设每秒 300 个新订单,平均数据库事务耗时为 20 毫秒,在稳定条件下粗略对应约 6 个正在执行的事务。这只是平均在途数量的估算,并不等于 6 个连接就足够,也不能预测热点库存行的等待。连接池、慢请求和失败重试都要在压测中观察;没有足够数据时,应保留容量余量并明确触发限流的阈值。
成本应按活动窗口计算。示例预算包括活动前 2 小时预热、活动持续 4 小时、活动后 2 小时核对,共 8 小时的临时计算资源,以及数据库容量、队列存储、日志和网络费用。把资源数量乘以使用时长和单价,另列常驻资源、压测费用和恢复演练费用。不要只比较服务器单价,增加异步路径还会增加告警、值守和排错的人工成本。价格随环境变化,方案应保留计算口径而非写死某个报价。
6 常见坑:大促临时改规则未回滚
大促现场常出现临时要求:延长支付期限、放宽限购、提高准入速度,或对某类用户开放新优惠。这些操作会改变交易语义。临时把支付期限从 10 分钟改为 30 分钟,会延长库存占用;活动结束后如果忘记恢复,平时的缺货率也会升高。规则不是页面提示文字,它会影响订单创建、到期任务和支付异常处理。只恢复前端展示,后台仍可能按旧规则工作。
每个临时规则都应包含活动范围、版本、生效时间、失效时间、负责人和恢复动作。下单时把实际使用的关键规则版本写入订单或可追溯记录,尤其是金额、优惠和到期时间。到期任务应使用订单已经确定的到期时间,不能每次读取最新全局期限来重新计算。这样才能避免配置回滚后,既有订单的支付期限被意外缩短,或新订单继续继承活动期间的宽松条件。
回滚也不是把配置恢复原值就结束。停止新请求采用新规则,与处理已受新规则影响的订单,是不同工作。例如恢复每人限购 1 件,不代表可以直接取消已经合法购买 2 件的订单;关闭新优惠也不能擅自改变已确认的应付金额。方案应分别说明新订单何时切回、既有订单如何继续履约、异常记录由谁核对。必要时保留只读的历史规则,供客服和审计解释交易结果。

规则变化要能与指标变化对齐。监控图上标注版本切换时刻,关注预占存量、预占年龄、到期释放延迟、支付待核对数量,以及新旧规则订单的分布。若活动结束后预占仍持续增长,应检查是否还有入口沿用活动规则,不能立即判定数据库故障。告警要关联明确动作,例如暂停新准入、恢复上一版本、启动待核对清单,而不是只发出“系统异常”。
最有效的预防是把恢复写成活动必经步骤:提前演练失效时间,到时自动停止新增规则适用,并由值守人员确认实际效果。自动失效也要有失败告警,因为配置系统本身可能不可用。活动复盘需要保留规则差异和恢复证据,不能只留下峰值流量截图。临时措施最终应当有明确去向:恢复、转为正式规则,或在下一次活动前删除。
7 案例:库存扣减与支付回调乱序
设订单 O23 在 12:00 创建,预占 1 件库存,支付期限为 10 分钟。用户在 12:09:59 完成付款,支付回调因网络延迟到 12:10:03 才到达;到期任务已在 12:10:01 尝试取消。用户看见支付成功,商店可能已经释放库存。这不是简单的“回调太慢”,而是支付事实、通知到达时间和本地取消动作不处于同个时钟顺序,系统必须允许这种情况出现。
先恢复证据:查订单创建记录、库存预占及释放记录、到期任务执行结果、支付交易号和支付机构查询结果。日志时间只能帮助排序,最终还要看哪个状态变更实际提交成功。不能因为回调日志排在取消日志后面,就断言支付发生得更晚。不同设备时钟有误差,网络也会重排消息;可信的支付结果与本地状态迁移记录需要一起核对。

如果支付确认先获得状态迁移资格,订单进入已支付,对应预占转成已售,到期任务看到终态后退出。如果取消先完成,订单取消且预占已释放,迟到的成功支付就生成异常处理记录,并触发核对和退款。退款本身也可能暂时失败,因此应有待退款、退款处理中和已退款等可追踪结果;具体状态命名可简化,但不能把发起退款等同于退款完成。
还有更隐蔽的顺序:回调已经到达,数据库提交失败,支付机构随后再次通知。接收端只有在按协议完成必要的可靠记录后才确认处理成功;重复回调应查到原支付交易与处理结果,继续未完成步骤或返回已有结果。若同笔支付交易号试图绑定不同订单,需要拒绝并告警。回调重试、人工补偿和定时核对都应通过相同的业务状态保护,避免各自实现不同的修改逻辑。
核对任务为通知丢失提供补充。它定期查询超过预期时间仍未完成的订单,与支付机构结果比对,按既定规则修复或转人工。核对不是无条件把外部“成功”覆盖本地状态,而是再次检查金额、归属和库存处理结果。样例中若商品已经售给其他用户,采用退款收尾;若业务希望尝试补货履约,需要另写业务授权与用户沟通规则,不能由技术人员临场决定。
这个案例的验收不只是“最终退款成功”。还要证明重复通知没有重复确认收入、重复到期任务没有重复释放、核对重跑没有重复退款,且客服能通过订单标识解释全过程。日志中使用必要的业务标识,避免记录完整支付凭据或敏感个人信息。把这些可观察结果变成演练证据,才能判断修复是否真正覆盖了故障,而非仅让某次请求返回成功。
8 把大促保护写进交易方案
完整交易方案需要让开发、运营和值守人员读出相同的行为。先描述用户承诺,再画出入口、订单服务、数据库与支付边界,标明限流位置、库存承诺位置和异常收尾位置。每个成功响应都要有可验证的依据,每类失败都要说明是否已受理以及如何查询。附上 ADR 后,评审者就能把选择与需求对照,而不是只审核组件是否齐全。
高可用首先要避免单个应用实例故障中断全部服务。可以在多个可用区运行无状态订单实例,并使用健康检查摘除故障实例;数据库采用具备明确故障切换机制的主备部署。主备并不自动意味着所有已确认写入都不会丢失,必须核实复制方式和确认语义。若无法保证库存承诺在切换后仍完整,应暂停新的库存承诺并完成核对,避免在不确定状态上继续售卖。
恢复目标要具体到业务。例如测试目标可设为应用实例故障后 5 分钟内恢复准入;对于已经确认的订单,要求恢复后能查询并核对承诺记录。实际恢复时间目标与恢复点目标需要业务认可,并由部署能力和演练证明。备份恢复与主备切换解决的问题不同,备份还应演练误操作后的数据恢复。不能只写“具备高可用”,却不说明库存、订单和支付记录在恢复后如何重新对齐。
风险表至少覆盖热点库存竞争、支付依赖异常、队列积压、规则未恢复和数据库切换。每项风险写触发信号、保护动作、责任人和退出条件。例如支付机构持续超时,先减少新支付尝试并保留订单查询及核对资源;恢复后逐步放开,观察待核对数量是否下降。降低流量不能替代处理已有交易,保护动作也不能让补偿任务永久停止。
发布计划与容量计划应相互约束。活动前固定关键规则版本,完成正常、过载和异常路径演练;活动中按已测阈值调整准入,记录每次改动;活动后恢复临时资源与规则,完成账实核对再关闭活动。预留的余量需要用于故障切换和交易收尾,不应在峰值时全部分配给新下单。这样的方案才同时回答需求、选择、成本、风险和高可用。
9 从电商与大促方案走向音视频与游戏方案(P24)
订单 API 帮助我们建立了按承诺设计系统的方法:先确定用户看到什么结果,再确定状态由谁维护,最后选择容量与故障保护措施。这个方法可以迁移,但不能把具体策略原样复制。电商订单通常允许用户等待几秒确认受理,却不允许重复扣款;音视频可能允许丢弃过时画面,却不能把排队延迟无限增加。业务对“来得晚”和“结果错”的容忍度不同,会改变架构重点。
进入 P24 时,可以继续沿用需求、选项、ADR、成本、风险和高可用的讨论顺序。变化的是测量对象:订单关注正确完成的交易量、状态收敛时间和资金库存核对;音视频与游戏还会关注端到端延迟、抖动、连续性和会话体验。这里先理解指标必须对应用户感受,不展开编码、传输协议和游戏同步内部机制。那些内容需要新的场景假设与实验。
回看本课,如果能够解释“已进入队列为什么未必有货”“超时为什么不能等同于失败”“支付成功为什么可能进入退款流程”,就已经掌握了交易边界的关键。再尝试写出当前方案最先达到的容量瓶颈,以及达到瓶颈时用户看到的提示。答案应来自路径和证据,不能只写增加实例。带着这种对承诺、等待和恢复的区分,再进入下一类业务。
放进方案里
本方案面向零售订单 API,覆盖商品下单、库存预占、支付确认、到期取消与异常核对。活动流量按每秒 3000 次入口请求、每秒 300 个新购买意图进行初始估算,最终准入阈值以压测结果为准。系统优先保护库存承诺和支付记录的正确性;过载时明确返回等待或未受理,受理结果可通过业务标识查询。排队资格不代表已经获得库存。
库存预占、待支付订单与幂等记录在同个数据库事务内提交,使用带可售数量条件的更新防止并发超卖。支付回调核验来源、金额和交易归属,重复通知通过支付交易标识及订单状态保护消除重复效果。支付确认与到期取消竞争时按实际提交结果处理;库存已释放后的迟到付款进入核对和退款,不直接恢复履约。定时核对覆盖通知遗漏,并保留人工处理入口。
入口采用有界准入等待,限制长度与等待时间,优先降级推荐和非必要统计。订单查询、库存释放、支付核对保留处理余量。订单实例跨可用区部署,数据库主备切换能力与数据保留语义必须经过演练;恢复状态不明确时暂停新增库存承诺。成本预算按预热、活动和核对窗口计算,并列明存储、日志、网络和人工值守费用。
活动规则记录版本、范围、期限与负责人,订单保存实际采用的关键规则和到期时间。活动后分别确认新订单规则恢复、既有订单继续履约和临时资源回收。验收证据包括并发预占、重复请求、响应丢失、回调乱序、重复释放及故障恢复记录;同时核对可售、预占、已售与支付结果。若持续有效订单量超过已验证容量,依据新增证据重新评审异步下单方案。
10 小结:下一步音视频与游戏方案(P24)
电商与大促方案的核心是让每次受理、库存变化和支付结果都能解释并恢复。限流控制准入,排队吸收有限波峰,降级保护必要交易,幂等与受控状态迁移处理重试和竞争。临时规则要有期限,故障恢复要有证据,成本要覆盖活动收尾。
自测时,可以用同笔订单讲清正常付款、提交超时、到期竞争和迟到回调的去向,并指出各自可查询的记录。下一课进入音视频与游戏方案(P24),继续按需求到恢复的顺序设计,同时重新判断等待、丢失与连续体验之间的取舍。