分布式锁的分布3种实现
我们在线上部署只有一个应用实例的时候,我们可用sychronized、式锁实现lock来加锁,分布但是式锁实现当部署了多个实例,实例间要对资源进行加锁,分布就要使用分布式锁了。式锁实现
我们这里介绍3种分布锁的分布实现方式:
- db
- redis
- zk
数据库
数据库实现分布式锁的原理有两种一种基于悲观锁,一种基于乐观锁。式锁实现spring帮助我们提供了一套shedlock的分布分布式锁。
- 悲观锁 shedlock
- 乐观锁
zk
我们知道zk的式锁实现节点分为持久节点、持久顺序节点、分布临时节点、式锁实现临时顺序节点。分布
持久节点: 创建后一直存在,式锁实现直到主动删除此节点。分布
持久顺序节点:创建后一直存在,知道主动删除此节点,在zk中,每个父节点会为它的第一级子节点维护一份时序,记录每个子节点创建的先后顺序。
临时节点:在客户端会话失效后节点自动清除,临时节点下面不能创建子节点。
临时顺序节点;在客户端会话失效后节点自动清除,临时节点下面不能创建子节点。
我们可以利用持久节点 + 临时顺序节点的特性来创建分布式锁。
zk持久节点 + 临时顺序节点 : 当客户端尝试获取锁,没有持久节点创建,同时创建临时顺
序节点,当临时顺序节点是最小的节点,则获取到锁,否则监听,当自己持有的临时顺序节点是最小的则获取锁。
redis
我们也可以利用redis的单线程特性,来实现分布式锁。
- 利用set和expire实现锁
- 利用set ex x nx
- 利用redisson
- 利用redisson + redlock
set和expire
我们可以分别利用set命令实现加锁及expire处理死锁问题或进程意外退出没有释放锁。
这种方案有缺点就是set和expire不是原子执行,当set执行完进程崩溃了,锁就永远无法释放。
set ex px nx
我们可以利用set ex px nx的方案来实现保障set和expire的原子性。
但是设置过期时间这个方案有缺点,过期时间设置的长了,导致效率低下,太短又会存在过期时间太短,业务逻辑还未执行完,锁被释放了。
redisson
redisson可以避免过期时间太长太短的问题,有一个守护进程,定时判断,锁是否存在,存在则延长锁的到期时间。
redisson: 是一个在redis的基础上实现的java驻内存数据网路,redisson底层采用netty网络框架。
redisson封装的redlock
由于单台redis机器,会存在机器故障挂掉的可能性,因此在上面的基础上,又提出了redlock:5台不同步的master,当获得锁时分别从这5台机器上获取锁,当大于等于3台获取到锁,则认为获取到了锁。
redisson给我们封装好了api。
参考
schedulerlock分布式锁原理
什么是分布式锁?实现分布式锁的三种方式
redlock: redis分布式锁最牛逼的实现