常见分布式锁实现方式

0x01、基于MySQL实现分布式锁
基于分布式锁的实现,首先肯定是想单独分离出一台mysql数据库,所有服务要想操作文件(共享资源),那么必须先在mysql数据库中插入一个标志,插入标志的服务就持有了锁,并对文件进行操作,操作完成后,主动删除标志进行锁释放,其与服务会一直查询数据库,看是否标志有被占用,直到没有标志占用时自己才能写入标志获取锁 。
但是这样有这么一个问题,如果服务(jvm1)宕机或者卡顿了,会一直持有锁未释放,这样就造成了死锁,因此就需要有一个监视锁进程时刻监视锁的状态,如果超过一定时间未释放就要进行主动清理锁标记,然后供其与服务继续获取锁 。
如果监视锁字段进程和jvm1同时挂掉,依旧不能解决死锁问题,于是又增加一个监视锁字段进程,这样一个进程挂掉,还有另一个监视锁字段进程可以对锁进行管理 。这样又诞生一个新的问题,两个监视进程必须进行同步,否则对于过期的情况管理存在不一致问题 。
因此存在以下问题,并且方案变得很复杂:

  • 监视锁字段进程对于锁的监视时间周期过短,仍旧会造成多售(jvm1还没处理完其持有的锁就被主动销毁,造成多个服务同时持有锁进行操作) 。
  • 监视锁字段进程对于锁的监视时间周期过长,会造成整个服务卡顿过长,吞吐低下 。
  • 监视锁字段进程间的同步问题 。
  • 当一个jvm持有锁的时候,其余服务会一直访问数据库查看锁,会造成其余jvm的资源浪费 。
0x02、基于redis实现分布式锁相比较于基于数据库实现分布式锁的方案来说,基于缓存来实现在性能方面会表现的更好一点,Redis就是其中一种 。由于Redis可以设置字段的有效期,因此可以实现自动释放超期的锁,不需要多个监视锁字段进程进行锁守护,可以依旧存在上述mysql实现中除了3以外1、2、4中的问题 。

常见分布式锁实现方式

文章插图
 
 
0x03、基于Zookeeper实现分布式锁基于以上两种实现方式,有了基于zookeeper实现分布式锁的方案 。由于zookeeper有以下特点:
  • 维护了一个有层次的数据节点,类似文件系统 。
  • 有以下数据节点:临时节点、持久节点、临时有序节点(分布式锁实现基于的数据节点)、持久有序节点 。
  • zookeeper可以和client客户端通过心跳的机制保持长连接,如果客户端链接zookeeper创建了一个临时节点,那么这个客户端与zookeeper断开连接后会自动删除 。
  • zookeeper的节点上可以注册上用户事件(自定义),如果节点数据删除等事件都可以触发自定义事件 。
  • zookeeper保持了统一视图,各服务对于状态信息获取满足一致性 。
Zookeeper的每一个节点,都是一个天然的顺序发号器 。
在每一个节点下面创建子节点时,只要选择的创建类型是有序(EPHEMERAL_SEQUENTIAL 临时有序或者PERSISTENT_SEQUENTIAL 永久有序)类型,那么,新的子节点后面,会加上一个次序编号 。这个次序编号,是上一个生成的次序编号加一
比如,创建一个用于发号的节点“/test/lock”,然后以他为父亲节点,可以在这个父节点下面创建相同前缀的子节点,假定相同的前缀为“/test/lock/seq-”,在创建子节点时,同时指明是有序类型 。如果是第一个创建的子节点,那么生成的子节点为/test/lock/seq-0000000000,下一个节点则为/test/lock/seq-0000000001,依次类推,等等 。

常见分布式锁实现方式

文章插图
 
参考来源:
https://www.cnblogs.com/jing99/p/11607094.html

【常见分布式锁实现方式】


    推荐阅读