Zookeeper详细使用解析!分布式架构中的协调服务框架最佳选型实践
Zookeeper概念
- Zookeeper是分布式协调服务,用于管理大型主机,在分布式环境中协调和管理服务是很复杂的过程,Zookeeper通过简单的架构和API解决了这个问题
Zookeeper实现分布式锁
分布式锁三要素:
加锁
解锁
锁超时
- Zookeeper数据结构类似树结构,由节点Znode组成
- Znode分为四种类型:
- 持久节点(PERSISTENT): 默认节点类型,创建节点的客户端与Zookeeper断开连接后,节点依旧存在
- 持久节点顺序节点(PERSISTENT_SEQUENTIAL): 持久节点顺序节点就是在创建持久节点时,Zookeeper根据创建节点的时间顺序给节点进行编号
- 临时节点(EPHEMERAL): 创建节点的客户端与Zookeeper断开连接后,临时节点会被删除
- 临时节点顺序节点(EPHEMERAL_SEQUENTIAL): 临时节点顺序节点就是在创建临时节点时,Zookeeper根据创建节点的时间顺序给节点进行编号
- 应用Zookeeper的临时顺序节点,实现分布式锁
Zookeeper与Redis分布式锁比较:
| 分布式锁 | Zookeeper | Redis |
|---|---|---|
| 优点 | 1.有封装好的框架,容易实现 2.有等待锁队列,提升抢锁的效率 |
Set和Del指令性能高 |
| 缺点 | 添加和删除节点性能低 | 1.实现复杂,需要考虑原子性,误删,锁超时问题 2.没有等待锁的队列,只能客户端自旋来等锁,效率低 |
Zookeeper的数据模型
- 类似数据结构中的树,文件系统中的目录
- Zookeeper的数据存储基于节点Znode
- Znode的引用方式是路径引用,每一个Znode节点拥有唯一的路径
Znode中的元素
- data: Znode存储的数据信息
- ACL: 记录Znode的访问权限,即哪些进程和IP可以访问本节点
- stat: Znode的各种元数据(数据的数据)
- child: 当前节点的子节点引用
Zookeeper的应用场景是读多写少的应用场景:Znode不用来存储大规模的业务数据,用于存储少量的状态和配置信息(Znode存储数据不能超过1MB)
Zookeeper基本操作
- 创建节点:create
- 删除节点:delete
- 判断节点是否存在:exists
- 获得一个节点的数据:getData
- 设置一个节点的数据:setData
- 获取节点下的所有子节点:getChildren
exists,getData,getChildren属于读操作,Zookeeper客户端在请求读操作时,可以选择是否设置watch
Zookeeper事件通知
- Watch可以理解成注册在特定Znode上的触发器
- 当Znode发生改变的时候,调用create,delete,setData方法,将会触发Znode上注册的对应事件,请求的Watch的客户端会接收到异步通知
- Zookeeper事件通知的交互过程:
- 客户端调用getData方法,watch的参数是true,服务端接收到请求,返回节点数据,在对应的Hash表中插入被Watch的Znode路径以及Watcher列表
- 当被Watch的Znode删除,服务端会查找Hash表,找到该Znode对应的所有Watcher,异步通知客户端,并且删除Hash表中对应的key-value
Zookeeper的一致性
- Zookeeper Service集群是一主多从结构
- 在更新数据时,首先更新到主服务器,再同步到从服务器
- 在读数据时,直接读取任意节点
- 采用ZAB协议,为了保证主从节点数据的一致性
ZAB协议
- ZAB(Zookeeper Automic Broadcast): 解决Zookeeper集群崩溃恢复,主从数据同步问题
- ZAB三种节点状态:
- Looking:选举状态
- Following:Following节点(从节点)所处的状态
- Leading:Leading(主节点)所处的状态
- 最大ZXID: 节点本地的最新事务编号,包含epoch和计数两部分
ZAB集群崩溃恢复
- 当Zookeeper的主节点服务器宕机后,集群就会进行崩溃恢复,分成三个阶段:
- Leader election(选举阶段):
- 集群中的节点处于Looking状态,各自向其它节点发起投票,投票当中包含自己服务器的ID和最新事务ID(ZXID)
- 节点用自身的ZXID和其它节点收到的ZXID作比较,如果发现其它节点的ZXID比自身大,即数据比自己新,就重新发起投票,投票给目前已知最大ZXID所属节点
- 每次投票后,服务器都会统计投票数量,判断是否某个节点得到半数以上的投票,这样的节点将会成为准Leader,状态变为Leading,其它节点状态变为Following
- Discovery(发现阶段):
- 在从节点发现最新的ZXID和事务日志,目的是为了防止在意外情况,选举产生多个Leader
- Leader接收所有Follower发送的最新的epoch值,Leader从中选出最大的epoch,基于此值+1,生成新的epoch分发给各个Follower
- 各个Follower接收到最新的epoch,返回ACK(响应码)给Leader,带上各自最大的ZXID和历史事务日志,Leader选出最大的ZXID,并更新自身历史日志
- Synchronization(同步阶段):
- 将Leader收集得到的最新历史事务日志,同步给集群中的所有Follower,只有当半数Follower同步成功,这个准Leader才能成为正式Leader.集群崩溃恢复正式完成
- Leader election(选举阶段):
ZAB主从数据同步
- Broadcast
Zookeeper常规情况下更新数据的时候,由Leader广播到所有的Follower:- 客户端发出写入数据请求给任意的Follower
- Follower把写入数据请求转发给Leader
- Leader采取二阶段提交方式:(先保留提交日志,再提交数据)先发送Propose广播给Follower
- Follower接收到Propose消息,写入日志成功后,返回ACK消息给Leader
- Leader接收到半数以上的ACK消息,返回成功给客户端,并且广播commit请求给Follower
数据一致性:
强一致性
弱一致性
顺序一致性:Zookeeper,依靠事务ID和版本号,保证数据的更新和读取是有序的
Zookeeper应用场景
- 分布式锁: 应用Zookeeper的临时顺序节点,实现分布式锁
- 服务注册与发现: 利用Znode和Watcher,实现分布式服务注册与发现,如Dubbo
- 共享配置和状态信息: Redis的分布式解决方案Codls,利用Zookeeper存放数据路由表和codls-proxy节点元信息,同时colds-config发起的命令都会通过Zookeeper同步到各个存活的codls-proxy
- 高可用实现: Kafka,HBase,Hadoop都依靠Zookeeper同步节点信息,实现高可用
基于Docker创建Zookeeper
1.创建docker-compose.yml
zoo:
image: zookeeper
restart: always
hostname: zoo
ports:
- 2181:2181
environment:
- ZOO_MY_ID: 1
- ZOO_SERVER: server.1(id)=zoo(IP):2888:3888
2.执行docker-compose up -d
Zookeeper三种工作模式
- 单机模式: 存在单点故障
- 集群模式: 在多台服务器上部署Zookeeper集群
- 伪集群模式: 在同一台服务器上运行多个Zookeeper实例,仍然有单点故障问题,其中配置的端口号要错开
Zookeeper三种端口号
- 2181: 客户端连接Zookeeper集群使用的监听端口号
- 3888: 选举Leader使用
- 2888: 集群内机器通讯使用(Leader和Follower之间数据同步使用的端口号,Leader监听此端口)
Zookeeper详细使用解析!分布式架构中的协调服务框架最佳选型实践的更多相关文章
- Zookeeper在分布式架构中的应用
Zookeeper 是一个高性能.高可靠的分布式协调系统,是 Google Chubby 的一个开源实现.Zookeeper 能够为分布式应用提供一致性服务,提供的功能包括:配置维护.域名服务.分布式 ...
- 分布式架构中shiro
分布式架构中shiro 前言:前段时间在搭建公司游戏框架安全验证的时候,就想到之前web最火的shiro框架,虽然后面实践发现在netty中不太适用,最后自己模仿shiro写了一个缩减版的,但是中间花 ...
- 分布式架构中一致性解决方案——Zookeeper集群搭建
当我们的项目在不知不觉中做大了之后,各种问题就出来了,真jb头疼,比如性能,业务系统的并行计算的一致性协调问题,比如分布式架构的事务问题, 我们需要多台机器共同commit事务,经典的案例当然是银行转 ...
- Zookeeper系列二:分布式架构详解、分布式技术详解、分布式事务
一.分布式架构详解 1.分布式发展历程 1.1 单点集中式 特点:App.DB.FileServer都部署在一台机器上.并且访问请求量较少 1.2 应用服务和数据服务拆分 特点:App.DB.Fi ...
- shiro权限控制(二):分布式架构中shiro的实现
前言:前段时间在搭建公司游戏框架安全验证的时候,就想到之前web最火的shiro框架,虽然后面实践发现在netty中不太适用,最后自己模仿shiro写了一个缩减版的,但是中间花费两天时间弄出来的shi ...
- [转]Todd.log - a place to keep my thoughts on programming 分布式架构中的幂等性
Todd.log - a place to keep my thoughts on programming 理解HTTP幂等性 基于HTTP协议的Web API是时下最为流行的一种分布式服务提供方式. ...
- 分布式 PostgreSQL 集群(Citus),分布式表中的分布列选择最佳实践
确定应用程序类型 在 Citus 集群上运行高效查询要求数据在机器之间正确分布.这因应用程序类型及其查询模式而异. 大致上有两种应用程序在 Citus 上运行良好.数据建模的第一步是确定哪些应用程序类 ...
- 分布式架构探索 - 2. WebService RPC框架之Apache CXF
Apache CXF是一个开源的WebService RPC框架. 例子: 1. 新建一个maven web项目, 添加pom 如下: <?xml version="1.0" ...
- 复杂分布式架构下的计算治理之路:计算中间件 Linkis
前言 在当前的复杂分布式架构环境下,服务治理已经大行其道.但目光往下一层,从上层 APP.Service,到底层计算引擎这一层面,却还是各个引擎各自为政,Client-Server 模式紧耦合满天飞的 ...
随机推荐
- 实验: survivor放不下的对象进入老年代
实验一: 存活对象包含 小于survivor大小的对象 + 大于survivor的对象 private static final Integer _1MB = 1024 * 1024; /** * - ...
- P1014_Cantor表 (JAVA语言)
题目描述 现代数学的著名证明之一是Georg Cantor证明了有理数是可枚举的.他是用下面这一张表来证明这一命题的: 1/11/1 , 1/21/2 , 1/31/3 , 1/41/4, 1/51/ ...
- Swagger接口如何生成Html离线文档
A very simple tool that converts Swagger Api Document to Html File. 小记Swagger接口生成Html离线文档 由来 很多人用swa ...
- JS实现环绕地球飞行的3D飞行线动画效果(JS+HTML)
1.项目介绍 JS+HTML实现绕地球飞行的3D飞行线动画效果,且3D地球可以随意拖动和滑动缩放,画面中心是蓝色地球,地球表面上的两点连线之间有光电随机出现沿着抛物线轨迹3D飞行,可使用较好的浏览器打 ...
- python2爬取国家统计局全国省份城市区街道信息
工作中,再次需要python,发现python用得好 ,真的可以节省很多人力,先说我的需求,需要做一个类似像支付宝添加收货地址时,选择地区的功能,需要详细到街道信息,也就是4级联动,如右图.首先需要的 ...
- 自动化kolla-ansible部署ubuntu20.04+openstack-victoria之vmware设置-02
自动化kolla-ansible部署ubuntu20.04+openstack-victoria之vmware设置-02 欢迎加QQ群:1026880196 进行讨论 1. vmwae版本 2. 网 ...
- (十五)VMware Harbor 标签管理
1. Harbor提供两种标签用来隔离各种资源(目前只有镜像): 全局级别标签: 由系统管理员管理,用于管理整个系统的镜像.它们可以添加到任何项目下的镜像中. 项目级别标签: 由项目管理员或者系统管理 ...
- .NET6 平台系列1 .NET发展史之.NET Framework简介
系列目录 [已更新最新开发文章,点击查看详细] 自1995年互联网战略日以来最雄心勃勃的事业 -- 微软.NET战略, 2000年6月30日. 微软公司于2002年2月13日正式推出第一代.N ...
- JDBC_10_使用Statement实现升序和降序
使用Statement数据库操作对象实现升序和降序 Statement可以使用在需要SQL语句拼接的情况下,因为在这样的情况下如果使用PreparedStatement就会给需要拼接的某个SQL关键字 ...
- 【golang】golang中结构体的初始化方法(new方法)
准备工作: 定义结构体:Student import ( "fmt" "reflect") type Student struct { StudentId st ...