验证与性能口径
用状态不变量检验交易正确性,区分历史压测、源码测试和本站 mock 验证。
正确性先于吞吐
抢座测试关心同一场次同一座位最终只有一笔有效占用,多座位冲突时不能留下部分占用。SeatConcurrencyIT 使用六十四个工作线程提交一千个调用任务;任务数不等于同时运行一千个线程。
支付、取消和对账集成测试使用 Testcontainers 提供真实依赖,检查状态推进、重复回调、Redis 自愈及五类补偿。浏览器 mock 的通过只能证明演示状态与交互,不能替代真实依赖的并发测试。
用不变量组织验证
| 不变量 | 需要构造的场景 | 观察对象 |
|---|---|---|
| 同场次同座位最多一笔有效占用 | 多个请求争抢同一座位 | 成功订单与 order_seat 唯一性 |
| 整批购买不能部分成功 | 请求中混入一个已占座位 | 其余座位与限购计数是否保持不变 |
| 订单只能从待支付推进一次 | 支付、取消、超时相互竞争 | CAS 影响行数和最终状态 |
| 重复通知不产生额外业务变更 | 同一通知重放、成功后再通知 | 支付单、订单与座位状态 |
| 差异可以按业务依据修复 | 删除座位图或制造孤儿状态 | 对账前后数据及修复报告 |
成功请求数只描述入口结果。判断没有超卖,还要查询有效占用;判断取消真正释放,还要检查数据库和 Redis 两侧;判断幂等,也要观察限购计数是否被重复修改。每个断言都应对应一个业务不变量。
历史压测记录
项目 README 保存了 2026 年 9 月 16 日一次同机、单实例 JMeter 运行记录。本次站点建设没有重跑该压测。
| 指标 | 历史值与口径 |
|---|---|
| 混合总请求 | 5505 次,含浏览、注册、登录及下单 |
| 混合总吞吐 | 351.7 QPS,不是下单接口吞吐 |
| 下单采样 | 250 次尝试,249 成功、1 次预期座位冲突 |
| 下单延迟 | 这 250 次采样的 P99 为 43 ms |
| 事后唯一性检查 | 重复场次座位占用数为 0 |
压测器、JVM 和数据库等依赖同机争用 CPU、内存与网络,结果适合这次环境内的相对参考,不能外推为生产容量。脚本把预期抢座冲突作为正常业务结果,因此报告的错误率零不表示全部请求都买票成功。
混合负载包含哪些请求
历史脚本有浏览和下单两类主要负载。浏览线程反复查询场次与座位图;下单线程先登录、读取最新座位图,再随机选择空闲座位提交。注册和登录也计入总请求,因此总吞吐同时包含读取、鉴权与交易处理。
脚本预建不同用户,减少同一用户频率与限购额度对抢座链路的干扰。这样的设计适合观察并发座位冲突,却不能回答某个用户持续重试时的限流体验,也不能替代缓存冷启动、数据库故障或支付回调积压的专项测试。
如何理解尾延迟
P99 43 ms 描述的是该次 250 个下单样本的尾部百分位,不是最大耗时,也不是长期稳定保证。少量样本对尾延迟的估计容易随运行波动;比较优化效果时,需要固定数据量、依赖状态、负载比例和预热方式,同时看吞吐、错误语义和资源占用。
如果只把业务冲突排除在错误率之外,却没有单独统计冲突数量,报告会掩盖用户实际买票失败的比例。当前记录同时报告 249 次成功与 1 次预期冲突,才具有可解释性。
观测哪些信号
下单计数、支付回调接受 / 重复 / 差异、各类对账修复量由 Micrometer 暴露。TraceId 帮助关联 HTTP、消息和补偿日志。判断一次“支付成功但座位未售出”应同时检查支付单、订单、有效占用和 Redis,单看接口成功率不足以定位差异。
仓库提供 Prometheus 接入,但没有提交 Grafana 预置面板,也未实现原规划的慢 SQL 拦截日志。不要把可观测性依赖已接入描述成完整生产监控已经落地。
一次差异如何排查
以“用户看到付款成功,但座位仍锁定”为例,先用订单号关联支付单与回调,确认成功通知是否被接受;再检查订单是否已支付及有效占用是否存在;最后对照 Redis 字段和对账修复量。若订单已经取消,应转向资金差异分支,不能直接强行改成已支付。
TraceId 用于串联一次执行,订单号和支付单号用于关联跨请求的业务过程。两类标识都需要:同一笔交易可能经历多次查询、支付尝试与通知,每次请求的链路标识不一定相同。
本站演示验证范围
本站状态测试覆盖整批锁座冲突、跨订单限购、支付失败后重试、重复成功、主动取消、到期释放、过期后的支付尝试、身份隔离、数据恢复、排期冲突与开售后禁止修改。
浏览器检查另外验证真实 Vue 页面中的选座、下单、支付与运营界面,以及桌面和手机布局。这里的十五分钟到期由可控时钟的状态测试验证,不需要把页面挂起十五分钟才能判定核心规则。
验证分为三层:状态测试快速检查可控规则;真实依赖集成测试检查事务、Lua、消息和 Mapper;浏览器检查真实界面是否正确表达结果。层次之间相互补充,不能把本站 mock 的一次流畅操作当成生产并发性能或真实支付安全性的证明。
