分布式锁的3种实现

分布式锁的3种实现

我们在线上部署只有一个应用实例的时候,我们可用sychronized、lock来加锁,但是当部署了多个实例,实例间要对资源进行加锁,就要使用分布式锁了。

我们这里介绍3种分布锁的实现方式:

  1. db
  2. redis
  3. zk

数据库

数据库实现分布式锁的原理有两种一种基于悲观锁,一种基于乐观锁。spring帮助我们提供了一套shedlock的分布式锁。

  1. 悲观锁 shedlock
  2. 乐观锁

zk

我们知道zk的节点分为持久节点、持久顺序节点、临时节点、临时顺序节点。

持久节点: 创建后一直存在,直到主动删除此节点。

持久顺序节点:创建后一直存在,知道主动删除此节点,在zk中,每个父节点会为它的第一级子节点维护一份时序,记录每个子节点创建的先后顺序。

临时节点:在客户端会话失效后节点自动清除,临时节点下面不能创建子节点。

临时顺序节点;在客户端会话失效后节点自动清除,临时节点下面不能创建子节点。

我们可以利用持久节点 + 临时顺序节点的特性来创建分布式锁。

zk持久节点 + 临时顺序节点 : 当客户端尝试获取锁,没有持久节点创建,同时创建临时顺
序节点,当临时顺序节点是最小的节点,则获取到锁,否则监听,当自己持有的临时顺序节点是最小的则获取锁。

redis

我们也可以利用redis的单线程特性,来实现分布式锁。

  1. 利用set和expire实现锁
  2. 利用set ex x nx
  3. 利用redisson
  4. 利用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分布式锁最牛逼的实现

你可能感兴趣的:(分布式,数据库,java)