分布式锁的粒度(Granularity)是分布式系统中一个非常重要的概念,它指的是锁所保护的资源或数据范围的大小。
简单来说,就像现实生活中的锁:
- 粗粒度锁:像锁住整个大楼的大门
- 细粒度锁:像锁住大楼里每个办公室的门
粒度级别的详细说明
1. 粗粒度锁(Coarse-Grained Lock)
特点:一把锁保护大量资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class OrderSystem { private DistributedLock globalLock = new RedisLock("ORDER_SYSTEM_LOCK"); public void processOrder() { globalLock.lock(); try { } finally { globalLock.unlock(); } } }
|
2. 细粒度锁(Fine-Grained Lock)
特点:针对特定资源加锁
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class OrderService { public void updateOrder(String orderId) { DistributedLock orderLock = new RedisLock("ORDER_LOCK:" + orderId); orderLock.lock(); try { } finally { orderLock.unlock(); } } }
|
3. 中等粒度锁(Medium-Grained Lock)
介于两者之间
1 2 3 4 5 6 7 8 9 10 11 12
| public class UserService { public void processUserOrder(Long userId) { DistributedLock userLock = new RedisLock("USER_LOCK:" + userId); userLock.lock(); try { } finally { userLock.unlock(); } } }
|
粒度选择的权衡
| 维度 |
粗粒度锁 |
细粒度锁 |
| 并发性能 |
❌ 低(串行化严重) |
✅ 高(并发度高) |
| 系统吞吐量 |
❌ 低 |
✅ 高 |
| 实现复杂度 |
✅ 简单 |
❌ 复杂 |
| 死锁风险 |
✅ 低(锁数量少) |
❌ 高(锁数量多) |
| 资源争用 |
❌ 高 |
✅ 低 |
| 内存开销 |
✅ 低 |
❌ 高 |
实际应用场景
适合粗粒度锁的场景
1 2 3 4 5 6 7 8 9 10 11 12
| public class SystemManager { public void systemMaintenance() { DistributedLock maintenanceLock = new RedisLock("SYSTEM_MAINTENANCE"); maintenanceLock.lock(); try { } finally { maintenanceLock.unlock(); } } }
|
适合细粒度锁的场景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class InventoryService { public boolean deductStock(Long itemId, Integer quantity) { String lockKey = "INVENTORY_LOCK:" + itemId; DistributedLock lock = new RedisLock(lockKey); lock.lock(); try { Item item = itemRepository.findById(itemId); if (item.getStock() >= quantity) { item.setStock(item.getStock() - quantity); itemRepository.update(item); return true; } return false; } finally { lock.unlock(); } } }
|
最佳实践建议
-
从业务需求出发:
- 如果业务允许一定程度的数据不一致,考虑更细的粒度
- 如果需要强一致性,可能需要较粗的粒度
-
渐进式优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class PaymentService { public void processPayment(Long userId, String orderId) { String lockKey = "PAYMENT_USER:" + userId; } public void processPaymentV2(Long userId, String orderId) { String lockKey = "PAYMENT_ORDER:" + orderId; } }
|
-
避免过度细化:
- 太细的粒度会增加系统复杂度
- 可能引入死锁问题
- 增加锁管理的开销
总结
分布式锁的粒度本质是在并发性能与系统复杂度之间的权衡:
- 粗粒度:简单可靠,但性能差
- 细粒度:性能好,但复杂度高
选择合适粒度的关键是深入理解业务场景、数据访问模式和性能要求,通过监控和测试找到最适合的平衡点。