前言
关于锁,相信大家都不陌生,一般我们用其在多线程环境中控制对共享资源的并发访问
单服务下,用 JDK 中的 synchronized
或 Lock
的实现类可实现对共享资源的并发访问
分布式服务下,JDK 中的锁就显得力不从心了,分布式锁也就应运而生了
分布式锁的实现方式有很多,常见的有如下几种
基于 MySQL,利用行级悲观锁(select ... for update)
基于 Redis,利用其 (setnx + expire) 或 set
基于 Zookeeper,利用其临时目录和事件回调机制
具体的实现细节就不展开了,网上资料很多。
分布式锁的特点
分布式锁是一种在分布式系统中用来确保多个节点在某一时刻只有一个节点能够执行某个操作的机制。结合 Java 中自身所带的锁,分布式锁的主要要特点如下所示:
互斥性:在同一时间内,只有一个节点能够持有锁,从而保证操作的原子性。
安全性:分布式锁必须能够保证在分布式系统中,即使在网络分区或其他异常情况下,也不会出现多个节点同时持有锁的情况。
性能:分布式锁应该具有高性能,能够在高并发环境下快速响应锁的请求和释放。
可靠性:即使在部分节点失败的情况下,分布式锁也应该能够正常工作,保证系统的稳定性。
容错性:分布式锁应该能够处理节点故障,并且在节点恢复后能够正确地恢复锁的状态。
可扩展性:随着系统规模的扩大,分布式锁应该能够适应更多的节点和更大的负载。
自动续期:在某些实现中,持有锁的节点可能会自动续期,以防止在长时间操作中锁被意外释放。
锁超时:分布式锁应该有超时机制,以避免死锁的发生。
监控与告警:分布式锁的实现通常包括监控机制,以便在锁出现问题时能够及时告警。
易用性:分布式锁应该易于集成和使用,开发者可以通过简单的API调用来管理锁。
一致性:在某些场景下,分布式锁需要保证操作的一致性,例如在分布式数据库事务中。
可重入性:一些分布式锁实现可能支持可重入性,即同一个线程可以多次请求同一把锁。
专一释放:谁加的锁就只有它能释放这把锁。
为什么会出现这种错乱释放的问题了,举个例子就理解了
线程 T1 对资源 lock_zhangsan 加了锁,由于某些原因,加锁业务还未执行完,锁过期自动释放了,此时线程 T2 对资源 lock_zhangsan 加锁成功
T2 执行业务的时候,T1 业务执行完后释放资源 lock_zhangsan 的锁,结果把 T2 加的锁给释放了
公平与非公平:考虑获取锁的公平性。
公平锁:多个线程按照申请锁的顺序去获得锁,所有线程都