CASE STUDY01
JAVA BACKEND
CommerceFlow AI Mall
围绕商品、订单、库存和 AI 商品助手构建的 Java 业务系统,重点展示分层设计、状态流转、数据一致性和前后端联调。
/ SYSTEM PATH
从幂等请求到事务提交的事实链路。
- 01Request + Idempotency-Key
- 02请求指纹与唯一约束
- 03聚合同 SKU 数量
- 04库存原子条件 UPDATE
- 05订单 / 快照 / movement 写入
- 06MySQL 事务提交或整体回滚
- 07Java 构造 businessFacts
- 08Provider 或事实约束 fallback
/ DECISIONS & FAILURE CHECKS
正确性留在数据库与 Java 边界内。
01库存扣减使用原子条件 UPDATE
在 SQL 中同时判断库存并扣减,让库存竞争的胜负由单条写操作决定。
+
- 未选择 / 取舍
- 未采用“先 SELECT 库存、再 UPDATE”的读后写方案;后者在并发窗口中更容易超卖。
- 失败验证
- 50 个不同 Key 竞争库存 10,结果为 10 个 CREATED、40 个 INVENTORY_INSUFFICIENT,最终库存为 0。
02幂等落在数据库唯一约束
持久化 Idempotency-Key 与请求指纹;同请求返回原订单,不同请求返回 IDEMPOTENCY_KEY_REUSED。
+
- 未选择 / 取舍
- 未只使用进程内锁,因为它不能覆盖重启、重试与多实例边界,也不能留下持久化审计事实。
- 失败验证
- 20 个同 Key 同请求只产生一个物理订单;同 Key 不同请求返回等价 HTTP 409,且没有额外库存变化。
03Redis 只保护 AI 接口
Redis Lua 用于 AI ask endpoint 的固定窗口限流,订单正确性仍由 MySQL 事务与唯一约束保证。
+
- 未选择 / 取舍
- 未让 Redis 锁参与订单正确性;这避免 Redis 状态与 MySQL 事实之间出现新的双写一致性问题。
- 失败验证
- Redis 集成测试验证 5 / 60s Showcase 配置;Redis 不可用或限流结果不会改写订单事务事实。
04businessFacts 由 Java 从 MySQL 构造
库存、商品与订单事实先由 Java 读取并收敛为显式契约,再交给 Provider 生成表达。
+
- 未选择 / 取舍
- 未允许 Provider 自行查询或猜测库存;Provider 只消费受限事实,不拥有业务写权限。
- 失败验证
- AI 客服测试校验事实字段与引用链路,防止回答使用契约之外的业务数据。
05AI 不可用时由 Java 事实降级
Provider 异常时返回基于 businessFacts 的确定性降级结果,不让外部模型故障破坏业务事实。
+
- 未选择 / 取舍
- 未把“强制调用外部模型”当作成功条件;可用性优先于看起来更智能的不可验证回答。
- 失败验证
- Provider 禁用测试验证降级边界;回退内容仍受 Java 事实契约限制。
/ FEATURED FAILURE CASE
成功结果只说明正常路径;失败结果用于检查设计是否真的守住边界。
PRIMARY · INVENTORY COMPETITION
库存 10,50 个不同 Key 同时竞争
- SETUP
- MySQL 8.4 独立测试库;50 个不同幂等 Key 请求同一 SKU。
- EXPECTED
- 最多 10 个订单成功,不超卖;失败请求不留下订单或库存变动。
- OBSERVED
- 10 个 CREATED、40 个 INVENTORY_INSUFFICIENT;最终库存 0;orders、items、movements 均为 10。
- LESSON
- 原子条件 UPDATE 与同事务证据写入能够把竞争结果收敛为可核对的数据库事实。
BOUNDARY这是受控本地可靠性回放,不是 QPS、吞吐量、生产压测或分布式多实例证明。
其他失败回放
IDEMPOTENCY20 个同 Key 同请求+
- EXPECTED
- 只产生一个物理订单,顺序重放返回原订单。
- OBSERVED
- 库存 10 → 9;只存在一个订单;并发非 owner 请求可能得到 IDEMPOTENCY_IN_PROGRESS。
- LESSON / BOUNDARY
- 幂等语义区分 owner、并发等待与顺序重放。 不外推为分布式多实例幂等能力。
KEY CONFLICT同 Key 不同请求+
- EXPECTED
- 拒绝错误折叠,不复用原订单。
- OBSERVED
- 返回 IDEMPOTENCY_KEY_REUSED(等价 HTTP 409),无额外库存变化。
- LESSON / BOUNDARY
- 幂等键必须与请求指纹共同判断。 结果来自仓库测试,不代表所有网关重试策略。
ROLLBACK第二个 SKU 缺货触发整体回滚+
- EXPECTED
- 整个订单失败,第一个 SKU 的预扣减恢复。
- OBSERVED
- orders、items、movements 均为 0,第一个 SKU 库存恢复。
- LESSON / BOUNDARY
- 订单与库存证据必须处于同一 MySQL 事务。 未覆盖支付、物流或跨服务 Saga。
DUPLICATE SKU重复 SKU 先聚合再扣减+
- EXPECTED
- 聚合为数量 5,避免重复写入和分段扣减。
- OBSERVED
- 只产生一个 order item 与一个 inventory movement。
- LESSON / BOUNDARY
- 在事务入口规范化请求,减少后续一致性分支。 只验证单订单内聚合,不代表批量导入能力。
/ VERIFIED EVIDENCE
可靠性回放、事务测试与事实契约。
01 / documentationLOCAL VERIFIEDcommerceflow-ai-mall main @ dea3eab
2026-07-31 · 本地 Showcase 状态,不代表生产部署、线上流量或外部模型效果。README · LOCAL SHOWCASE ↗02 / local50 REQUESTS / STOCK 10受控 MySQL 可靠性回放 · 10 CREATED / 40 INSUFFICIENT
2026-07-31 · 本地并发场景,不是生产压测、QPS 或吞吐量指标。库存竞争回放 ↗03 / local20 SAME-KEY REQUESTS / 1 ORDER同 Key 同请求 · 库存 10 → 9 · 顺序重放返回原订单
2026-07-31 · 不声称分布式多实例幂等。并发幂等测试 ↗04 / localROLLBACK / ZERO RESIDUE第二个 SKU 缺货 · orders/items/movements = 0
2026-07-31 · 只覆盖单体 MySQL 事务,不覆盖跨服务 Saga。事务回滚测试 ↗ / SOURCE INDEX
每个入口都固定到对应仓库与证据提交;链接说明打开的具体内容。
SOURCE+
TEST+
DOCUMENT+
CI+
本案例未绑定远端 CI;只展示该提交的本地回放与文档证据。