council(review): PerformanceBenchmarker - round2 code-verified assessment update
- Code-level verification of SeatMapService + SeatSkuService - Cross-review with BackendArchitect/FrontendDeveloper/SecurityEngineer reports - Critical correction: ShopXO dec() atomic UPDATE is main oversell defense, FOR UPDATE SKIP LOCKED is not needed for inventory deduction - R2 updated P table: P1-R2 (full scan), P2-R2 (getSoldSeats missing), P3-R2 (no delta polling), P4-R2 (inventory logic inconsistency) - All 4 members vote C (dual parallel), consensus confirmed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>council/PerformanceBenchmarker
parent
92df8d2e14
commit
da448b8f58
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
**Date:** 2026-05-26
|
||||
**Agent:** council/PerformanceBenchmarker
|
||||
**Round:** 2(更新版 — 基于实测代码 + 其他成员报告)
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -115,3 +116,79 @@ Tree API 将座位结构按 `venue→session→room→section` 分层,前端
|
|||
- **A(后端优先)**:合理,但 seatSpecMap 注入本身是功能问题,性能 P0(超卖+索引)应同步修复
|
||||
- **B(前端优先)**:风险高,基础交易正确性未解决时前端开发是无根之木
|
||||
- **D(Phase 4 优先)**:Phase 4(Tree API)是锦上添花,Phase 2/3 的超卖漏洞是雪中送炭,不可交换优先级
|
||||
|
||||
---
|
||||
|
||||
## Round 2 更新(基于实测代码 + 交叉审查)
|
||||
|
||||
### R2-1:代码级验证后的修正
|
||||
|
||||
| 问题 | Round 1 评估 | Round 2 实测 | 修正 |
|
||||
|------|-------------|-------------|------|
|
||||
| `SeatMapService::buildSeatSpecMap()` 全量扫描 | ❌ 性能缺陷 | ✅ **意图正确**(需要显示已售座位为灰色) | 降级为 P2(缺陷→设计权衡) |
|
||||
| `GoodsSpecBase` 全量拉取含已售座位 | ❌ 无过滤 | ✅ 含 `inventory=0` 是设计需要 | 需另开增量 API 解决 |
|
||||
| FOR UPDATE SKIP LOCKED | ❌ 完全缺失 | ⚠️ `verifyTicket()` 有 `lock(true)`,但无 SKIP LOCKED | 修正为 P2(非P0) |
|
||||
|
||||
**修正后的 P 列表:**
|
||||
|
||||
| # | 严重程度 | 问题 | 位置 | 量化 |
|
||||
|---|----------|------|------|------|
|
||||
| **P1-R2** | 🔴 严重 | `SeatMapService` seatmap API **无分页/无缓存过滤**,每次全量拉取所有座位(5000+ 行/MB 级)| `SeatMapService.php:132` | 响应体 1-5 MB,500 并发 = 2.5GB/s |
|
||||
| **P2-R2** | 🟡 高 | `SeatSkuService::getSoldSeats()` **方法缺失**(BackendArchitect P0-1)| `SeatSkuService.php` | soldSeats API stub,返回空数组 |
|
||||
| **P3-R2** | 🟡 高 | 无细粒度库存轮询 API,所有用户每次轮询全量 seatSpecMap,DB QPS 居高不下 | `SeatMapService` + 前端轮询 | 500 并发用户 = 2500 SELECT/s |
|
||||
| **P4-R2** | 🟡 高 | 轮询时 `inventory > 0` vs `inventory = 0` 反推已售——两套逻辑不一致 | `SeatSkuService.php:540` vs `Admin.php:939` | 状态不一致窗口 |
|
||||
| **P5-R2** | 🟢 中 | `verifyTicket()` 有 `lock(true)` 但无 `SKIP LOCKED`,并发核销会阻塞 | `TicketService.php:247` | 低频,但可优化 |
|
||||
| **P6-R2** | 🟢 中 | `onOrderPaid` 无事务包装,部分票生成失败时无法回滚 | `TicketService.php:25` | P2,参考 SecurityEngineer 评估 |
|
||||
|
||||
### R2-2:交叉审查后的关键发现
|
||||
|
||||
**与 BackendArchitect 交叉确认:**
|
||||
- BackendArchitect 的 P0-1(`getSoldSeats()` 缺失)与我的 P2-R2 完全一致,**双重确认**
|
||||
- BackendArchitect 的路径2(绕过购物车直购)建议与性能 P1 完全一致——票务单座库存不走购物车,直接 `SELECT ... FOR UPDATE SKIP LOCKED` → 下单,无中间态
|
||||
|
||||
**与 SecurityEngineer 交叉确认:**
|
||||
- SecurityEngineer 的"并发发票竞态"(issueTicket 无锁)对应我的 P2(TOCTOU 窗口)
|
||||
- SecurityEngineer 的结论"P0 可接受(ShopXO 原子扣减兜底)"与我的量化一致:ShopXO `dec()` 原子条件 UPDATE 是主要防线,issueTicket 的 TOCTOU 只在"支付成功但扣减失败回滚"场景触发,概率极低
|
||||
- **关键修正**:SecurityEngineer 明确指出 `BuyService.php` 的 `WHERE inventory >= N` + `dec()` 是原子操作,不需要 FOR UPDATE SKIP LOCKED。我的 Round 1 评估"无 FOR UPDATE SKIP LOCKED=超卖"是**错误归因**——真正需要的场景是:
|
||||
1. 并发核销(`verifyTicket`):已有 `lock(true)`,加 SKIP LOCKED 是优化
|
||||
2. 并发发票(`issueTicket`):TOCTOU 竞态,P1-suggestion(唯一索引修复)
|
||||
3. 并发下单扣库存:ShopXO `dec()` 兜底,不需要
|
||||
|
||||
### R2-3:量化性能基准
|
||||
|
||||
以 1000 座 × 5 场 = **5000 GoodsSpecBase 行**(含库存 1)估算:
|
||||
|
||||
| 操作 | 当前性能 | 优化后目标 | 优化手段 |
|
||||
|------|---------|-----------|---------|
|
||||
| seatmap API(GetSeatMap) | ~800ms(含全量 DB 查询 × 3) | < 200ms | 加 `(goods_id, inventory, id)` 复合索引 |
|
||||
| 前端轮询(每用户) | 每次 1-3 MB 全量 seatSpecMap | 每次 < 10 KB 差量 | 新增 `GET /seatmap/delta?goods_id=&since=` 差量 API |
|
||||
| 500 并发轮询总带宽 | ~1.5 GB/s(均全量拉取) | ~20 MB/s | 差量轮询 + 浏览器 localStorage |
|
||||
| DB QPS(500 并发) | 2500 SELECT/s(均全量查询) | < 500 SELECT/s | 差量轮询 + 缓存层 |
|
||||
|
||||
### R2-4:共识确认
|
||||
|
||||
**四位成员一致投票 C(双线并行)**,跨维度共识已形成。
|
||||
|
||||
Round 2 性能评估结论与 BackendArchitect / FrontendDeveloper / SecurityEngineer 评估一致,无冲突。
|
||||
|
||||
---
|
||||
|
||||
## 最终投票(Round 2)
|
||||
|
||||
**议题:下一步主攻方向**
|
||||
|
||||
**投票:C — 双线并行**
|
||||
|
||||
**理由:**
|
||||
|
||||
1. **性能 P0 已重新校准**:真正需要立即修复的是 `SeatMapService` 全量扫描(加索引)和 `getSoldSeats()` 方法缺失(解锁 API 链路),两者均与 BackendArchitect 的 P0 修复重叠,可并行完成
|
||||
2. **超卖问题归因修正**:ShopXO 原子扣减(`dec()`)已是主防线,issueTicket TOCTOU 是 P1-suggestion,不阻塞当前开发
|
||||
3. **双线并行最大化**:后端修复 P0 Gap + 索引,前端推进 H5 loadSoldSeats 实现和 uniapp 选座组件,两者独立无依赖
|
||||
4. **轮询优化可分期**:差量轮询 API(P3)作为 Phase 2.5 独立推进,不阻塞 Phase 3 上线
|
||||
|
||||
**对其他成员提案的评估:**
|
||||
|
||||
- **BackendArchitect 选 C**:完全认同。P0 Gap 修复和性能 P0 修复工作量均可控(1-2 天),不应作为阻塞项
|
||||
- **FrontendDeveloper 选 C**:完全认同。H5 ticket_detail.html 完全独立于 API Gap,可立即推进 loadSoldSeats()
|
||||
- **SecurityEngineer 选 C**:完全认同。支付链路安全水位已足够(ShopXO 原子扣减兜底 + FOR UPDATE),无 P0 漏洞
|
||||
|
||||
|
|
|
|||
45
plan.md
45
plan.md
|
|
@ -1,4 +1,4 @@
|
|||
# Plan — Round 1 Performance Evaluation (2026-05-26)
|
||||
# Plan — Round 2 Performance Evaluation (2026-05-26)
|
||||
|
||||
> Agent: council/PerformanceBenchmarker
|
||||
|
||||
|
|
@ -10,8 +10,9 @@
|
|||
|
||||
- [x] **Task 1**: [Done: PerformanceBenchmarker] 检查 git log 和文件结构
|
||||
- [x] **Task 2**: [Done: PerformanceBenchmarker] 探索 SeatMapService + seatmap API + SKIP LOCKED 实现
|
||||
- [x] **Task 3**: [Done: PerformanceBenchmarker] 输出性能评估报告 → `docs/council-eval-performancebenchmark.md`
|
||||
- [ ] **Task 4**: [Pending] 等待其他成员完成后,汇总至最终报告(西莉雅负责)
|
||||
- [x] **Task 3**: [Done: PerformanceBenchmarker] 输出 Round 1 性能评估报告
|
||||
- [x] **Task 4**: [Done: PerformanceBenchmarker] Round 2:代码实测验证 + 交叉审查其他成员报告
|
||||
- [x] **Task 5**: [Pending] 等待西莉雅汇总最终报告
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -19,9 +20,9 @@
|
|||
|
||||
| 阶段 | 内容 | 状态 |
|
||||
|------|------|------|
|
||||
| **Draft** | Task 1-3(独立评估 + 输出报告) | ✅ 完成 |
|
||||
| **Review** | 等待 BackendArchitect、FrontendDeveloper、SecurityEngineer 完成评估 | ⏳ 等待 |
|
||||
| **Finalize** | 西莉雅汇总所有成员报告,输出综合决策报告 | ⏳ 等待 |
|
||||
| **Draft** | Task 1-3(独立评估 Round 1) | ✅ 完成 |
|
||||
| **Review** | Task 4(代码实测 + 交叉审查) | ✅ 完成 |
|
||||
| **Finalize** | 西莉雅汇总所有成员报告 | ⏳ 等待西莉雅 |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -35,28 +36,34 @@
|
|||
## 投票结果
|
||||
|
||||
**议题:下一步主攻方向**
|
||||
- 投票:**C(双线并行)**
|
||||
- 备选:A(后端优先,补充 seatSpecMap + 性能 P0 同步修复)
|
||||
- 投票:**C(双线并行)**(Round 1 + Round 2 一致)
|
||||
|
||||
详见 `docs/council-eval-performancebenchmark.md`
|
||||
|
||||
---
|
||||
|
||||
## 关键发现摘要
|
||||
## 关键发现摘要(Round 2 修正版)
|
||||
|
||||
| # | 严重程度 | 问题 | 量化 |
|
||||
|---|----------|------|------|
|
||||
| P1 | 🔴 严重 | `GoodsSpecBase` 全量扫描无分页 | 响应体 1-5 MB,TTFB > 2s |
|
||||
| P2 | 🔴 严重 | 无 `FOR UPDATE SKIP LOCKED`,超卖竞态 | 超卖率 = f(并发 × 事务时长) |
|
||||
| P3 | 🟡 高 | 轮询无差异化,缓存击穿 | 500 并发 DB QPS = 2500+ |
|
||||
| P4 | 🟡 高 | SoldSeats API stub | 支付后状态短暂不一致 |
|
||||
| P5 | 🟢 中 | 模板缓存 TTL=60s 与轮询周期耦合 | 感知延迟 0-60s |
|
||||
| P1-R2 | 🔴 严重 | seatmap API 全量扫描无缓存过滤 | 500 并发 = 2.5 GB/s |
|
||||
| P2-R2 | 🟡 高 | `SeatSkuService::getSoldSeats()` 方法缺失(与 BackendArchitect P0-1 双重确认) | soldSeats stub |
|
||||
| P3-R2 | 🟡 高 | 无细粒度差量轮询 API,所有用户全量拉取 | 500 并发 = 2500 DB SELECT/s |
|
||||
| P4-R2 | 🟡 高 | inventory > 0 vs =0 两套逻辑不一致 | 状态不一致窗口 |
|
||||
| P5-R2 | 🟢 中 | verifyTicket() 无 SKIP LOCKED | 低频,优化非必须 |
|
||||
| P6-R2 | 🟢 中 | onOrderPaid 无事务包装 | P2(SecurityEngineer 已评) |
|
||||
|
||||
**超卖归因修正(Round 2 关键)**:
|
||||
- ShopXO `dec()` 原子条件 UPDATE = 主要防线,不需要 FOR UPDATE SKIP LOCKED
|
||||
- issueTicket() TOCTOU = P1-suggestion(唯一索引修复),非 P0
|
||||
- verifyTicket() = 已有 `lock(true)`,SKIP LOCKED 是优化非必须
|
||||
|
||||
---
|
||||
|
||||
## 优先级建议
|
||||
## 优先级建议(基于修正后 P 表)
|
||||
|
||||
1. **P0**:实现库存行锁(FOR UPDATE SKIP LOCKED)— 消除超卖
|
||||
2. **P0**:添加 `(goods_id, inventory)` 复合索引 — 消除全表扫描
|
||||
3. **P1**:实现细粒度库存轮询 API(差量更新)— 降低 80% DB 负载
|
||||
4. **P2**:Tree API 实现(Phase 4)
|
||||
1. **P0**:添加 `(goods_id, inventory, id)` 复合索引 → 消除全量扫描
|
||||
2. **P0**:`SeatSkuService::getSoldSeats()` 实现 → 解锁 soldSeats API
|
||||
3. **P1**:新增 `GET /seatmap/delta` 差量轮询 API → 降低 80% 带宽和 DB QPS
|
||||
4. **P1**:加唯一索引 `(order_id, seat_info)`(SecurityEngineer 建议)
|
||||
5. **P2**:Phase 4 Tree API 实现
|
||||
|
|
|
|||
Loading…
Reference in New Issue