一、基本概念

分布式锁,是单机锁的一种扩展,主要是为了锁住分布式系统中不同机器代码的物理块或逻辑块。以此保证不同机器之间的逻辑一致性。

二、一个简单的案例

对DB写操作的双检锁案例

  1. 伪代码如下

    if (可以插入一条数据) {lock {if (可以插入一条数据) {// 插入一条数据}}
    }
  2. 上面代码中的lock如果是单机情况下的锁的话,在一台服务器多线程情况下是没有问题的。但是如果是分布式的情况下,单机的锁只能锁住一台服务器的物理代码块,是无法防住其他机器产生的脏数据的。
  3. 分布式情况下这个lock就需要换成分布式锁以保证数据一致性。

三、分布式锁实现原理

所需的依赖

  1. 一个拥有强一致性的服务发现存储仓库。(保证数据一致性)
  2. 一个具有高可用性的服务发现存储仓库。(保证服务的稳定性)
  3. 在这里我们使用etcd作为服务发现存储仓库。

具体实现原理

我们本次所使用的etcd的能力

  1. etcd节点的保持独占能力。(同一时间只有一台服务器可以拥有节点)
  2. 节点事件监听能力。(可以在节点被释放/占有时通知观察者-服务器)
  3. 节点主动释放能力。(服务器可以主动释放拥有节点)
  4. 节点超时自动释放能力。(超时自动释放节点)

在代码中,需要准备以下几个内容

  1. etcd长监听。(监听etcd节点,在节点变更时作出响应)
  2. 事件队列。(存放争夺etcd节点的方法)
  3. 争夺锁事件。
  4. 等待锁超时事件。(没画在流程图中,在争夺锁事件入队列时注册,持有锁时注销)
  5. 持有锁超时事件。(没画在流程图中,在持有锁时注册,在释放锁时注销)
  6. 释放锁事件。

基本代码流程图

  • 正常代码流程图(markdown画的,有点丑)

    st=>start: 项目启动
    watcher=>operation: 监听etcd
    ed=>end: 等待请求st->watcher->ed
    st=>start: 开始执行lock
    ed=>end: 结束
    watcher=>operation: 监听etcd
    hasEvent=>condition: 事件队列为空
    pushEvent=>operation: 争夺锁事件 入等待队列
    watcherEvent=>operation: etcd节点超时事件和释放事件
    popEvent=>operation: 争夺锁事件 出事件队列
    execute=>operation: 执行被锁住的代码块
    fight=>condition: 争夺锁失败
    unlock=>operation: 释放锁st->fight
    fight(no)->execute->unlock->ed
    fight(yes)->pushEvent->watcherEvent->popEvent->fight
  • 事件细节伪代码

    1. 准备一个清空所有相关事件的万能方法

      假设eventQueue是这种业务对应的事件队列
      假设fightEvent是该次执行的争夺锁事件
      假设clear为清除超时事件的方法
      假设holdEvent为持有锁超时事件
      假设waitEvent为等待锁超时事件
      假设unLockEvent为释放锁事件// 清空所有事件 - clearAll
      eventQueue.remove(fightEvent)
      clear(waitEvent)
      clear(holdEvent)
    2. 监听etcd的两个事件

      // 当etcd锁超时事件或etcd主动释放事件发生时// 争夺锁事件 出事件队列
      fightEvent = eventQueue.pop
      // 执行争夺锁事件
      执行 fightEvent
    3. 争夺锁事件

      // 争夺锁事件
      执行 etcd争夺锁方法
      if (抢到锁了) {// 清空所有事件执行 clearAll// 设置持有锁超时事件设置 holdEvent
      } else {// 争夺锁事件如果是二次入队列,建议到队列头,而不是到队列尾eventQueue.push(fightEvent)
      }
    4. 等待锁超时事件(用时间轮延时执行)

      // 清空所有事件
      执行 clearAll
      // 抛出异常
      throw new Exception
    5. 持有锁超时事件(用时间轮延时执行)

      // 执行释放锁事件
      执行 unLockEvent
    6. 释放锁事件

      // 释放锁事件
      执行 etcd释放锁方法
      // 清空所有事件
      执行 clearAll
  • 备注

    以上代码可以用有限状态机设计模式来设计业务
  • 图解分布式服务器与etcd集群交互

    1. 项目启动时初始化,服务器A、B、C是一个分布式系统(不考虑哪台为master)
    2. 同时发来10个请求,此时经过算法分配假设变成了这样
    3. 开始争夺锁时,10个线程同时向etcd争夺锁
    4. 假设请求2争夺成功,那么第一次竞争完毕后除了请求2,其他请求都进入了各自的事件队列等待etcd释放锁的通知
    5. 当请求2执行完代码块后,向etcd发送释放锁请求
    6. etcd收到释放锁请求,将节点删除,触发compareAndDelete事件(释放锁事件)
    7. 三台服务器接收到释放锁的信息,各自让事件队列头的请求向etcd发送争夺锁请求
    8. 锁抢完后,重复4->6的行为
  • 补充说明

    1. etcd还有一个功能是控制时序,这样的话就可以将每个请求抢锁的行为控制到只剩一次,业务执行的顺序由etcd控制,不过我没有试过,有兴趣的同学可以试一试。
    2. 之前基于分布式锁的原理还写了一个分布式缓存锁,是通过锁缓存来防止缓存击穿的,有空的时候补上。感谢各位同学看我的文章看到此处。

分布式锁的原理和实现详解相关推荐

  1. java的markword_【转帖】Java工具结构与锁实现原理及MarkWord详解

    Java工具结构与锁实现原理及MarkWord详解 https://www.pianshen.com/article/2382167638/ 我们都知道,Java工具存储在堆(Heap)内存.那么一个 ...

  2. Java对象结构与锁实现原理及MarkWord详解

    阅读本博客前,需要了解基本的同步概念,传送门:http://note.youdao.com/noteshare?id=7f10475c6bb01658b955eaca531c0be6&sub= ...

  3. Spark SQL原理及常用方法详解(二)

    Spark SQL 一.Spark SQL基础知识 1.Spark SQL简介 (1)简单介绍 (2)Datasets & DataFrames (3)Spark SQL架构 (4)Spark ...

  4. SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解

    目录 前言 SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解 一.关于ShedLock 二.ShedLock的三个核心组件 三.ShedLock使用三步走 四.Spr ...

  5. 技术分享| 基于 Etcd 的分布式锁实现原理及方案

    1. 为什么选择 Etcd 据官网介绍,Etcd 是一个分布式,可靠的 Key-Value 存储系统,主要用于存储分布式系统中的关键数据.初见之下,Etcd 与 NoSQL 数据库系统有几分相似,但作 ...

  6. redis队列优先级java实现_Redis 实现队列原理的实例详解

    Redis 实现队列原理的实例详解 场景说明: ·用于处理比较耗时的请求,例如批量发送邮件,如果直接在网页触发执行发送,程序会出现超时 ·高并发场景,当某个时刻请求瞬间增加时,可以把请求写入到队列,后 ...

  7. hbase 二进制数据写入_分布式数据库HBase的架构设计详解(有彩蛋)

    原标题:分布式数据库HBase的架构设计详解(有彩蛋) 本文根据DBAplus社群第99期线上分享整理而成,文末还有好书送哦~ 讲师介绍 陈鸿威 云财经大数据CTO 曾任百度高级工程师,现主持设计开发 ...

  8. python使用kafka原理详解_Python操作Kafka原理及使用详解

    Python操作Kafka原理及使用详解 一.什么是Kafka Kafka是一个分布式流处理系统,流处理系统使它可以像消息队列一样publish或者subscribe消息,分布式提供了容错性,并发处理 ...

  9. python的编程模式-Python设计模式之状态模式原理与用法详解

    本文实例讲述了Python设计模式之状态模式原理与用法.分享给大家供大家参考,具体如下: 状态模式(State Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类 ...

  10. DeepLearning tutorial(1)Softmax回归原理简介+代码详解

    FROM: http://blog.csdn.net/u012162613/article/details/43157801 DeepLearning tutorial(1)Softmax回归原理简介 ...

最新文章

  1. 怎么帮java转换成类图_有把java代码直接转成uml类图的工具吗 – 手机爱问
  2. python怎么查看代码错误_python中的错误如何查看
  3. 香港中文大学Center for Gut Microbiota Research招聘启事
  4. 大数据Scala编程.问题集(02)
  5. 13.Django之url路由系统初探(一)
  6. 查看mysql.sock_如何查找 mysql 的mysql.sock文件?
  7. 如何高效的学习掌握新技术
  8. EF中加载实体的方式
  9. vue-router 在项目中的使用
  10. 【ASP.NET开发】.NET三层架构简单解析
  11. 用Mockito回答
  12. 微信小程序隐藏菜单栏目下转发按钮的几个方法
  13. Django:ORM基本操作-CRUD,管理器对象objects,----->新增
  14. IDEA+SpringBoot+Dubbo在webapp下创建前端页面
  15. 如何下载旧版本android NDK
  16. 常用运算放大器 - 选型列表(比较全,参数详细)
  17. c# excel插入图表
  18. 小程序UI框架minui
  19. kibana 写两个查询条件_Kibana使用之Lucene的语法查询
  20. both and和both of 得用法 和区别

热门文章

  1. aws搭建深度学习gpu_选择合适的GPU进行AWS深度学习
  2. 南昌计算机学校哪家最可靠,南昌问题孩子管教学校哪家靠谱
  3. 中缀表达式转后缀表达式规则
  4. Django media 配置
  5. 杨晓峰-Java核心技术-9 HashMap Hashtable TreeMap MD
  6. CTF---Web入门第二题 上传绕过
  7. tomcat、redis session共存配置
  8. 【PHP设计模式 02_JieKou.php】面向接口开发
  9. ASP.NET OAuth:解决refresh token无法刷新access token的问题
  10. postfix发送邮件报错:mail for xxxxx.com loops back to myself