Zookeeper实现分布式锁(Zk分布式锁)

文章目录

    • 概述
    • 如何用Zookeeper实现分布式锁
    • Zk分布式锁原理和实现
    • Zookeeper实现分布式锁Java代码

概述

基于zookeeper临时有序节点可以实现的分布式锁。
1、zookeeper天生设计定位就是分布式协调,强一致性。锁的模型健壮、简单易用、适合做分布式锁。
2、如果获取不到锁,只需要添加一个监听器就可以了,不用一直轮询,性能消耗较小。
3、如果有较多的客户端频繁的申请加锁、释放锁,对于zk集群的压力会比较大。

如何用Zookeeper实现分布式锁

使用 ZooKeeper 实现分布式锁是一种常见的方法,它可以确保在分布式系统中的多个节点上对共享资源进行互斥访问。下面是一种基本的方法来实现分布式锁:

  1. 创建一个持久性的父节点:
    在 ZooKeeper 中创建一个持久性的父节点,用于存储所有的锁。
  2. 每个请求尝试创建一个临时顺序节点:
    当一个节点需要获取锁时,它在上述创建的父节点下创建一个临时顺序节点。
  3. 获取节点列表:
    节点获取父节点下的所有子节点,并对它们进行排序。
  4. 判断是否是最小的节点:
    节点检查它是否是所有子节点中最小的节点。如果是,表示该节点获取了锁;否则,它监听比它小的前一个节点的删除事件。
  5. 如果不是最小的节点,则等待:
    如果节点不是最小的节点,它会监听比它小的前一个节点的删除事件,一旦前一个节点被删除,它再次尝试获取锁,重复步骤 3 和步骤 4。
  6. 释放锁:
    当节点使用完共享资源后,它删除自己创建的临时顺序节点,从而释放锁。
    这种方法利用了 ZooKeeper 的节点顺序性质和临时节点的特性来实现分布式锁。由于节点是按顺序创建的,所以可以通过比较节点的序号来确定锁的持有者。而且,使用临时节点可以确保如果锁的持有者发生故障或失去连接,则锁会被自动释放。
    这只是一个基本的实现方法,实际应用中可能还需要考虑超时处理、重试机制、错误处理等情况,以确保分布式锁的可靠性和健壮性。

Zk分布式锁原理和实现

Zookeeper 是基于临时顺序节点以及 Watcher 监听器机制实现分布式锁的。
1.ZooKeeper 的每一个节点都是一个天然的顺序发号器。
2.ZooKeeper 节点的递增有序性可以确保锁的公平。
3.ZooKeeper 的节点监听机制,可以保障占有锁的传递有序而且高效
Zookeeper实现分布式锁原理:
Zookeeper节点路径不能重复 保证唯一性。 临时节点+事件通知
1.获取锁方法:
多个jvm同时在zk上创建一个临时节点/lockPath,
最终只能够有一个jvm创建临时节点成功,如果能够创建
临时节点成功jvm 表示获取锁成功能够正常执行业务逻辑,
如果没有创建临时节点成功的jvm,则表示获取锁失败。
获取锁失败之后,可以采用不断重试策略,重试多次
获取锁失败之后,当前的jvm就进入到阻塞状态。
2.释放锁方法:
直接调用.close();释放锁
因为采用临时节点,当我们调用close()方法的时候
该临时节点会自动被删除。
其他没有获取到锁的jvm,就会从新进入到获取锁的状态。
3.被唤醒的方法:
被阻塞的jvm(没有获取锁成功的jvm),采用事件监听的方式
监听到节点已经被删除的情况下,则开始从新进入到获取锁的状态。
Zookeeper 实现分布式锁的方法比较多,我们可以使用有序节点来实现,
1、来看这个图,每个线程或进程在 Zookeeper 上的/lock 目录下创建一个临时有序的节点表示去抢占锁,所有创建的节点会按照先后顺序生成一个带有序编号的节点。
2、线程创建节点后,获取/lock 节点下的所有子节点,判断当前线程创建的节点是否是所有的节点的序号最小的。
3、如果当前线程创建的节点是所有节点序号最小的节点,则认为获取锁成功。
4、如果当前线程创建的节点不是所有节点序号最小的节点,则对节点序号的前个节点添加一个事件监听,当前一个被监听的节点释放锁之后,触发回调通知,从而再次去尝试抢占锁。
ZooKeeper 是一种分布式协调服务,它可以帮助分布式系统中的各个节点进行协调和通信。ZooKeeper 的协调机制是通过一种称为 “ZNode” 的数据结构来实现的。
在 ZooKeeper 中,每个节点都被称为一个 ZNode,它可以有子节点和关联的数据。ZNode 可以被视为一种目录结构,其中每个节点都有一个路径。通过这个路径,可以找到节点的数据。
当使用 ZooKeeper 实现分布式锁时,可以使用一种称为 “顺序节点” 的机制。顺序节点是一种特殊的 ZNode,它会在创建时自动分配一个唯一的顺序编号。这个编号可以用来解决分布式锁的问题。
假设我们有一个需要被协调的任务,可以让多个进程都去创建 ZooKeeper 中的同一家目录下的一个子节点。由于是顺序节点,每个进程创建的子节点都会被分配一个唯一的编号。当一个进程创建了编号最小的子节点时,就认为它获得了锁,可以执行任务。其他进程在创建子节点时会被阻塞,等待前一个进程释放锁。
这个过程中,只要有一台机器能够成功创建子节点并获得锁,就可以完成任务。其他机器会继续等待,直到锁被释放。这样可以保证只有一个进程能够执行任务,实现分布式锁的效果。
总之,ZooKeeper 提供了分布式协调的机制,可以通过顺序节点实现分布式锁的功能,使得分布式系统中的任务可以被协调执行。

Zookeeper实现分布式锁Java代码

基于 ZooKeeper 实现分布式锁的一般步骤如下:

  1. 创建一个持久性节点:
    在 ZooKeeper 中创建一个持久性节点,作为锁的父节点,所有的锁都将作为其子节点。
  2. 获取锁:
    当一个客户端需要获取锁时,它在锁的父节点下创建一个临时顺序节点。
  3. 获取所有子节点列表:
    客户端获取锁父节点下的所有子节点,并对它们进行排序。
  4. 判断是否获取锁:
    客户端检查是否自己创建的节点是所有子节点中序号最小的节点,如果是,则表示客户端成功获取到了锁。
  5. 如果未获取锁,则监听前一个节点:
    如果客户端创建的节点不是序号最小的节点,则客户端需要监听前一个节点的变化事件。
  6. 处理监听事件:
    如果前一个节点被删除(表示前一个客户端释放了锁),则客户端重复步骤 3 和步骤 4。
  7. 使用锁:
    客户端成功获取到锁后,可以执行需要互斥访问的代码。
  8. 释放锁:
    当客户端完成了对共享资源的访问后,需要删除自己创建的临时顺序节点,以释放锁。
    下面是一个简单的 Java 代码示例,演示了如何使用 ZooKeeper 实现分布式锁:
import org.apache.zookeeper.*;public class DistributedLock implements Watcher {private ZooKeeper zooKeeper;private String lockPath;private String currentLockPath;public DistributedLock(String host, String lockPath) {try {this.zooKeeper = new ZooKeeper(host, 3000, this);this.lockPath = lockPath;} catch (Exception e) {e.printStackTrace();}}public void lock() {try {currentLockPath = zooKeeper.create(lockPath + "/lock", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);while (true) {String minNode = getMinNode();if (currentLockPath.equals(minNode)) {return;} else {synchronized (this) {wait();}}}} catch (Exception e) {e.printStackTrace();}}private String getMinNode() throws KeeperException, InterruptedException {String minNode = null;for (String node : zooKeeper.getChildren(lockPath, false)) {if (minNode == null || node.compareTo(minNode) < 0) {minNode = node;}}return minNode;}public void unlock() {try {zooKeeper.delete(currentLockPath, -1);} catch (Exception e) {e.printStackTrace();}}@Overridepublic void process(WatchedEvent event) {synchronized (this) {notifyAll();}}public static void main(String[] args) {String host = "localhost:2181";String lockPath = "/locks";DistributedLock lock = new DistributedLock(host, lockPath);lock.lock();System.out.println("获取到锁,执行任务...");// 在这里执行需要互斥访问的代码lock.unlock();System.out.println("释放锁,任务完成。");}
}

这段代码实现了一个简单的分布式锁,使用 ZooKeeper 实现了锁的获取和释放,确保了对共享资源的互斥访问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/767133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

01.重新认识文件(Linux基本概念)

知识引入&#xff1a; 我们经常使用word或者wps写的论文、作业等都是文件&#xff0c;而我们这样对文件的认识也比较片面。我们是否思考过&#xff0c;如果文件里面没有写东西&#xff0c;那么计算机会不会保存呢&#xff1f;答案是&#xff0c;肯定会的。因为我们每次建的空文…

Linux下对线程的认识+生产消费者模型+信号量

线程的概念 线程是进程内部中更加轻量化的一种执行流。线程是CPU调度的基本单位&#xff0c;而进程是承担系统资源的实体。就是说一个进程中可能会有多个线程&#xff0c;而在Linux内核中并没有真正重新的创建线程并重新进行资源分配&#xff0c;因为我们每个线程指向的资源都是…

力扣---最长回文子串---二维动态规划

二维动态规划思路&#xff1a; 首先&#xff0c;刚做完这道题&#xff1a;力扣---最长有效括号---动态规划&#xff0c;栈-CSDN博客&#xff0c;所以会有一种冲动&#xff0c;设立g[i]&#xff0c;表示以第i位为结尾的最长回文子串长度&#xff0c;然后再遍历一遍取最大长度即可…

【图解物联网】第8章 物联网与机器人

8.1 由设备到机器人 把我们身边形形色色的“物”都连接到互联网&#xff0c;这就是物联网。物联网中使用的设备随着时间的推移在不断进化&#xff0c;这条进化之路的前方到底有什么呢&#xff1f;这里我们就围绕其中一种形式&#xff0c;即机器人来对讨论一下这个问题。 8.1…

(Node+Express+vue)常量抽取

好久没来更新了&#xff0c;最近在用node整项目。。。 定义一个名为constant.js文件&#xff0c;用来存放项目的常量信息。 // 定义一个常量对象 const obj {// 默认请求成功DEFAULT_SUCCESS: {code: 1001,msg: },// 默认请求失败DEFAULT_ERROR: {code: 1002,msg: 系统错误},…

lin_20240321_calculating_rG4score.R

1.使用上一步的结果来计算RG4 用法和脚本如下&#xff1a; ################################################################################ ################# Function used for the G4Hunter paper ######################### ######################################…

【C语言】指针基础

指针是C语言中的一个重要概念&#xff0c;也是其强大功能的核心之一。理解指针的基础知识对于编写高效、灵活的C语言程序至关重要。本文将介绍指针的基本概念、用法以及一些常见的技巧和注意事项&#xff0c;旨在帮助读者建立起对C语言指针的全面理解&#xff0c;并能够熟练地运…

Python程序设计 类与继承

一. 继承的概念 生活中的继承&#xff0c;一般指的是子女继承父辈的财产。 拓展1&#xff1a;经典类或旧式类 不由任意内置类型派生出的类&#xff0c;称之为经典类。 class 类名:代码...... 拓展2&#xff1a;新式类 # 父类A class A(object):def __init__(self):self.n…

error: ‘mutex’ in namespace ‘boost’ does not name a type 解决办法

在ubuntu下使用make编译的时候出现错误&#xff1a; error: ‘boost::mutex’ has not been declared 以及&#xff1a; error: ‘mutex’ in namespace ‘boost’ does not name a type 等错误&#xff0c;原因是有可能是没有安装boost或者是没有添加boost头文件&#xff…

使用Python的scipy.integrate计算微积分

先上一个二重积分计算&#xff0c;来自2022年考研数学第二题 进行计算前先在终端下载 scipy包 pip install scipy 在脚本中先导入所需要的模块 import scipy.integrate as spi 定义函数f(x, y) &#xff0c;所得值返回 def f(x, y): return y / (1 x**3)**0.5 定义…

基于springboot+vue的影院订票系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

LeetCode Python - 71. 简化路径

目录 题目描述解法运行结果 题目描述 给你一个字符串 path &#xff0c;表示指向某一文件或目录的 Unix 风格 绝对路径 &#xff08;以 ‘/’ 开头&#xff09;&#xff0c;请你将其转化为更加简洁的规范路径。 在 Unix 风格的文件系统中&#xff0c;一个点&#xff08;.&…

一图理解递归-算法通关村

一图理解递归-算法通关村 递归是我们算法进阶的基础&#xff0c;是必须要掌握的内容&#xff0c;只有掌握了递归才算真的会算法。与递归有关的问题有&#xff1a; 与树和二叉树相关的大部问题二分查找相关的问题快速排序、归并排序相关的问题所有回溯的问题所有动态规划的问题 …

大数据分析-基于Python的网络爬虫及数据处理---智联招聘人才招聘特征分析与挖掘的算法实现

概要 随着科学技术的发展&#xff0c;人类进入了互联网时代&#xff0c;不仅数据量庞大&#xff0c;而且数据种类繁多&#xff0c;Python简单易学, 语法清晰&#xff0c;在数据操作方面有着一定优势&#xff0c;成为了数据采集和可视化领域的热门语言。本论文主要是使用Python来…

golang 使用AES加密

在使用AES加密数据后&#xff0c;将加密结果使用base64.StdEncoding.EncodeToString处理的原因是多方面的&#xff1a; 可读性&#xff1a;AES加密后的数据通常是二进制格式&#xff0c;直接查看或处理这些二进制数据不方便也不直观。Base64编码将这些二进制数据转换为ASCII字符…

Kruskal最小生成树【详细解释+动图图解】【sort中的cmp函数】 【例题:洛谷P3366 【模板】最小生成树】

文章目录 Kruskal算法简介Kruskal算法前置知识sort 中的cmp函数 算法思考样例详细示范与解释kruskal模版code↓ 例题&#xff1a;洛谷P3366 【模板】最小生成树code↓完结撒花QWQ Kruskal算法简介 K r u s k a l Kruskal Kruskal 是基于贪心算法的 M S T MST MST 算法&#xff…

导师坚鹏:厦门火炬高新区数字化转型战略蓝图从规划到落地培训

厦门火炬高新区战略制胜&#xff1a;数字化转型战略蓝图从规划到落地培训 厦门国家火炬高技术产业开发区&#xff08;简称“厦门国家火炬高新区”&#xff09;1991年被国务院批准为全国首批国家级高新区&#xff0c;是全国三个以“火炬”冠名的国家高新区之一。目前&#xff0c…

CPU密集的高效访问和数据安全

import asyncio import concurrent.futures import random # 全局变量&#xff0c;用于存储计算结果的列表 list1 [] list2 [] lock asyncio.Lock() # 异步锁 # CPU计算密集型任务 async def cpu_intensive_task(): global list1, list2 # 获取异步锁 async with…

Excel通过下拉菜单,显示不同图片

背景&#xff1a;有的时候需要通过更改下拉菜单来改变对应的 值/ 图片。 如果是数值的话就是我们常常用的Vlookup&#xff0c;这个可以很简单的实现这个功能。&#xff08;这个如果不知道请自行百度&#xff09; 但是如果是图片呢&#xff1f;这个就不常见了&#xff0c;那么…

Unity中关于SendMessage方法

在Unity中&#xff0c;SendMessage 方法用于在游戏对象及其所有子对象上调用指定名称的方法。这种方法可以用于在不需要知道接收方的确切类型的情况下&#xff0c;向游戏对象发送消息。 基本语法如下&#xff1a; void SendMessage(string methodName, object value null, S…