一、基于数据库
创建一张锁表,通过操作该表中的数据来实现。
需要加锁时,就在该表中增加一条记录,想要释放锁时,就删除这条记录。
缺点:1、强依赖数据库的可用性,一旦数据库挂掉,会导致业务系统不可用。
2、锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁。
二、基于zookeeper
左边的整个区域表示一个Zookeeper集群,locker是Zookeeper的一个持久节点,node_1、node_2、node_3是locker这个持久节点下面的临时顺序节点。client_1、client_2、client_n表示多个客户端,Service表示需要互斥访问的共享资源。
这种方式数据完整性很高,但是管理起来很复杂。
三、Dubbo一致性哈希+同步锁(synchronized)
利用dubbo的一致性hash算法,使得同一个对象映射倒同一个服务上,然后在服务对其加同步锁实现分布式锁。
四、基于缓存(redis)
1、setnx
setnx:进行写入,当且仅当key不存在时,返回1(加锁成功);若key存在,则什么都不做,返回0(锁被占用)。
expire:为key设置一个超时时间,超过这个时间锁会自动释放,避免死锁。
delete:删除key(释放锁)
2、incr
Incr:将key中储存的数字值增一,如果key不存在,那么key的值会先被初始化为0,然后再执行INCR操作。如果incr之后大于1,说明此key正在被别人锁定,否则获得锁。
expire:设置超时时间,超过时间自动释放锁。
del:删除key,释放锁。
3、EXISTS
检查给定 key 是否存在。
4、Redisson
读写锁(ReadWriteLock)。Redisson的分布式可重入读写锁RReadWriteLock, 该对象允许同时有多个读取锁,但是最多只能有一个写入锁。
RReadWriteLock rwlock = redisson.getLock("anyRWLock");
RReadWriteLock rwlock = redisson.getReadWriteLock(key);
//加锁
rwlock.readLock().lock();
rwlock.writeLock().lock();
//加锁,支持过期解锁,10秒钟以后自动解锁,无需调用unlock方法手动解锁
rwlock.readLock().lock(10, TimeUnit.SECONDS);
rwlock.writeLock().lock(10, TimeUnit.SECONDS);
//尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
boolean res = rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
//解锁 lock.unlock();
rwlock.readLock().unlock();
rwlock.writeLock().unlock();