1. 分布式锁的核心价值与设计原则
在分布式系统中,多个服务实例对共享资源的并发访问是一个经典难题。想象一下电商平台的库存扣减场景:当两个用户同时下单购买最后一件商品时,如果没有分布式锁的保护,系统可能会错误地认为库存充足,导致超卖问题。分布式锁正是为了解决这类跨进程、跨机器的资源竞争问题而诞生的。
1.1 从本地锁到分布式锁的演进
在单体应用时代,我们使用Java中的synchronized或ReentrantLock等本地锁就能解决多线程并发问题。这些锁机制通过JVM内部的内存操作实现互斥,性能极高且易于使用。但随着系统架构演进为分布式微服务,本地锁的局限性立即显现:
- 作用范围仅限于单个JVM进程
- 无法跨服务实例实现全局互斥
- 在容器化部署环境下完全失效
java复制// 本地锁在分布式环境中的失效示例
public class InventoryService {
private final Object lock = new Object();
private int stock = 100;
public void deduct() {
synchronized(lock) { // 只能锁住当前实例的调用
if (stock > 0) {
stock--;
}
}
}
}
1.2 分布式锁的七大核心特性
一个生产级的分布式锁必须满足以下设计要求:
| 特性 | 描述 | 重要程度 |
|---|---|---|
| 互斥性 | 在任意时刻,只有一个客户端能持有锁 | 必须 |
| 防死锁 | 即使持有锁的客户端崩溃,锁也最终能够被释放 | 必须 |
| 安全释放 | 锁只能被持有它的客户端释放,不能被其他客户端误删 | 必须 |
| 容错性 | 锁服务本身具有高可用性,部分节点故障不影响锁的正常使用 | 高 |
| 可重入性 | 同一个客户端(线程)可以多次获取同一个锁 | 推荐 |
| 公平性 | 按照请求顺序获取锁,避免饥饿 | 可选 |
| 阻塞/非阻塞 | 支持获取不到锁时阻塞等待或立即返回 | 推荐 |
提示:在实际项目中,我们通常需要根据业务场景在这些特性之间做出权衡。例如秒杀系
