搜索

分布式锁


发布时间: 2022-11-24 21:37:01    浏览次数:96 次

1 什么是分布式锁?

分布式锁,即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题,而分布式锁,就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是,分布式系统中竞争共享资源的最小粒度从线程升级成了进程。相对应的是线程锁、进程锁。

线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如synchronized是共享对象头,显示锁Lock是共享某个变量(state)。

进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁。

分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。

 

2 分布式锁的实现方式

基于数据库实现分布式锁,基于Zookeeper实现分布式锁,基于reids实现分布式锁

2.1 基于数据库实现分布式锁

使用专用的数据表:

 

 

 

适用场景:没有其他中间件可以使用,需要加锁的资源恰好有对应的数据表

优点:理解起来简单,不需要维护其他中间件

缺点:需要自己实现加锁/解锁过程,性能较差

 

2.2 基于数据库实现分布式锁基于Zookeeper实现分布式锁

线程去创建/resource_name子节点时会自动编号,第一个编号是/0000001。

第一个线程去创建锁成功并且发现编号是/0000001并且是最小编号,那就直接保留执行程序;

第二个线程再去获取锁时,创建的子节点会自动编号为/0000002,该线程会发现这个节点不是最小节点,就向上一个节点/0000001设置一个watcher监视器,待/0000001线程执行完毕释放的时候就直接触发/0000002执行程序;

第三个个线程再去获取锁时,创建的子节点会自动编号为/0000003,该线程会发现这个节点不是最小节点,就向上一个节点/000000x设置一个watcher监视器,待/000000x线程执行完毕释放的时候就直接触发/0000003执行程序;

 

 

 

解锁流程:

  • 进行重入的判断(利用ThreadLocal)
    • 若为重入,在重入次数减1,返回
  • 删除zookeeper上的有序节点

 

2.3 基于reids实现分布式锁

redis(remote dictionary server)是一个k-v存储中间件。

关键点:

a. 对key不设置过期时间,由Redisson在加锁成功后给维护一个watchdog看门狗,watchdog负责定时监听并处理,在锁没有被释放且快要过期的时候自动对锁进行续期,保证解锁前锁不会自动失效
b. 通过Lua脚本实现了加锁和解锁的原子操作
c. 通过记录获取锁的客户端id,每次加锁时判断是否是当前客户端已经获得锁,实现了可重入锁。

redis分布式锁实现原理图

 

 加锁后开启一个守护线程进行监听"看门狗"。Redisson超时时间默认设置30s,线程每10s调用一次判断锁还是否存在,如果存在则延长锁的超时时间。

 

 

 

资源:

https://www.cnblogs.com/Mufasa/p/15978320.html

https://blog.csdn.net/qq_42764269/article/details/122412431

 

免责声明 分布式锁,资源类别:文本, 浏览次数:96 次, 文件大小:-- , 由本站蜘蛛搜索收录2022-11-24 09:37:01。此页面由程序自动采集,只作交流和学习使用,本站不储存任何资源文件,如有侵权内容请联系我们举报删除, 感谢您对本站的支持。 原文链接:https://www.cnblogs.com/ningshare/p/16916297.html