沉默是金,总会发光
大家好,我是沉默
在分布式系统的世界里,高并发就像是一场没有硝烟的战争
——订单创建、库存扣减、支付回调、超时关单……
每一个环节都可能在同一毫秒内被成百上千的请求冲击。
很多开发者的第一反应是:
“加个分布式锁吧!”
但锁不是万能,甚至可能拖慢系统。
真正的高手,会先分析业务场景,精准选择最优解
——有时不用锁,反而更优雅、更高效
今天,我就带你拆开高并发的“黑箱”,看看 悲观锁、乐观锁、无锁方案 是如何在不同战场各显神通,让你选出最优解。
**-**01-
业务场景分析
解决并发问题,第一步不是选锁,而是:
- 梳理业务场景
- 找到该场景下的冲突点
- 再决定是否加锁、加什么锁
有些场景甚至不需要锁,只靠 一条 SQL 就能解决,而且还是性能最优解。
- 02-
并发防控的三大方案
无论方案多花哨,本质上就三类:
| 方案 | 核心思想 | 优点 | 缺点 | 典型场景 |
|---|---|---|---|---|
| 悲观锁 | 先加锁再操作 | 防冲突强,fail-fast | 降并发、锁等待 | 高频写、冲突多 |
| 乐观锁 | 先操作再校验版本 | 高并发友好 | 冲突高时失败多 | 冲突低、可重试 |
| 无锁方案 | 靠数据库天然行锁 | 无业务锁、快 | 场景有限 | 秒杀、不超卖 |
- 悲观锁(Pessimistic Lock)
假设冲突频繁发生,先拿锁再执行。
案例:订单创建(高并发、幂等控制)
@DistributeLock(keyExpression = "#req.identifier", scene = "ORDER_CREATE")public OrderResponse create(OrderCreateRequest req) { orderValidatorChain.validate(req); // 库存扣减 + 创建订单}
适合:写多读少、冲突高、需 fail-fast
2. 乐观锁(Optimistic Lock)
假设冲突概率低,先处理再用版本号做 CAS 校验。
案例:支付回调(并发低、有状态机)
UPDATE trade_orderSET lock_version = lock_version + 1, order_state = #{orderState}WHERE order_id = #{orderId} AND lock_version = #{lockVersion}
适合:读多写少、可重试、冲突低
3. 无锁方案(SQL 行锁)
业务代码不显式加锁,直接靠 MySQL 行锁串行化更新。
案例:秒杀库存扣减(只关心不超卖)
UPDATE collectionSET saleable_inventory = saleable_inventory - #{quantity}WHERE id = #{id} AND saleable_inventory - frozen_inventory >= #{quantity}
适合:极高并发、关注正确性而非顺序
- 03-
如何选?
-
写多读少、冲突高 → 悲观锁
-
读多写少、冲突低 → 乐观锁
-
对并发不敏感,只需防止数据错误 → 无锁(SQL 行锁)
**-**04-
总结
你的系统,可能正因为「乱加锁」在白白牺牲性能。
高手的思路是:先分析场景痛点,再选方案,而不是一上来就加锁。
最后留个问题:
为什么秒杀库存扣减不用乐观锁,甚至不用分布式锁?
如果你还没想明白,不妨回到上面的 SQL 细细琢磨。
提示:答案藏在 MySQL 行锁 和 WHERE 条件 里,
并不是不需要加锁,而是把加锁的操作交给了DB。
**-**05-
粉丝福利
点点关注,送你 SQL Server 性能调优实战,如果你正在优化 SQL,又或者刚准备调优性能。可以仔细阅读一下,或许对你有所帮助!