ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

持续输出面试题之分布式锁

2020-09-22 09:02:25  阅读:160  来源: 互联网

标签:输出 面试题 加锁 lock zookeeper Redis 客户端 节点 分布式


分布式锁

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();

标签:输出,面试题,加锁,lock,zookeeper,Redis,客户端,节点,分布式
来源: https://www.cnblogs.com/hongcaixia/p/13710090.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有