分布式锁

架构设计原则:能不用分布式锁就不用。
但这句话不能停在“经验之谈”,必须理解背后的系统理论。
我给你一个架构级判断框架。

一、先明确:分布式锁的本质是什么?

分布式锁本质是:
在多个进程 / 多实例之间实现互斥访问
它解决的不是一致性问题,而是:
  • 资源竞争协调问题
  • 并发访问冲突问题

二、为什么“能不用就不用”?

因为分布式锁有天然成本:
成本类型
说明
可用性降低
锁服务挂了,业务全阻塞
性能下降
所有请求串行化
死锁风险
续期失败或异常
复杂度
需要处理过期、误删、主从切换
CAP影响
Redis锁不保证强一致
你加锁,本质是:
主动降低系统吞吐换取互斥
架构设计第一原则是:
提升并发能力,而不是压制并发

三、什么时候必须用分布式锁?

只有在以下三种场景之一成立时。

① 跨资源协调(无法通过数据库事务解决)

例如:
  • 同时操作数据库 + 文件系统
  • 数据库 + 第三方接口
  • 数据库 + MQ
例如:
扣库存发送短信调用外部支付接口
你无法用一个本地事务包住。
必须通过“互斥”避免重复执行。

② 全局唯一执行任务

典型场景:
  • 定时任务集群
  • 批处理Job
  • 数据迁移脚本
例如:
10个服务实例
只允许1个执行定时任务
这时分布式锁是合理的。

③ 非结构化共享资源

例如:
  • 生成全局编号
  • 操作共享缓存结构
  • 操作共享内存结构
数据库无法约束时。

四、什么时候不应该使用分布式锁?

这是架构师必须掌握的。

❌ 1. 可以用数据库唯一索引解决

例如:
防止重复订单
UNIQUE(userId, productId)
强一致
无锁
高可靠
优于Redis锁。

❌ 2. 可以用状态机 + 乐观锁解决

例如库存扣减:
update stockset count = count - 1where id = 1 and count > 0
这是CAS模式。
比加锁高效。
 
核心思想:
用“当前状态”作为并发控制条件
比如:
update Expenseset Status = 'Processing'where BusinessId = @idand Status = 'Init'
影响行数:
  • =1 → 成功(说明没人改过)
  • =0 → 失败(说明已被修改)
这就天然实现了:
  • 并发控制
  • 幂等
  • 互斥
而且没有真正“锁住”任何东西。

❌ 3. 可以用幂等设计解决

前端给唯一id 后端数据库表增加唯一约束 通过数据库来解决
这是金融系统标准方案。

❌ 4. 高并发场景

秒杀系统如果加分布式锁:
直接废掉吞吐。
应该使用:
  • 预扣库存
  • 队列削峰
  • 原子扣减

五、架构判断流程(建议你记住)

当你遇到并发问题时:

第一步:能不能用数据库约束?

  • 唯一索引?
  • 行级锁?
  • 乐观锁?
如果能,用数据库。

第二步:能不能用幂等?

  • Token
  • 状态机
  • 版本号
如果能,用幂等。

第三步:是否必须跨实例互斥?

如果必须:
再考虑分布式锁。

六、架构师级认知

分布式锁不是一致性工具。
真正的一致性靠:
  • 事务
  • 唯一约束
  • 状态机
  • 消息最终一致性
分布式锁只是:
降低冲突概率的协调机制
这点非常重要。

七、你现在销账系统的情况

你当前:
  • 单数据库
  • 强一致要求
  • 业务ID唯一
结论:
你根本不需要 Redis 分布式锁。
数据库已经是最强锁。

八、什么时候我会用Redis锁?

我会用在:
  • 集群定时任务
  • 防止缓存击穿
  • 防止某段代码并发执行
而不会用在:
  • 金融核心交易
  • 强一致账务系统

九、面试高级回答模板

如果面试官问:
架构设计时是否必须用分布式锁?
你可以回答:
分布式锁属于最后手段。
优先考虑数据库约束、乐观锁或幂等设计。
只有在跨实例、跨资源、无法通过事务解决的互斥场景下才会使用。
并且根据一致性要求选择 Redis 或 ZooKeeper。
这就是架构思维。

十、送你一句核心判断

如果你的系统还能用数据库事务解决问题,就不要引入分布式锁。
posted @ 2026-03-05 16:02  12不懂3  阅读(54)  评论(0)    收藏  举报
创作不易,请勿抄袭,欢迎转载!