zoukankan      html  css  js  c++  java
  • 持续输出面试题之分布式锁

    分布式锁

    1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
    2、高可用的获取锁与释放锁
    3、高性能的获取锁与释放锁
    4、具备可重入特性(可理解为重新进入,由多于一个任务并发使用,而不必担心数据错误)
    5、具备锁失效机制,防止死锁
    6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败

    基于zookeeper的分布式锁

    1.zookeeper的一些特性

    • 有序节点:假如当前有一个父节点为/lock,我们可以在这个父节点下面创建子节点;zookeeper提供了一个可选的有序特性,例如我们可以创建子节点“/lock/node-”并且指明有序,那么zookeeper在生成子节点时会根据当前的子节点数量自动添加整数序号,也就是说如果是第一个创建的子节点,那么生成的子节点为/lock/node-0000000000,下一个节点则为/lock/node-0000000001,依次类推。

    • 临时节点:客户端可以建立一个临时节点,在会话结束或者会话超时后,zookeeper会自动删除该节点。

    • 事件监听:在读取数据时,我们可以同时对节点设置事件监听,当节点数据或结构变化时,zookeeper会通知客户端。当前zookeeper有如下四种事件:
      1.节点创建;
      2.节点删除;
      3.节点数据修改;
      4.子节点变更。

    2.实现
    ①客户端连接zookeeper,并在/lock下创建临时的且有序的子节点,第一个客户端对应的子节点为/lock/lock-1,第二个为/lock/lock-2,以此类推。
    ②客户端获取/lock下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听/lock的子节点变更消息,获得子节点变更通知后重复此步骤直至获得锁;
    ③执行业务代码;
    ④完成业务流程后,删除对应的子节点释放锁。

    基于curator的zookeeper分布式锁实现

        public static void main(String[] args) throws Exception {
            //创建zookeeper的客户端
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
    
            CuratorFramework client = CuratorFrameworkFactory.newClient("10.21.41.181:2181,10.21.42.47:2181,10.21.49.252:2181", retryPolicy);
    
            client.start();
    
            //创建分布式锁, 锁空间的根节点路径为/curator/lock
            InterProcessMutex mutex = new InterProcessMutex(client, "/curator/lock");
    
            mutex.acquire();
    
            //获得了锁, 进行业务流程
            System.out.println("Enter mutex");
    
            //完成业务流程, 释放锁
            mutex.release();
    
            //关闭客户端
            client.close();
    
        }
    

    基于redis的分布式锁

    1.流程
    1、服务A为了获得锁,向Redis发起如下命令: SET productId:lock 0xx9p03001 NX PX 30000 其中,"productId"由自己定义,可以是与本次业务有关的id,"0xx9p03001"是一串随机值,必须保证全局唯一(原因在后文中会提到),“NX"指的是当且仅当key(也就是案例中的"productId:lock”)在Redis中不存在时,返回执行成功,否则执行失败。"PX 30000"指的是在30秒后,key将被自动删除。执行命令后返回成功,表明服务成功的获得了锁。
    2、服务B为了获得锁,向Redis发起同样的命令: SET productId:lock 0000111 NX PX 30000 由于Redis内已经存在同名key,且并未过期,因此命令执行失败,服务B未能获得锁。服务B进入循环请求状态,比如每隔1秒钟(自行设置)向Redis发送请求,直到执行成功并获得锁。
    3、服务A的业务代码执行时长超过了30秒,导致key超时,因此Redis自动删除了key。此时服务B再次发送命令执行成功,假设本次请求中设置的value值为0000222。
    4、服务A执行完毕,为了释放锁,服务A会主动向Redis发起删除key的请求。

    2.实现
    加锁
    客户端集成Redisson,在加锁之前,首先需要通过hash算法选定集群内某一个Redis Master,后续加锁、解锁等各种过程都是在这个Redis Master和与之绑定的slave节点之间。
    执行lua脚本实现加锁
    watch dog自动延期
    watch dog是一个后台线程,它会每隔10秒观察当前客户端是否仍然持有锁,如果持有,说明客户端可能仍然在使用锁,因此延长锁的剩余生存时间。
    释放锁机制 如果执行lock.unlock(),Redis会找到上方test数据结构,将加锁次数减一。如果减完后发现加锁次数为0,则说明当前客户端不再持有锁,因此执行: del test命令, 从Redis中删除这条key。

    // 准备为名为"test"的key加锁
    RLock lock = redisson.getLock("test");
    // 加锁
    lock.lock();
    // 解锁
    lock.unlock();
    
  • 相关阅读:
    重新想象 Windows 8 Store Apps (15) 控件 UI: 字体继承, Style, ControlTemplate, SystemResource, VisualState, VisualStateManager
    重新想象 Windows 8 Store Apps (12) 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示
    返璞归真 asp.net mvc (10) asp.net mvc 4.0 新特性之 Web API
    与众不同 windows phone (29) Communication(通信)之与 OData 服务通信
    与众不同 windows phone (33) Communication(通信)之源特定组播 SSM(Source Specific Multicast)
    与众不同 windows phone (27) Feature(特性)之搜索的可扩展性, 程序的生命周期和页面的生命周期, 页面导航, 系统状态栏
    与众不同 windows phone (30) Communication(通信)之基于 Socket TCP 开发一个多人聊天室
    返璞归真 asp.net mvc (12) asp.net mvc 4.0 新特性之移动特性
    重新想象 Windows 8 Store Apps (2) 控件之按钮控件: Button, HyperlinkButton, RepeatButton, ToggleButton, RadioButton, CheckBox, ToggleSwitch
    重新想象 Windows 8 Store Apps (10) 控件之 ScrollViewer 特性: Chaining, Rail, Inertia, Snap, Zoom
  • 原文地址:https://www.cnblogs.com/hongcaixia/p/13710090.html
Copyright © 2011-2022 走看看