ZooKeeper的应用场景(命名服务、分布式协调通知)

3 命名服务

命名服务(NameService)也是分布式系统中比较常见的一类场景,在《Java网络高级编程》一书中提到,命名服务是分布式系统最基本的公共服务之一。在分布式系统中,被命名的实体通常可以是集群中的机器、提供的服务地址或远程对象等一这些我们都可以统称它们为名字(Name),其中较为常见的就是一些分布式服务框架(如RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据指定名字来获取资源的实体、服务地址和提供者的信息等。

Java语言中的JNDI便是一种典型的命名服务。JNDI是Java命名与目录接口(Java Naming and Directory Interface)的缩写,是J2EE体系中重要的规范之一,标准的J2EE容器都提供了对JNDI规范的实现。因此,在实际开发中,开发人员常常使用应用服务器自带的JNDI实现来完成数据源的配置与管理一使用JNDI方式后,开发人员可以完全不需要关心与数据库相关的任何信息,包括数据库类型、JDBC驱动类型以及数据库账户等。

ZooKeeper提供的命名服务功能与JNDI技术有相似的地方,都能够帮助应用系统通过一个资源引用的方式来实现对资源的定位与使用。另外,广义上命名服务的资源定位都不是真正意义的实体资源一在分布式环境中,上层应用仅仅需要一个全局唯一的名字,类似于数据库中的唯一主键。 下面我们来看看如何使用ZooKeeper来实现一套分布式全局唯一ID的分配机制。

所谓ID,就是一个能够唯一标识某个对象的标识符。在我们熟悉的关系型数据库中,各个表都需要一个主键来唯一标识每条数据库记录,这个主键就是这样的唯一ID。在过去的单库单表型系统中,通常可以使用数据库字段自带的auto_increment属性来自动为每条数据库记录生成一个唯一的ID,数据库会保证生成的这个ID在全局唯一。但是随着数据库数据规模的不断增大,分库分表随之出现,而auto_increment 属性仅能针对单一表中的记录自动生成ID,因此在这种情况下,就无法再依靠数据库的auto_increment 属性来唯一标识一条记录了。于是,我们必须寻求一种能够在分布式环境下生成全局唯一ID的方法。

说起全局唯一ID,相信读者都会联想到UUID。没错,UUID是通用唯一识别码(Universally Unique Identifier) 的简称,是一种在分布式系统中广泛使用的用于唯一标识元素的标准,最典型的实现是GUID (Globally Unique ldentifier,全局唯一标识符),主流ORM框架Hibernate有对UUID的直接支持。

确实,UUID是一个非常不错的全局唯一ID生成方式,能够非常简便地保证分布式环境中的唯一性。一个标准的UUID 是一个包含32位字符和4个短线的字符串,例如“e70f1357-f260-46ff-a32d-53a086c57ade”。UUID的优势自然不必多说,我们重点来看看

它的缺陷。

(1)长度过长

UUID最大的问题就在于生成的字符串过长。显然,和数据库中的INT类型相比,存储一个UUID需要花费更多的空间。

(2)含义不明

上面我们已经看到一个典型的UUID是类似于“e70f1357- f260-46fF- a32d-53a086c57ade"的一个字符串。根据这个字符串,开发人员从字面上基本看不出任何其表达的含义,这将会大大影响问题排查和开发调试的效率。

接下来,我们结合一个分布式任务调度系统来看看如何使用ZooKeeper来实现这类全局唯一ID的生成。

通过调用ZooKeeper节点创建的API接口可以创建一个顺序节点,并且在API返回值中会返回这个节点的完整名字。利用这个特性,我们就可以借助ZooKeeper来生成全局唯一的ID了,如下图所示。

结合上图,我们来讲解对于一个任务列表的主键,使用ZooKeeper生成唯一ID 的基本步骤。

(1)所有客户端都会根据自己的任务类型,在指定类型的任务下面通过调用create()接口来创建一个顺序节点,例如创建“job-”节点。

(2)节点创建完毕后,create()接口会返回一个完整的节点名,例如“job-000000003"。

(3)客户端拿到这个返回值后,拼接上type类型,例如“type2-job 000000003”, 这就可以作为一个全局唯一的ID了。

在ZooKeeper中,每一个数据节点都能够维护--份子节点的顺序顺列,当客户端对其创建一个顺序子节点的时候ZooKeeper会自动以后缀的形式在其子节点上添加一个序号,在这个场景中就是利用了ZooKeeper的这个特性。

4 分布式协调/通知

分布式协调/通知服务是分布式系统中不可缺少的一个环节,是将不同的分布式组件有机结合起来的关键所在。对于一个在多台机器上部署运行的应用而言,通常需要一个协调者(Coordinator)来控制整个系统的运行流程,例如分布式事务的处理、机器间的互相协调等。同时,引入这样一个协调者,便于将分布式协调的职责从应用中分离出来,从而可以大大减少系统之间的耦合性,而且能够显著提高系统的可扩展性。

ZooKeeper中特有的Watcher注册与异步通知机制,能够很好地实现分布式环境下不同机器,甚至是不同系统之间的协调与通知,从而实现对数据变更的实时处理。基于ZooKeeper实现分布式协调与通知功能,通常的做法是不同的客户端都对ZooKeeper上同一个数据节点进行Watcher注册,监听数据节点的变化(包括数据节点本身及其子节点),如果数据节点发生变化,那么所有订阅的客户端都能够接收到相应的Watcher通知,并做出相应的处理。

MySQL数据复制总线:Mysql_Replicator

MySQL数据复制总线(以下简称“复制总线”)是一个实时数据复制框架,用于在不同的MySQL数据库实例之间进行异步数据复制和数据变化通知。整个系统是一个由MySQL数据库集群、消息队列系统、任务管理监控平台以及ZooKeeper 集群等组件共同构成的一个包含数据生产者、复制管道和数据消费者等部分的数据总线系统,下图所示是该系统的整体结构图。

 

在该系统中,ZooKeeper主要负责进行一系列的分布式协调工作,在具体的实现上,根据功能将数据复制组件划分为三个核心子模块:Core、 Server 和Monitor,每个模块分别为一个单独的进程,通过ZooKeeper进行数据交换。

Core实现了数据复制的核心逻辑,其将数据复制封装成管道,并抽象出生产者和消费者两个概念,其中生产者通常是MySQL数据库的Binlog日志。

Server负责启动和停止复制任务。

Monitor负责监控任务的运行状态,如果在数据复制期间发生异常或出现故障会进行告警。

三个子模块之间的关系如下图所示。

每个模块作为独立的进程运行在服务端,运行时的数据和配置信息均保存在ZooKeeper上,Web控制台通过ZooKeeper上的数据获取到后台进程的数据,同时发布控制信息。

任务注册

Core进程在启动的时候,首先会向/mysql_replicator/tasks节点(以下简称“任务列表节点”)注册任务。例如,对于一个“复制热门商品”的任务,Task 所在机器在启动的时候,会首先在任务列表节点上创建一个子节点,例如/mysql_replicator/tasks/copy_hot_item(以下简称“任务节点")。如果在注册过程中发现该子节点已经存在,说明已经有其他Task机器注册了该任务,因此自己不需要再创建该节点了。

任务热备份

为了应对复制任务故障或者复制任务所在主机故障,复制组件采用“热备份”的容灾方式,即将同一个复制任务部署在不同的主机上,我们称这样的机器为“任务机器”,主、备任务机器通过ZooKeeper互相检测运行健康状况。

为了实现上述热备方案,无论在第一步中是否创建了任务节点,每台任务机器都需要在/mysql_replicator/tasks/copy_hot_item/instances节点上将自己的主机名注册上去。注意,这里注册的节点类型很特殊,是一个临时的顺序节点。在注册完这个子节点后,通常一个完整的节点名如下: /mysql_replicator/tasks/copy_hot_item/intsances/[Hostname]-I,其中最后的序列号就是临时顺序节点的精华所在。

在完成该子节点的创建后,每台任务机器都可以获取到自己创建的节点的完成节点名以及所有子节点的列表,然后通过对比判断自己是否是所有子节点中序号最小的。如果自己是序号最小的子节点,那么就将自己的运行状态设置为RUNNING,其余的任务机器则将自己设置为STANDBY,我们将这样的热备份策略称为“小序号优先”策略。

热备切换

完成运行状态的标识后,任务的客户端机器就能够正常工作了,其中标记为RUNNING的客户端机器进行正常的数据复制,而标记为STANDBY的客户端机器则进入待命状态。这里所谓待命状态,就是说一旦标记为RUNNING的机器出现故障停止了任务执行,那么就需要在所有标记为STANDBY的客户端机器中再次按照“小序号优先”策略来选出RUNNING机器来执行,具体的做法就是标记为STANDBY的机器都需要在/mysql_replicator/tasks/copy_hot item/instances节点上注册一个“子节点列表变更”的Watcher监听,用来订阅所有任务执行机器的变化情况——一旦RUNNING机器宕机与ZooKeeper断开连接后,对应的节点就会消失,于是其他机器也就接收到了这个变更通知,从而开始新一轮的RUNNING选举。

记录执行状态

既然使用了热备份,那么RUNNING任务机器就需要将运行时的上下文状态保留给STANDBY任务机器。在这个场景中,最主要的上下文状态就是数据复制过程中的一些进度信息,例如Binlog日志的消费位点,因此需要将这些信息保存到ZooKeeper上以便共享。在Mysql_Replicator的设计中,选择了/mysq_replicator/tasks/copy_hot_item/lastCommit作为Binlog日志消费位点的存储节点,RUNNING任务机器会定时向这个节点写人当前的Binlog日志消费位点。

控制台协调

在Mysql_Replicator中,Server主要的工作就是进行任务的控制,通过ZooKeeper来对不同的任务进行控制与协调。Server会将每个复制任务对应生产者的元数据,即库名、表名、用户名与密码等数据库信息以及消费者的相关信息以配置的形式写入任务节点/mysql_replicator/tasks/copy_hot_item中去,以便该任务的所有任务机器都能够共享该复制任务的配置。

冷备切换

到目前为止我们已经基本了解了Mysql_Replicator的工作原理,现在再回过头来看上面提到的热备份。在该热备份方案中,针对一个任务,都会至少分配两台任务机器来进行热备份,但是在一定规模的大型互联网公司中,往往有许多MySQL实例需要进行数据复制,每个数据库实例都会对应一个复制任务,如果每个任务都进行双机热备份的话,那么显然需要消耗太多的机器。

和热备份中比较大的区别在于,Core进程被配置了所属Group(组)。举个例子来说,假如一个Core进程被标记了group1,那么在Core进程启动后,会到对应的ZooKeepergroup1节点下面获取所有的Task列表,假如找到了任务“copy_hot_item”之后,就会遍历这个Task列表的instances 节点,但凡还没有子节点的,则会创建一个临时的顺序节点: /mysql_replicator/task-groups/group1/copy_hot_item/instances/[Hostname]-1——当然,在这个过程中,其他Core进程也会在这个instances节点下创建类似的子节点。和热备份中的“小序号优先”策略一样,顺序小的Core进程将自己标记为RUNNING,不同之处在于,其他Core进程则会自动将自己创建的子节点删除,然后继续遍历下一个Task节点一我们将这样的过程称为“冷备份扫描”。就这样,所有Core进程在一个扫描周期内不断地对相应的Group下面的Task进行冷备份扫描。整个过程可以通过如下图所示的流程图来表示。

冷热备份对比

从上面的讲解中,我们基本对热备份和冷备份两种运行方式都有了一定的了解,现在再来对比下这两种运行方式。在热备份方案中,针对一个任务使用了两台机器进行热备份,借助ZooKeeper的Watcher通知机制和临时顺序节点的特性,能够非常实时地进行互相协调,但缺陷就是机器资源消耗比较大。而在冷备份方案中,采用了扫描机制,虽然降低了任务协调的实时性,但是节省了机器资源。

一种通用的分布式系统机器间通信方式

在绝大部分的分布式系统中,系统机器间的通信无外乎心跳检测、工作进度汇报和系统调度这三种类型。接下来,我们将围绕这三种类型的机器通信来讲解如何基于ZooKeeper去实现一种分布式系统间的通信方式。

心跳检测

机器间的心跳检测机制是指在分布式环境中,不同机器之间需要检测到彼此是否在正常运行,例如A机器需要知道B机器是否正常运行。在传统的开发中,我们通常是通过主机之间是否可以相互PING通来判断,更复杂一点的话,则会通过在机器之间建立长连接,通过TCP连接固有的心跳检测机制来实现上层机器的心跳检测,这些确实都是一些非常常见的心跳检测方法。

下面来看看如何使用ZooKeeper来实现分布式机器间的心跳检测。基于ZooKeeper的临时节点特性,可以让不同的机器都在ZooKeeper的一个指定节点下创建临时子节点,不同的机器之间可以根据这个临时节点来判断对应的客户端机器是否存活。通过这种方式,检测系统和被检测系统之间并不需要直接相关联,而是通过ZooKeeper上的某个节点进行关联,大大减少了系统耦合。

工作进度汇报

在一个常见的任务分发系统中,通常任务被分发到不同的机器上执行后,需要实时地将自己的任务执行进度汇报给分发系统。这个时候就可以通过ZooKeeper来实现。在ZooKeeper上选择一个节点,每个任务客户端都在这个节点下面创建临时子节点,这样便可以实现两个功能:

通过判断临时节点是否存在来确定任务机器是否存活;

各个任务机器会实时地将自己的任务执行进度写到这个临时节点上去,以便中心系

统能够实时地获取到任务的执行进度。

系统调度

使用ZooKeeper,能够实现另--种系统调度模式:一个分布式系统由控制台和一些客户端系统两部分组成,控制台的职责就是需要将--些指令信息发送给所有的客户端,以控制它们进行相应的业务逻辑。后台管理人员在控制台上做的一些操作,实际上就是修改了ZooKeeper上某些节点的数据,而ZooKeeper进一步把这些数据变更以事件通知的形式发送给了对应的订阅客户端。

总之,使用ZooKeeper来实现分布式系统机器间的通信,不仅能省去大量底层网络通信和协议设计上重复的工作,更为重要的一点是大大降低了系统之间的耦合,能够非常方便地实现异构系统之间的灵活通信。

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

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

相关文章

基于LVQ神经网络的人脸朝向识别

1案例背景 1.1人脸识别概述 人脸识别作为一个复杂的模式识别问题,近年来受到了广泛的关注,识别领域的各种方法在这个问题上各显所长,而且发展出了许多新方法,大大丰富和拓宽了模式识别的方向。人脸识别、检测,跟踪、特征定位等技术近年来一直是研究的热点。人脸识别是人脸应用…

W5500-EVB-PICO 做UDP Server进行数据回环测试(七)

前言 前面我们用W5500-EVB-PICO 开发板在TCP Client和TCP Server模式下,分别进行数据回环测试,本章我们将用开发板在UDP Server模式下进行数据回环测试。 UDP是什么?什么是UDP Server?能干什么? UDP (User Dataqram P…

Python 3 使用HBase 总结

HBase 简介和安装 请参考文章:HBase 一文读懂 Python3 HBase API HBase 前期准备 1 安装happybase库操作hbase 安装该库 pip install happybase2 确保 Hadoop 和 Zookeeper 可用并开启 确保Hadoop 正常运行 确保Zookeeper 正常运行3 开启HBase thrift服务 使用命…

ChatGPT爆火,会给教育带来什么样的影响或者冲击?

近来,人工智能聊天机器人ChatGPT连上热搜,火爆全网。ChatGPT拥有强大的信息整合能力、自然语言处理能力,可谓是“上知天文,下知地理”,而且还能根据要求进行聊天、撰写文章等。 ChatGPT一经推出,便迅速在社…

生活随笔,记录我的日常点点滴滴.

前言 😘个人主页:曲终酣兴晚^R的小书屋🥱 😕作者介绍:一个莽莽撞撞的🐻 💖专栏介绍:日常生活&往事回忆 😶‍🌫️每日金句:被人暖一下就高热&…

SpringBoot的配置文件(properties与yml)

文章目录 1. 配置文件的作用2. 配置文件格式3. 配置文件的使用方法3.1. properties配置文件3.1.1. 基本语法和使用3.1.2. properties优缺点分析 3.2. yml配置文件3.2.1. 基本语法与使用3.2.2. yml中单双引号问题3.2.3. yml配置不同类型的数据类型及null3.2.4. 配置对象3.2.5. 配…

CS5263替代停产IT6561连接DP转HDMI音视频转换器ASL 集睿致远CS5263设计电路原理图

ASL集睿致远CS5263是一款DP1.4到HDMI2.0b转换器芯片,设计用于将DP1.4源连接到HDMI2.0b接收器。 CS5263功能特性: DP接口包括4条主通道、辅助通道和HPD信号。接收器支持每通道5.4Gbps(HBR2)数据速率。DP接收机结合了HDCP1.4和HDCP…

接口测试工具——Postman测试工具 Swagger接口测试+SpringBoot整合 JMeter高并发测试工具

目录 Postman测试工具接口测试工具swaggerKnife4j1.引入依赖2.配置3.常用注解4.接口测试 JMeter什么是JMeter?JMeter安装配置1.官网下载2.下载后解压3.汉语设置 JMeter的使用方法1.新建线程组2.设置参数3.添加取样器4.设置参数:协议,ip,端口…

使用Nginx解决跨域问题

前言: 项目是公司的老项目,只有部署在服务器上的时候,项目才可以正常运行(接口是通的);现在需求:在现有的项目代码上进行修改,请求接口是第三方给的。接口是正常的,通过A…

stm32f407 ADC学习记录

主要特性: ● 可配置 12 位、10 位、8 位或 6 位分辨率 ● 在转换结束、注入转换结束以及发生模拟看门狗或溢出事件时产生中断 ● 单次和连续转换模式 ● 用于自动将通道 0 转换为通道“ n ”的扫描模式 ● 数据对齐以保持内置数据一致性(16位的数据…

Python pycparser(c文件解析)模块使用教程

文章目录 安装 pycparser 模块模块开发者网址获取抽象语法树1. 需要导入的模块2. 获取 不关注预处理相关 c语言文件的抽象语法树ast3. 获取 预处理后的c语言文件的抽象语法树ast 语法树组成1. 数据类型定义 Typedef2. 类型声明 TypeDecl3. 标识符类型 IdentifierType4. 变量声明…

Jmeter快捷方式和应用图标设置

很多人在安装Jmeter,安装到本机却没有icon,每次使用的时候,每次打开应用都要找目录,不太方便。 【解决问题】 使用bin路径下的一个.bat文件,创建快捷方式。 【操作步骤】 Step1、将Jmeter 安装bin路径下的jmeter.bat 发送快捷方…

用node.js搭建一个视频推流服务

由于业务中有不少视频使用的场景,今天来说说如何使用node完成一个视频推流服务。 先看看效果: 这里的播放的视频是一个多个Partial Content组合起来的,每个Partial Content大小是1M。 一,项目搭建 (1)初…

微信小程序纯前端从阿里云OSS下载json数据-完整版

起因 因为云开发开始收费(貌似很久了),准备改造在以前的小程序,数据转到oss上,小程序使用原生,不算专业领域, 所以先百度.... 网上的教程真的是千篇一律,大部分开局就是require(ali-oss); 好点的npm install ali-oss --save开局,拼凑操作到最后发现要用云开发,因为云…

在Orangepi5开发板3588s使用opencv获取摄像头画面

先感谢香橙派群的管理员耐心指导,经过不断的调试修改最后成功通过opencv调用mipi摄像头获取画面 就记录分享一下大概步骤希望大家少踩点坑!!!!!! 我用的固件系统是ubuntu2022.0.4 固件是&#x…

【jwt】JWT原理,JWT是用来解决什么问题的,如何自定义生成JWT数据,并且实现jwt数据的解码

JWT: JSON Web Token 1. jwt概述 用户登录成功后,服务端 如何知道客户端的每次请求对应的是哪个用户呢?怎么做:目前有两种方式实现. 1.1. 一是通过sessionId的方式,登录成功后服务端返回sessionId给客户端&#xff0…

Linux_10_进程、系统性能和计划任务

目录 1 进程和内存管理1.1 什么是进程1.2 进程结构1.3 进程相关概念1.3.1 物理地址空间和虚拟地址空间1.3.2 用户和内核空间1.3.3 C代码和内存布局之间的对应关系1.3.4 进程使用内存问题1.3.4.1 内存泄漏: Memory Leak1.3.4.2 内存溢出: Memory Overflow1.3.4.3 内存不足: OOM …

【STM32RT-Thread零基础入门】 5. 线程创建应用(线程创建、删除、初始化、脱离、启动、睡眠)

硬件:STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 文章目录 前言一、线程管理接口介绍二、任务:使用多线程的方式同时实现led闪烁和按键控制喇叭(扫描法)1. RT-Thread相关接…

STM32 FLASH 读写数据

1. 《STM32 中文参考手册》,需要查看芯片数据手册,代码起始地址一般都是0x8000 0000,这是存放整个项目代码的起始地址 2. 编译信息查看代码大小,修改代码后第一次编译后会有这个提示信息 2.1 修改代码后编译,会有提示…

ant-design-vue在ios使用AUpload组件唤起了相机,HTML的 `capture` 属性

在使用ant design vue组件的上传组件AUpload的时候有一个问题&#xff0c;直接按照demo写&#xff0c;在ios上会唤起相机&#xff0c;但是实际上我们的需求是弹出选择相册/相机这个弹框。 解决办法是加一个 cupture"null"这个属性即可 <a-upload:capture"nu…