美文网首页
分布式锁简析

分布式锁简析

作者: 造一个大大的轮子 | 来源:发表于2019-07-12 16:09 被阅读0次

    1. 为什么要使用分布式锁?

    场景
    1. 变量A存在JVM1、JVM2、JVM3三个JVM(进程)内存中
    2. 变量A同时都会在JVM分配一块内存,三个请求发过来同时对这个变量进行操作(例如3个人买书,书的库存只有2本),显然结果是不对的
    3. 不是同时发过来,三个请求分别操作三个不同JVM内存区域的数据,变量A之间不存在共享,也不具有可见性,处理的结果也是不对的
      注:这个变量主要体现在一个类中有一个成员变量,它是一个有状态的对象

    2. 分布式锁应该具备哪些条件?

    1. 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
    2. 高可用的获取与释放锁(zookeeper一直都能提供锁,并且释放锁)
    3. 高性能的获取锁与释放锁(快)
    4. 具备可重入性特性(可理解为重新进入,由多于一个任务并发使用,而不必担心数据错误)

    可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反,不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。
    可重入函数:
    1.不为连续的调用持有静态数据。
    2.不返回指向静态数据的指针;所有数据都由函数的调用者提供。
    3.使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
    4.如果必须访问全局变量,记住利用互斥信号量来保护全局变量。
    5.绝不调用任何不可重入函数。

    1. 具备锁失效机制,防止死锁

    回顾:多线程是如何避免死锁的?
    我们只要破坏产生死锁的四个条件中的其中一个就可以了。
    1.破坏互斥条件
    这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥的(临界资源需要互斥访问)。
    2.破坏请求与保持条件
    一次性申请所有的资源。
    3.破坏不剥夺条件
    占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
    4.破坏循环等待条件
    靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。
    我们对线程 2 的代码修改成下面这样就不会产生死锁了

    1. 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败
      说明:类似于熔断机制,避免大量申请锁等待而导致的阻塞.

    什么是Zookeeper

    Zookeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一的文件名,即同一目录下文件名不能重复

    Zookeeper实现分布式锁的步骤

    1. 创建一个目录MyZookeeper
    2. 线程A想要获取锁就在MyZookeeper目录下创建一个临时顺序节点
    3. 线程A获取MyZookeeper目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁
    4. 此时线程B也获取锁,它会先获取所有的MyZookeeper节点下的子节点,如果判断自己不是最小的节点,就设置监听比自己次小的节点
    5. 线程A处理完毕,删除自己的节点,线程B监听到变更事件(加入线程B次小的节点是A),还是判断下自己是不是最小的节点,如果是就获得锁

    参考:单点故障与分布式锁

    相关文章

      网友评论

          本文标题:分布式锁简析

          本文链接:https://www.haomeiwen.com/subject/phmekctx.html