zk基础—2.架构原理和使用场景

大纲

1.zk的使用场景

2.zk主要会被用于那些系统

3.为什么在分布式系统架构中需要使用zk集群

4.zk分布式系统具有哪些特点

5.zk集群机器的三种角色

6.客户端与zk之间的长连接和会话

7.zk的数据模型znode和节点类型

8.zk最核心的Watcher监听回调机制

9.ZAB协议的主从同步机制和崩溃恢复机制

10.ZAB协议流程之集群启动-数据同步-崩溃恢复

11.采用2PC两阶段提交思想的ZAB消息广播流程

12.zk到底是强一致性还是最终一致性

13.ZAB协议下两种可能存在的数据不一致问题

14.崩溃恢复时新Leader和Follower的数据同步

15.ZAB协议会如何处理需要丢弃的消息的

16.zk的Observer节点的作用

17.zk适合小集群部署 + 读多写少场景的原因

18.zk特性的总结

1.zk的使用场景

(1)分布式锁

(2)集群元数据管理

(3)分布式协调(HA)

(4)zk使用场景总结

Kafka里使用zk进行元数据管理、Master选举、分布式协调,Canal也一样使用zk进行元数据管理、Master选举(HA主备切换),HDFS的HA也是基于zk来做的。

(1)分布式锁

在分布式架构中的分布式锁,就有:Redis分布式锁和zk分布式锁。

(2)集群元数据管理

Kafka和Canal是在分布式集群中运行的分布式架构,都需要一个地方集中式地存储和管理分布式集群的核心元数据,所以它们都选择把分布式集群的核心元数据放在zk中。

(3)分布式协调(HA)

如果有客户端对zk中的数据做了变更,然后zk会通知其他监听这个数据的客户端数据发生变更了。

非常经典的几个分布式协调的场景:

一.Kafka

Kafka有多个Broker,多个Broker会竞争成为一个Controller的角色。如果作为Controller的Broker挂了,那么它在zk里注册的一个节点就会删除。然后其他Broker紧接着会被zk反向通知,继续竞争成为新的Controller。

二.HDFS

HDFS中NameNode的HA架构就部署主备两个NameNode,只有一个NameNode通过zk选举成为Master,另一个NameNode作为备份。

三.Canal

Canal的HA架构也是通过zk,确保一个节点挂掉后,可以通知其他备用节点进行切换,来保证HA。

(4)zk使用场景总结

zk封装了分布式架构中很多核心和主流的需求功能,比如很多分布式系统都需要分布式锁、集中式存储分布式集群的元数据、Master选举、分布式协调,这些功能需求都可以使用zk来实现。

2.zk主要会被用于那些系统

(1)分布式Java业务系统

(2)开源的分布式系统

(3)自研的分布式系统

(1)分布式Java业务系统

比如分布式电商平台、Java开发的互联网平台、或者是传统架构系统,都属于分布式Java业务系统。

这些系统大部分依赖Dubbo、Spring Cloud来对系统进行拆分,拆分成很多服务或子系统后,再相互协调工作来完成最终的功能。

但zk在这类Java业务系统中用得是比较少的,zk在这类Java业务系统中用得比较多的功能也只是分布式锁,即便是分布式锁的功能很多时候也会选择使用Redis分布式锁。

(2)开源的分布式系统

比如Dubbo、HBase、HDFS、Kafka、Canal、Storm、Solr,主要使用zk进行:集中式存储分布式集群的元数据、Master选举实现HA架构、分布式协调和通知。

复制代码
Dubbo:使用zk作为注册中心 + 集中式存储分布式集群的元数据;
HBase:使用zk进行集中式存储分布式集群的元数据;
HDFS:使用zk进行Master选举实现HA架构;
Kafka:使用zk进行集中式存储分布式集群的元数据,分布式协调和通知;
Canal:使用zk进行集中式存储分布式集群的元数据,Master选举实现HA;

Canal、Kafka、HDFS等这些技术都用了zk进行元数据管理和Master选举。

(3)自研的分布式系统

在很多自研类似的一些分布式系统,都可能会考虑:是否需要一个地方集中式存储分布式集群的元数据?是否需要一个组件辅助进行Master选举来实现HA架构?是否需要进行分布式协调和通知?

如果在自研分布式系统时,有类似这样的需求,那么就可以考虑引入zk来满足该需求。

3.为什么在分布式系统架构中需要使用zk集群

(1)自研一个类似zk的系统

(2)使用zk集群

当需要对分布式集群进行:集中式存储元数据、Master选举实现HA、分布式协调和通知时,可以自研一个类似zk的系统,也可以使用zk集群。

(1)自研一个类似zk的系统

如果是单机版本,只部署在一台机器上,里面提供了一些功能。虽然已实现存储一些元数据、支持Master选举、支持分布式协调和通知。但是对于单机版本的系统,万一挂掉了怎么办?

所以需要集群部署,通过多台机器保证高可用,即便挂掉一台机器,都可以继续运行下去。

假设现在有3台机器,要进行元数据的存储。已经向机器1写了一条数据,那么机器1应该怎么把数据同步给其他的机器?所以自研一个类似的zk系统一旦集群部署后,数据一致性应该怎么保证?

(2)使用zk集群

久经考验的zk,bug很少且功能全面,已用在很多工业级的分布式系统中,所以直接使用zk集群即可。

4.zk分布式系统具有哪些特点

(1)集群化部署

(2)树形结构的数据模型

(3)顺序写

(4)数据一致性

(5)高性能

(6)高可用

(7)高并发

(1)集群化部署

3~5台机器组成一个集群,每台机器都在内存保存zk的全部数据。机器间互相通信同步数据,客户端可连接任何一台机器。

(2)树形结构的数据模型

znode的数据结构跟文件系统类似,是有层级关系的树形数据结构。znode的数据结构是树形结构,纯内存保存,znode可以认为是一个节点而已。

lua 复制代码
create /usr/local/uid
create /usr/local/test_file

uid:可以写入一些数据的值,比如hello world
test_file:也可以写入一些数据的值

(3)顺序写

集群中只有一台机器可以写,所有机器都可以读。所有写请求都会分配一个zk集群全局的唯一递增编号ZXID,ZXID的作用就是用来保证客户端发起的写请求都是有顺序的。

(4)数据一致性

任何一台zk机器收到了写请求后都会同步给其他机器,保证数据一致。客户端连接到任何一台zk机器看到的数据都是一致的。

(5)高性能

每台zk机器都在内存维护数据,所以zk集群绝对是高并发高性能的。如果让zk部署在高配置机器上,3台机器的zk集群能抗下每秒几万请求。

(6)高可用

哪怕集群中挂掉不超过一半的机器,都能保证集群可用,数据不会丢失。3台机器可以挂1台,5台机器可以挂2台。

(7)高并发

高并发是由高性能决定的,只要基于纯内存数据结构来处理,那么并发能力是很高的。使用高配置的物理机器进行写,比如1台16核32G可以支持几万QPS,3台16核32G可以支持十几万QPS。

5.zk集群机器的三种角色

通常来说zk集群里有三种角色的机器,分别是Leader、Follower、Observer。集群启动后会自动选举一个Leader出来,只有Leader可以写,Follower只能同步数据和提供数据的读取。如果Leader挂了,那么Follower会继续选举出新的Leader。Observer只能读,而且Observer不参与选举。

6.客户端与zk之间的长连接和会话

zk集群启动后,集群中的各个节点会自己分配好角色。之后客户端跟zk集群建立的连接,是TCP长连接。也就建立了一个会话Session,会通过心跳来感知会话是否存在。

7.zk的数据模型znode和节点类型

zk的核心数据模型就是znode树,往zk写数据就是创建树形结构的znode,里面可以写入值,存放在zk的内存中。

有两种节点:持久节点和临时节点。持久节点,就是哪怕客户端断开连接,也一直存在。临时节点,就是只要客户端断开连接,节点就没了。

顺序节点,就是创建节点时自增加全局递增的编号。

Curator中关于zk分布式锁的实现就是基于zk的临时顺序节点来实现的,加锁时会创建一个临时顺序节点。zk会自动给临时节点加上一个后缀,也就是全局递增的一个编号。如果客户端断开连接,就自动销毁这个客户端加的锁,此时其他客户端就会感知到而尝试去加锁。

如果进行元数据存储,则需要使用持久节点。如果进行分布式协调和通知,则通常使用临时节点。如果实现分布式锁,则通常使用临时顺序节点。

每个znode还有一个Stat用来存放数据版本:

scss 复制代码
一.version(znode的版本)
二.cversion(znode子节点的版本)
三.aversion(znode的ACL权限控制版本)

8.zk最核心的Watcher监听回调机制

zk最核心的机制是:一个客户端可以对znode进行Watcher监听,当znode发生改变时zk会回调该客户端进行通知。

这是非常有用的一个功能,在分布式系统的协调中是非常有必要的。如果zk只支持写和读,那只能实现元数据存储、Master选举和部分功能,对于分布式系统的协调需求就没办法实现了。如系统A监听一个数据的变化,如果系统B更新了该数据,zk需要能通知系统A该数据的变化。

通过对zk内存数据模型(不同节点类型)进行这两种操作:写数据和读数据、监听数据变化(更新数据时反向通知数据变化),就可以实现:存储集群元数据、分布式锁、Master选举、分布式协调监听等功能;

9.ZAB协议的主从同步机制和崩溃恢复机制

ZAB协议使用的是主从架构,需要划分集群角色,有Leader和Follower两种角色。其中Leader和Follower都可以处理读请求,但只有Leader可以处理写请求。

Leader收到事务请求后,会往本地磁盘日志文件写数据,然后转换为Proposal提议并同步给所有的Follower。Follower收到Leader的Proposal提议后,也会往本地磁盘日志文件写数据。

当Leader发现超过半数Follower都收到Proposal提议时,Leader会给所有Follower发送Commit消息提交事务写数据到内存。

如果Leader崩溃了,Follower会重新选举新的Leader保证服务运行。

所以ZAB协议涉及:角色划分、2PC(两阶段)、过半写机制。

10.ZAB协议流程之集群启动-数据同步-崩溃恢复

(1)zk集群启动时会进入数据恢复模式

(2)zk启动完后会进入消息广播模式

(3)Leader宕机时会进入数据恢复模式

(1)zk集群启动时会进入数据恢复模式

集群启动时会选举一个Leader。只要有过半机器认可某台机器是Leader,那么该机器就可以被选举为Leader。

Leader选举出来后,Leader会等待集群中过半Follower与它进行数据同步。只要过半Follower完成数据同步,集群就会退出恢复模式,就可以对外提供服务。当然还没完成数据同步的Follower会继续与Leader进行数据同步。

(2)zk启动完后会进入消息广播模式

客户端既可以连接Leader,也可以连接Follower,但要注意只有Leader可以处理写请求。

如果客户端发送了一个写请求给Follower,那么Follower会把写请求转发给Leader。Leader收到写请求后,会把写请求以Proposal提议的形式同步给所有Follower。过半Follower都收到Proposal后,Leader再发送Commit消息让Follower提交写请求。

(3)Leader宕机时会进入数据恢复模式

当Leader宕机时,Follower会重新选举一个Leader。只要过半Follower都承认一个Follower成为Leader,那么就可以完成选举。

所以在zk集群中,只要宕机的机器数小于一半,那么集群就还可以正常工作。因为还有过半机器存活下来进行重新选举,此时还可以重新选举出新的Leader。新的Leader选举出来后再重新等待过半Follower跟它进行数据同步,过半Follower完成数据同步后集群就会重新进入消息广播模式。

(4)总结

一.集群启动时的数据恢复模式

Leader选举(过半机器选举机制) + (剩余机器)进行数据同步。

二.消息写入时的消息广播模式

Leader采用2PC模式的过半写机制,来给Follower进行同步。

三.Leader宕机时的数据恢复模式

Leader宕机时,只要剩余存活机器超过一半,那么就还可以选举出新的Leader。选举出新的Leader后,Follower会重新进行数据同步。

11.采用2PC两阶段提交思想的ZAB消息广播流程

(1)Leader发起一个事务Proposal之前

(2)每个Follower收到一个事务Proposal后

(3)Leader自己也会进行Commit操作

对每一条消息进行广播时,都是通过2PC实现的。首先Leader广播Proposal提议,然后各个Follower返回ACK响应,Leader收到过半Follower的ACK响应后再广播Commit消息让Follower进行提交。

(1)Leader发起一个事务Proposal之前

Leader会分配一个全局唯一递增的ZXID来严格保证事务处理的顺序,而且Leader会为每个Follower创建一个FIFO队列。队列里会顺序放入发送给Follower的Proposal,从而保证事务处理的顺序。

(2)每个Follower收到一个事务Proposal后

Follower会立即写入本地磁盘日志,写入成功后就可以保证数据不丢失。然后Follower会返回一个ACK给Leader,当过半Follower都返回ACK时,Leader就会发送Commit消息给全部Follower。

(3)Leader自己也会进行Commit操作

Leader和Follower进行Commit之后,就意味这个数据可以被读取到了。

12.zk到底是强一致性还是最终一致性

(1)强一致性

(2)最终一致性

(3)顺序一致性

(1)强一致性

只要写入一条数据,无论从zk哪台机器上都可以马上读取到这条数据。强一致性的写入操作卡住时,直到Leader和全部Follower都进行了Commit,才能让写入操作返回,才能认为写入成功。所以只要写入成功,无论从哪个zk机器查询都能查到,这就是强一致性。很明显,ZAB协议机制下的zk不是强一致性。

(2)最终一致性

写入一条数据,方法返回写入成功。此时马上去其他zk机器上查有可能是查不到的,可能会出现短暂时间的数据不一致。但是过一会儿,一定会让其他机器同步到这条数据,最终一定可以查到写入的数据。

在ZAB协议中:当过半Follower对Proposal提议返回ACK时,Leader就会发送Commit消息给所有Follower。只要Follower或者Leader进行了Commit,那么这个数据就会被客户端读取到。

那么就有可能出现:有的Follower已经Commit了,但有的Follower还没有Commit。某个客户端连接到某个Follower时可以读取到刚刚Commit的数据,但有的客户端连接到另一个Follower时却没法读取到还没有Commit的数据。

所以zk不是强一致性的。Leader不会保证一条数据被全部Follower都Commit后,才让客户端读取到。在Commit的过程中,可能会出现在不同的Follower上读取到的数据是不一致的情况。但完成Commit后,最终一定会让客户端读取到一致的数据。

(3)顺序一致性

zk官方给自己的定义是顺序一致性,当然也属于最终一致性。但zk的顺序一致性比最终一致性更好一点,因为Leader会保证所有的Proposal提议同步到Follower时是按顺序进行同步的。

如果要求zk是强一致性,那么可以手动调用zk的sync()方法。

13.ZAB协议下两种可能存在的数据不一致问题

(1)Leader还没发送Commit消息就崩溃

(2)Leader还没广播Proposal提议就崩溃

(1)Leader还没发送Commit消息就崩溃

Leader收到了过半的Follower的ACK,接着Leader自己Commit了,但还没来得及发送Commit消息给所有Follower自己却宕机了。此时相当于Leader的数据跟所有Follower是不一致的,所以得保证全部Follower最终都完成Commit。

因此Leader崩溃后,就会选举一个拥有最大ZXID的Follower作为Leader,这个Leader会检查事务日志。如果发现自己事务日志里有一个还没进行提交的Proposal提议,那么旧说明旧Leader没来得及发送Commit消息就崩溃了。此时它作为新Leader会为这个Proposal提议向Follower发送Commit消息,从而保证旧Leader提交的事务最终可以被提交到所有Follower中。

同理,如果Leader收到过半Follower的ACK响应后,在发送Commit消息的过程中,出现Leader宕机或者Leader和Follower的网络问题。那么Follower只要与它能找到的Leader(新选举的ZXID最大的Follower或者原来的Leader)进行数据同步,就可以保证新数据在该Follower中完成Commit。

(2)Leader还没广播Proposal提议就崩溃

Leader没来得及发送Proposal提议给所有Follower的时候就宕机了,此时Leader上的这个请求应该是要被丢弃的。

对于这种情况:如果旧Leader日志里有一个事务Proposal提议,它重启后跟新Leader同步,发现这个事务Proposal提议其实是不应该存在的,那么就会直接丢弃。

14.崩溃恢复时新Leader和Follower的数据同步

(1)先发送Proposal提议再发送Commit消息

(2)Commit操作会把数据写入到内存中的znode

(3)通过已同步Follower列表判断数据可用

(4)选择ZXID最大的Follower作为新Leader的原因

(1)先发送Proposal提议再发送Commit消息

新选举出一个Leader后,其他Follower就会跟它进行数据同步。Leader会给每个Follower准备一个队列,然后把所有的Proposal提议都发送给Follower,并紧接着会发送Commit消息给那个Follower。

(2)Commit操作会把数据写入到内存中的znode

Commit操作就是把这条数据加入内存中的znode树形数据结构里,这样客户端就能访问到该数据,当然也会去通知监听这个znode的客户端。而收到Proposal提议时,会将数据以事务日志的形式顺序写入到磁盘。

(3)通过已同步Follower列表判断数据可用

如果一个Follower跟新Leader完成数据同步后,就会加入新Leader的已同步Follower列表中。当这个已同步Follower列表中有过半的Follower时,那么新Leader就可以对外继续提供服务了。

(4)选择ZXID最大的Follower作为新Leader的原因

在选举新Leader时,会挑选拥有最大ZXID的那个Follower作为新Leader。比如5个机器,1Leader + 4个Follower。1个Leader把Proposal发送给4个Follower,其中3个Follower(过半)都收到了Proposal返回ACK了,但是第四个Follower没收到Proposal。此时Leader执行Commit后挂了,Commit消息没法发送给其他Follower。这时剩余4个Follower,只要其中3个投票某一个当Leader,那它就可成为Leader。假设收到Proposal的那3个Follower都投票给没收到Proposal的Follower,那么这条数据就会永久丢失,所以需要选择一个拥有最大ZXID的Follower作为新Leader。

15.ZAB协议会如何处理需要丢弃的消息的

(1)ZAB协议根据epoch处理需要丢弃的消息

(2)ZAB协议的简单总结

(1)ZAB协议根据epoch处理需要丢弃的消息

每一个事务的ZXID是64位的,高32位是Leader的epoch(表示选举轮次),低32位是自增长的序列号。

如果一个Leader刚把一个Proposal提议写入本地磁盘日志,还没来得及广播Proposal提议给全部Follower就崩溃了。那么当新Leader选举出来后,事务的epoch会自增长一位。然后当旧Leader重启后重新加入集群成为Follower时,会发现自己比新Leader多出一条Proposal提议,但该Proposal提议的epoch比新Leader的epoch低,所以会丢弃这条数据。

(2)ZAB协议的简单总结

一.启动时:过半机器选举Leader + 数据同步

二.对外提供服务时:2PC + 过半写机制,顺序一致性(最终一致性)

三.崩溃恢复时:重新选举Leader + 针对两种数据不一致的情况进行处理

16.zk的Observer节点的作用

(1)对于写请求

(2)对于读请求

Observer节点不参与Leader选举,不参与广播提议时过半Follower进行ACK的环节,只处理客户端读请求和同步数据。

(1)对于写请求

由于Leader在进行数据同步时,Observer不会参与到过半写机制里。所以zk集群无论多少台机器,只能是由一个Leader进行写。Leader单机写入最多每秒上万QPS,这是没法扩展的。

因此zk是适合写少的场景。Redis的写QPS可以达10万,zk的写QPS才上万。虽然Redis和zk都是内存级的,而且对写请求的处理都是单线程处理的。但是由于Redis没有过半写机制,所以它的写性能更高。

(2)对于读请求

Follower通常会有2个或4个,这样处理读请求时就可以达到每秒几万QPS。如果引入更多的Follower,那么在过半写机制中会有更多的Follower参与。这会影响Leader写的效率,因此就有了Observer。

所以为了进一步提升zk集群对读请求的处理能力,可以引入Observer节点。由于它只同步数据提供读服务,所以可以无限扩展节点而不影响写效率。

17.zk适合小集群部署 + 读多写少场景的原因

(1)zk集群通常采用三五台机器小集群部署

(2)zk集群适合读多写少的场景

(1)zk集群通常采用三五台机器小集群部署

假设有1个Leader + 20个Follower,总共21台机器。此时由于Follower要参与到ZAB的写请求的过半ACK,所以一个写请求要等至少10个Follower返回ACK才能发送Commit消息。Leader发送Commit消息后才能告诉客户端写请求成功,所以性能会比较差。所以ZAB协议决定了zk集群通常采用1个Leader + 2个Follower的小集群。

(2)zk集群适合读多写少的场景

zk集群的写请求的处理能力是无法扩展的。如果读请求量大,可以加Observer机器。因此zk只适合读多写少的场景,所以zk主要是用来处理分布式系统的一些协调工作。

18.zk特性的总结

(1)集群模式部署

(2)主从架构

(3)内存数据模型

(4)顺序一致性

(5)高性能

(6)高可用

(7)高并发

(1)集群模式部署

一般奇数节点部署,不能超过一半的机器挂掉。因为5台机器可以挂2台,6台机器也最多只能挂2台。所以5台和6台效果一致,所以奇数节点可以减少机器开销。而且zk集群是小集群部署,适用于读多写少的场景。

(2)主从架构

Leader、Follower、Observer。

(3)内存数据模型

znode,多种节点类型,支持Watcher机制实现监听回调通知。

(4)顺序一致性

消息按顺序同步,但是最终才会一致,不是强一致。ZXID的高32位epoch,低32位是自增长的序列号。

(5)高性能

2PC中的过半写机制,纯内存的数据结构,znode。ZAB协议:2PC、过半ACK + 写事务日志,Commit + 写内存数据。

(6)高可用

Follower宕机没影响,Leader宕机有数据不一致问题。新选举的Leader会自动处理,正常运行。但是在恢复模式期间,可能有一小段时间是没法写入zk的。客户端跟zk进行TCP长连接,通过心跳机制维持Session。

(7)高并发

单机Leader写,Observer节点可以线性扩展读QPS。

相关推荐
寒士obj12 小时前
分布式组件【ZooKeeper】
微服务·zookeeper
笨蛋少年派13 小时前
zookeeper简介
分布式·zookeeper·云原生
007php0074 天前
百度面试题解析:Zookeeper、ArrayList、生产者消费者模型及多线程(二)
java·分布式·zookeeper·云原生·职场和发展·eureka·java-zookeeper
坐吃山猪5 天前
zk02-知识演进
运维·zookeeper·debian
yumgpkpm6 天前
华为鲲鹏 Aarch64 环境下多 Oracle 数据库汇聚操作指南 CMP(类 Cloudera CDP 7.3)
大数据·hive·hadoop·elasticsearch·zookeeper·big data·cloudera
小醉你真好6 天前
16、Docker Compose 安装Kafka(含Zookeeper)
docker·zookeeper·kafka
yumgpkpm8 天前
CMP (类ClouderaCDP7.3(404次编译) )华为鲲鹏Aarch64(ARM)信创环境多个mysql数据库汇聚的操作指南
大数据·hive·hadoop·zookeeper·big data·cloudera
yumgpkpm10 天前
大数据综合管理平台(CMP)(类Cloudera CDP7.3)有哪些核心功能?
hive·hadoop·elasticsearch·zookeeper·big data
回家路上绕了弯13 天前
深入 Zookeeper 数据模型:树形 ZNode 结构的设计与实践
后端·zookeeper
90919322113 天前
SQL关键词标签在数据分析中的应用与实践
zookeeper