Zookeeper—知识整理 阳光穿透心脏的1/2处 2022-10-16 03:00 180阅读 0赞 ### 文章目录 ### * * * Zookeeper是什么? * Zookeeper架构是什么样子的? * Zookeeper 下 Server 工作状态 * Zookeeper应用场景? * Zookeeper部署模式? * Zookeeper的数据节点Znode? * Zookeeper命令实战 * * * get:可用于获取节点的值 * set:可用于给节点赋值 * create :可用于创建节点 * delete :可用于删除节点 * 创建其他类型的节点 * Zookeeper 事件监听机制 * Zookeeper选举过程? * Zookeeper实现配置中心原理 * Zookeeper 实现注册中心原理 * Zookeeper实现分布式锁? * Zookeeper实现分布式锁可能出现的问题? * ZAB协议 * * 1. 崩溃恢复 * 2. 消息广播 * ZK ACL 权限控制 ### Zookeeper是什么? ### Zookeeper是为分布式应用提供一致性服务的软件,什么意思呢,它并不用来存储海量数据,更多的是给整个数据库集群提供一致性服务,保存的也是机器相关的数据。 ### Zookeeper架构是什么样子的? ### ![img][] * Leader 领导 * Follower 跟随者 * Client 客户端 一般来说,同一时刻有一个Leader,多个Follower。 ### Zookeeper 下 Server 工作状态 ### 服务器具有四种状态,分别是 LOOKING、FOLLOWING、LEADING、OBSERVING。 (1)LOOKING:寻 找 Leader 状态,也叫投票状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,因此需要进入 Leader 选举状态。 (2)FOLLOWING:跟随者状态。表明当前服务器角色是 Follower。 (3)LEADING:领导者状态。表明当前服务器角色是 Leader。 (4)OBSERVING:观察者状态。表明当前服务器角色是 Observer。 ### Zookeeper应用场景? ### * 服务注册与订阅(共用节点): * 分布式通知(监听znode): * 服务命名(znode特性): * 数据订阅、发布(watcher): * 分布式锁(临时节点): ### Zookeeper部署模式? ### * 单机部署 * 集群部署 * 伪集群部署 ### Zookeeper的数据节点Znode? ### * 持久结点:若非主动删除,否则结点一直存在于Zookeeper上。 * 临时结点:生命周期与客户端会话绑定,随着会话失效,结点自动删除,但这个删除是有时延的。 * 持久顺序结点:在持久结点的基础上,增加`顺序`特性,通过父节点维护的自增整形数字来实现 * 持久临时结点:在临时结点的基础上,增加`顺序`特性,通过父节点维护的自增整形数字来实现 在Zookeeper3.5之后,增加了`容器节点`和`TTL节点` 下面是`apache`对创建节点模式的定义,可以看到除了我们常用的四种节点之外,还有三种与容器节点和TTL节点有关 package org.apache.zookeeper; public enum CreateMode { PERSISTENT(0, false, false, false, false), PERSISTENT_SEQUENTIAL(2, false, true, false, false), EPHEMERAL(1, true, false, false, false), EPHEMERAL_SEQUENTIAL(3, true, true, false, false), CONTAINER(4, false, false, true, false), PERSISTENT_WITH_TTL(5, false, false, false, true), PERSISTENT_SEQUENTIAL_WITH_TTL(6, false, true, false, true); ### Zookeeper命令实战 ### Zookeeper很像文件系统,但是文件系统的目录是无法保存数据的,Zookeeper的每个节点都可以保存数据。 下面以持久化节点操作为例, ##### get:可用于获取节点的值 ##### [zk: localhost:2181(CONNECTED) 4] get /node null 带参数get -s [zk: localhost:2181(CONNECTED) 8] get -s /node wyh cZxid = 0x2 // 事务ID ctime = Wed Aug 18 09:57:48 CST 2021 mZxid = 0x3 mtime = Wed Aug 18 09:58:06 CST 2021 pZxid = 0x2 // 子节点ID cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0 ##### set:可用于给节点赋值 ##### [zk: localhost:2181(CONNECTED) 5] set /node wyh [zk: localhost:2181(CONNECTED) 6] get /node wyh ##### create :可用于创建节点 ##### 创建根节点 [zk: localhost:2181(CONNECTED) 3] create /node Created /node 创建子节点 [zk: localhost:2181(CONNECTED) 9] create /node/subnode Created /node/subnode #### delete :可用于删除节点 #### delete如果有子节点,不可以直接删除,需挨个删除 #### 创建其他类型的节点 #### 临时节点 create -e create -e /expireNode 顺序节点, create -s ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg4OTg0MQ_size_16_color_FFFFFF_t_70] 可以看到,它为每个节点的名字加上了顺序号,保证节点是顺序的 ### Zookeeper 事件监听机制 ### 可以通过-w 指定对数据进行监听,当节点发生变化时,会监听到该事件 [zk: localhost:2181(CONNECTED) 18] get -w /node/subnode # 设置监听 null [zk: localhost:2181(CONNECTED) 19] set /node/subnode hello # 改变数据 WATCHER::# 监听到 [zk: l WatchedEvent state:SyncConnected type:NodeDataChanged path:/node/subnode ocalhost:2181(CONNECTED) 20] 同时,也可以对某个目录进行监听,通过ls -w 实现,这样该目录下产生结点变化,便可以监听到。 ### Zookeeper选举过程? ### zookeeper提供了三种选举Leader的方式: * LeaderElection * AuthFastLeaderElection * FastLeaderElection (最新默认) 默认的选举算法是FastLeaderElection 可简述为: 1. 每个候选人为自己投票 2. 如果票数相同,则观察编号大小,大的占优势 3. 成为Leader的一个条件是投票数过半,否则已投票人仍为Looking状态 ### Zookeeper实现配置中心原理 ### 配置中心主要用来解决每次修改配置文件都需要重启,不能动态修改配置,且在分布式情况下,不易管理。 Zookeeper可以实现配置中心,前面我们知道可以通过`create /node_name` 来创建结点,并且该结点是可以保存数据的 可以把配置文件保存到某结点,之后让多个服务通过客户端`-w` 去监听该节点的变化,若出现变化,则在监听到事件后,便去重新加载该配置文件。 ### Zookeeper 实现注册中心原理 ### * 生产者 通过创建临时结点去注册服务,该临时节点主要保存的是IP、PORT、API等信息 * 消费者 根据生产者注册的服务名称去Zookeeper拿到已注册的服务数据,拉到本地并解析,并在之后通过-w 去监听,例如有新的机器加进来提供相同的服务,那么就会触发事务监听机制,从而消费者可以更新本地的服务信息。 ### Zookeeper实现分布式锁? ### Zookeeper提供实现独占锁和共享锁两种,对于独占锁,同一时刻,只能有一个客户端操作资源,对于共享锁,则是读共享,读写互斥。 zk是基于前面提到的四个结点来实现分布式锁的,因为zk结点是有唯一的特性的。 创建结点实现加锁,删除结点实现释放锁,在释放锁之后通知其他客户端来加锁走业务。 1. 考虑到机器可能宕机,导致结点无法删除,锁也就无法删除了,故采用**临时节点**比较好。 2. 但通知/监听机制可能会导致“羊群效应”,用**顺序节点**可以解决这个问题。 3. 综上,最好是选用**临时顺序结点**来实现分布式锁。 ### Zookeeper实现分布式锁可能出现的问题? ### 如果由于网络抖动,客户端A成功获取了锁,进行业务操作,而之后zk与客户端A的连接断了,删除掉临时结点,此时客户端B就可以进行加锁,产生并发问题。 ### ZAB协议 ### ZAB 协议是 Zookeeper 专门设计的一种支持崩溃恢复的原子广播协议。通过该协议,Zookeeper 基于主从模式的系统架构来保持集群中各个副本之间数据的一致性。具体如下: Zookeeper 使用一个单一的主进程来接收并处理客户端的所有事务请求,并采用原子广播协议将数据状态的变更以事务 Proposal 的形式广播到所有的副本进程上去。如下图: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg4OTg0MQ_size_16_color_FFFFFF_t_70 1] 具体流程如下: 所有的事务请求必须由唯一的 Leader 服务来处理,Leader 服务将事务请求转换为事务 Proposal,并将该 Proposal 分发给集群中所有的 Follower 服务。如果有半数的 Follower 服务进行了正确的反馈,那么 Leader 就会再次向所有的 Follower 发出 Commit 消息,要求将前一个 Proposal 进行提交。 ZAB 协议包括两种基本的模式,分别是崩溃恢复和消息广播: #### 1. 崩溃恢复 #### 当整个服务框架在启动过程中,或者当 Leader 服务器出现异常时,ZAB 协议就会进入恢复模式,通过过半选举机制产生新的 Leader,之后其他机器将从新的 Leader 上同步状态,当有过半机器完成状态同步后,就退出恢复模式,进入消息广播模式。 #### 2. 消息广播 #### ZAB 协议的消息广播过程使用的是原子广播协议。在整个消息的广播过程中,Leader 服务器会每个事物请求生成对应的 Proposal,并为其分配一个全局唯一的递增的事务 ID(ZXID),之后再对其进行广播。具体过程如下: Leader 服务会为每一个 Follower 服务器分配一个单独的队列,然后将事务 Proposal 依次放入队列中,并根据 FIFO(先进先出) 的策略进行消息发送。Follower 服务在接收到 Proposal 后,会将其以事务日志的形式写入本地磁盘中,并在写入成功后反馈给 Leader 一个 Ack 响应。当 Leader 接收到超过半数 Follower 的 Ack 响应后,就会广播一个 Commit 消息给所有的 Follower 以通知其进行事务提交,之后 Leader 自身也会完成对事务的提交。而每一个 Follower 则在接收到 Commit 消息后,完成事务的提交。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg4OTg0MQ_size_16_color_FFFFFF_t_70 2] ### ZK ACL 权限控制 ### 为了避免存储在 Zookeeper 上的数据被其他程序或者人为误修改,Zookeeper 提供了 ACL(Access Control Lists) 进行权限控制。只有拥有对应权限的用户才可以对节点进行增删改查等操作。 Zookeeper 的权限由`[scheme : id :permissions]`三部分组成,其中 `Schemes` 和 `Permissions` 内置的可选项分别如下: **Permissions 可选项**: * **CREATE**:允许创建子节点; * **READ**:允许从节点获取数据并列出其子节点; * **WRITE**:允许为节点设置数据; * **DELETE**:允许删除子节点; * **ADMIN**:允许为节点设置权限。 **Schemes 可选项**: * **world**:默认模式,所有客户端都拥有指定的权限。world 下只有一个 id 选项,就是 anyone,通常组合写法为 `world:anyone:[permissons]`; * **auth**:只有经过认证的用户才拥有指定的权限。通常组合写法为 `auth:user:password:[permissons]`,使用这种模式时,你需要先进行登录,之后采用 auth 模式设置权限时,`user` 和 `password` 都将使用登录的用户名和密码; * **digest**:只有经过认证的用户才拥有指定的权限。通常组合写法为 `auth:user:BASE64(SHA1(password)):[permissons]`,这种形式下的密码必须通过 SHA1 和 BASE64 进行双重加密; * **ip**:限制只有特定 IP 的客户端才拥有指定的权限。通常组成写法为 `ip:182.168.0.168:[permissions]`; * **super**:代表超级管理员,拥有所有的权限,需要修改 Zookeeper 启动脚本进行配置。 经过上述介绍,也可知id可能是anyone、user:password几种 [img]: /images/20221014/bbce70082cf740d5acb1a5e7bdf33f5e.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg4OTg0MQ_size_16_color_FFFFFF_t_70]: /images/20221014/cafd5011f45f4a258c18a20407b54bf4.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg4OTg0MQ_size_16_color_FFFFFF_t_70 1]: /images/20221014/32252daa78334611bf9710a402fefc8d.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg4OTg0MQ_size_16_color_FFFFFF_t_70 2]: /images/20221014/c505e323a7d54507bccee50f30facaaf.png
还没有评论,来说两句吧...