zoukankan      html  css  js  c++  java
  • 分布式锁

    分布式锁

    • 借助数据库、Redis集群、Zookeeper集群作为辅助系统。

    • 面临的问题:

      1. 锁的一致性问题:在集群式辅助系统中,必然会存在锁的并发读,由于集群内部的数据同步存在延迟,不同客户端进程读到的锁可能不一致。

        • Zookeeper天生支持最终一致性,能在一定程度上满足。
        • Redison借助Redis集群借助redlock机制,也能保证最终一致性。
      2. 锁得不到释放:持有锁的进程崩溃,导致锁得不到释放,进一步导致其他进程被永久等待,称之为锁得不到释放。

        • 解决思路:给锁预设过期时间,一旦超超时锁会被强制释放,解决了永久等待问题。
      3. 锁的过早释放:新问题又产生了,预设的过期时间往往是一个经验值,可能出现持有锁的进程的正常逻辑还没执行完毕,锁就被错误的强制过期了,这时其他进程将会错误的执行,称之为锁的过早释放。

        • 简单粗暴,将超时时间设长一点,比如一分钟,这样能避免大部分的错误强制释放,但如果频繁发生进程故障,将导致大量的无效等待,优点是实现简单,不需要做额外开发,利用Redis的setIfAbsent+expire机制就可以实现。Redison就是基于此,同时在应用中开启后台线程定期给锁续约,避免锁的过早释放。
        • 给锁增加监听机制,一旦持有者崩溃就自动释放锁,将锁的释放权完全交给持有进程,这种方式合理高效,但实现复杂。

    1、数据库实现

    进程a先查询表,如果没有记录就向表中插入锁,拿到了锁,继续处理自己的逻辑;

    进程b也做同样的操作,查询发现表中已存在记录,表示锁被他人持有,进程b自旋查询等待;

    进程a处理完自己的逻辑后删除表中的记录。

    进程b查询表发现没有记录,将锁插入表,拿到了锁,继续处理自己的逻辑。

    2、Zookeeper实现

    每一个进程都到某个znode下创建一个临时有序子节点,同时每个进程都监听这个父znode。
    父znode下的每个子节点的变动都会触发进程重新拉取子节点列表,每个进程得到列表后比较自己的节点是否是列表中最小的那一个,如果是则表示得到了锁。执行完毕后断开连接,session失效对应的节点被删除,完成锁的释放。

    3、Redison实现

    借助setIfAbsent + expire + redlock + 后台续约线程。

  • 相关阅读:
    内存映射和独立存贮器
    Elastic Stack简介和Elasticsearch--先搞清楚概念第二篇
    终于有人把Elasticsearch原理讲透了!学习的第一篇总览全局
    Java对象的序列化和反序列化
    java类里的成员变量是自身的对象问题
    Maven多模块的2种依赖管理策略
    双重检查锁单例模式为什么要用volatile关键字?
    Maven pom中的 scope 详解
    IntelliJ IDEA 内置数据库管理工具实战
    docker安装mysql5.7
  • 原文地址:https://www.cnblogs.com/JaxYoun/p/12335222.html
Copyright © 2011-2022 走看看