分布式锁

数据库分布式锁

Redis实现分布式锁

ZooKeeper实现分布式锁

=======》

1.「锁的互斥性」:在分布式集群应用中,共享资源的锁在同一时间只能被一个对象获取。

2. 「可重入」:为了避免死锁,这把锁是可以重入的,并且可以设置超时。

3. 「高效的加锁和解锁」:能够高效的加锁和解锁,获取锁和释放锁的性能也好。

4. 「阻塞、公平」:可以根据业务的需要,考虑是使用阻塞、还是非阻塞,公平还是非公平的锁。

数据库分布式锁

在数据库的分布式锁的实现中,分为「悲观锁和乐观锁」「悲观锁的实现依赖于数据库自身的锁机制实现」

--》悲观锁

当一个数据库表被加上了排它锁,其它的客户端是不能够再对加锁的数据行加任何的锁,只能等待当前持有锁的释放锁。

排它锁是基于InnoDB存储引擎的,在执行操作的时候,在sql中加入for update,可以给数据行加上排它锁。

在代码的层面上使用connection.commit();,便可以释放锁,但是数据库复杂的加锁和解锁、事务等一系列消耗性能的操作,终归是无法抗高并发。

--》乐观锁

数据库乐观锁的方式实现分布式锁是基于「版本号控制」的方式实现,类似于「CAS的思想」,它认为操作的过程并不会存在并发的情况,只有在update version的时候才会去比较。

Redis实现的分布式锁:

Redis实现分布式锁的 方式,可以使用setnx、getset、expire、del这四个命令来实现。

  1. setnx:命令表示如果key不存在,就会执行set命令,若是key已经存在,不会执行任何操作。
  2. getset:将key设置为给定的value值,并返回原来的旧value值,若是key不存在就会返回返回nil 。
  3. expire:设置key生存时间,当当前时间超出了给定的时间,就会自动删除key。
  4. del:删除key,它可以删除多个key,语法如下:DEL key [key …],若是key不存在直接忽略。

ZK实现的分布式锁:

ZK实现的分布式锁的原理是基于一个「临时顺序节点」实现的,开始的时候,首先会在ZK中创建一个ParentLock持久化节点。

 当有client1请求锁的时候,,就会在ParentLock下创建一个临时顺序节点

 当client1创建完临时顺序节点后,就会检查ParentLock下面的所有的子节点,会判断自己前面是否还有节点,此时明显是没有的,所以获取锁成功

当第二个客户端client2进来获取锁的时候,也会执行相同的逻辑,会先在创建一个临时的顺序节点,并且序号是排在第一个节点的后面

 并且第二步也会判断ParnetLock下面的所有的子节点,看自己是否是第一个,明显不是,此时就会加锁失败。

那么此时client2会创建一个对client1的lock1的监听(Watcher),用于监听lock1是否存在,同时client2会进入等待状态

 当client1执行完自己的业务逻辑之后,就会删除锁,删除锁很简单,就是把这个lock1给删除掉

 此时就会通知client2:监听的lock1已经被删除,锁被释放,此时client2创建的lock2也就变成了第一个节点,尝试获取所得时候就会获取锁成功。

原文地址:https://www.cnblogs.com/KL2016/p/14605126.html