题目重点:定位锁等待来源,比较减少事务范围、分散热点与保持业务不变量。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 明确问高并发写下锁冲突处理;具体表、锁粒度和隔离等级缺失。练习库存扣减与多行转账两个业务例子,不保证对应实际schema。
- 业务不变量优先:库存不负、转账两侧原子。吞吐提高不能靠删掉必要锁或让失败静默成功。
解题路线
- 先采集wait graph、持锁事务时长、热点key、执行计划和重试量,区分死锁、长事务阻塞、热点串行化与扫描锁范围大。CPU低不代表服务无瓶颈,线程可能在等锁。
- 将网络调用移出事务、建立命中索引、只锁需要的行,并在多行更新时使用统一锁顺序降低deadlock。死锁仍可能发生,要让被中止事务幂等重试且有退避上限。
- 库存用权威条件更新quantity≥requested的原子操作保证不负;读后应用层减不安全。乐观version CAS适合低冲突,高冲突会产生大量重试,需要按实际分布选。
- 热点计数可以分片,但“实时精确剩余库存”或跨分片账户约束不自动跟着成立。队列串行化同key可控负载,代价是排队延迟和故障恢复;预分配额度则要证明不超卖。
手动走一遍
两事务各锁A/B后想锁对方会成环,统一按账户ID锁减少此模式。库存1,两请求各买1,只有一个条件更新成功;第二个明确缺货而非读到旧1再扣为负。
规模与取舍
同一必须串行的key吞吐上限受每次持锁服务时间限制。缩短10ms到1ms可提升理论上限,但还受IO/CPU/日志限制;分片收益只对允许拆分不变量的业务成立。
易错点与追问
容易失分的边界
- 增reader或线程数解决writer同key锁竞争。
- 无限立刻重试造成retry storm。
- 移动锁而没有重新证明余额/库存不变量。
继续深挖
- 如何处理超时但事务可能已提交?
- 乐观冲突率达到多少应切队列/锁?需要哪些测量?
