本文将详细讲解ZooKeeper的核心原理和应用场景,文章内容质量较高,所以边肖会分享给大家参考。希望你看完这篇文章后有所了解。
为什么会有动物园管理员?
我们知道编写一个分布式应用程序是非常困难的,主要原因是本地失败。当消息通过网络在两个节点之间传输时,如果网络出现故障,发送方不知道接收方是否收到了消息。收到消息后可能有网络故障,可能没有收到消息,也可能是接收方进程停滞。发件人确认的唯一方法是再次连接发送消息并询问他。这是局部故障:我根本不知道手术是否失败。因此,大多数分布式应用程序需要一个主控制器和协调控制器来管理物理分布的子流程。因此,大多数应用程序需要开发一个私有的协调程序,重复编译协调程序会浪费时间。此时,需要一个具有良好可扩展性的通用协调器。因为这个场景,动物园管理员应运而生。ZooKeeper旨在减少分布式应用程序承担的协调任务。
ZooKeeper常用的应用场景
01/分布式协调
分布式协调仅仅意味着有人监控了ZooKeeper中的数据。如果ZooKeeper中被监控的数据被修改,ZooKeeper将反过来告诉发起监控的人数据的变化。比如在卡夫卡的设计中,卡夫卡的一个节点在ZooKeeper中创建了一个数据。卡夫卡的策略是,谁创建了这个数据,谁就是卡夫卡集群的主节点,其他节点都会监听这个数据。如果主节点宕机,ZooKeeper对应的数据会发生变化,然后其他监听这个数据的节点会感知到主节点宕机,然后重新选举。
02/元数据管理
许多分布式程序需要集中管理它们的元数据,此时ZooKeeper是一个不错的选择。例如,Kafka和Storm等分布式工具会将核心元数据存储在ZooKeeper中。
03/高可用性
很多分布式项目都是主从架构。在正常情况下,一个集群是主节点,其余的是从节点。但是如果只有一个主节点,程序就会出现单点故障,所以此时需要部署多个主节点来实现高可用性,使用ZooKeeper从多个主节点中选择一个主节点,其余的作为备用节点。比如著名的HDFS就是ZooKeeper实现的高可用性。
04/分布式锁
企业中很多项目都需要分布式锁,我们可以用ZooKeeper来搞分布式锁。但是这里要注意的是,ZooKeeper可以搞分布式锁,但是ZooKeeper不支持太高的并发,这意味着ZooKeeper可能不适合分布式锁。如果并发性高,建议用Redis搞分布式锁,但如果并发性不是太高,用ZooKeeper搞分布式锁更方便,很多人都这样做。
动物园管理员核心原则
01/ZooKeeper集群架构
在ZooKeeper集群中,集群中的服务器角色分为领导者和学习者,学习者分为观察者和跟随者,具体功能如下:
0x01,领导者(leader)
为客户提供读写功能,负责发起和决定投票。只有集群中的领导者才能接受写作服务。
0x02,跟随器(follower)
为客户提供阅读服务,如果是书面服务,转发给领导。在选举过程中投票。
0x03,观察者(观察者)
为客户提供读服务,如果是写服务,转发一个领导。不参与领导的选举投票。不参与写作的半原则机制。在不影响写入的前提下,提高集群读取的性能,这是zookeeper3.3系列的新角色。
0x04,客户端(客户端)
连接到zookeeper集群的用户,请求的发起者,独立于zookeeper集群的角色。
02/ZooKeeper读写机制
在ZooKeeper的选举中,如果超过一半的节点选择一个节点作为领导者,那么这个节点就会成为领导者节点,这也是为什么ZooKeeper集群只要有一半以上的节点活着就可以正常提供服务的原因。例如,有五个ZooKeeper节点,其中两个已经关闭。此时三个节点还活着,存活的节点数超过一半。此时集群还在正常提供服务,所以ZooKeeper集群本来就没有高可用性。因为生存是由一半以上来判断的,所以我们在构建ZooKeeper集群时通常会使用奇数,这样会节省更多的机器。例如,如果我们安装一个6单元的ZooKeeper集群,3单元的停机时间会使集群无法使用,因为此时幸存的节点数量不到一半,所以6单元和5单元的效果是一样的。
,我们用5台比较合适。
对应一个ZooKeeper集群,我们可能有多个客户端,客户端能任意连接其中一台ZooKeeper节点,但是所有的客户端都只能往leader节点上面去写数据,所有的客户端能从所有的节点上面读取数据。如果有客户端连接的是follower节点,然后往follower上发送了写数据的请求,这个时候follower就会把这个写请求转发给leader节点处理。leader接受到写请求就会往其他节点(包括自己)同步数据,如果过半的节点接受到消息后发送回来ack消息,那么leader节点就对这条消息进行commit,commit后该消息就对用户可见了。因为需要过半的节点发送ack后,leader才对消息进行commit,这个时候会有一个问题,如果集群越大,那么等待过半节点发送回来ack消息这个过程就需要越久,也就是说节点越多虽然会增加集群的读性能,但是会影响到集群的写性能,所以我们一般建议ZooKeeper的集群规模在3到5个节点左右。为了解决这个问题,后来的ZooKeeper中增加了一个observer 的角色,这个节点不参与投票,只是负责同步数据。比如我们leader写数据需要过半的节点发送ack响应,这个observer节点是不参与过半的数量统计的。它只是负责从leader同步数据,然后提供给客户端读取,所以引入这个角色目的就是为了增加集群读的性能,然后不影响集群的写性能。用户搭建集群的时候可以自己设置该角色。
03 / Zookeeper 特点
0x01、一致性
client客户端无论连接到集群中的哪个节点,读到的数据都是一样的
0x02、实时性
ZooKeeper保证客户端在一定的时间间隔内获得结果,包括成功和失败,但是由于网络延迟原因,ZooKeeper不能保证两台客户端同时得到刚更新的消息。如果都需要最新的消息需要调用sync()接口。
0x03、原子性
leader在同步数据的时候,同步过程保证事务性,要么都成功,要么都失败。
0x04、顺序性
一台服务器上如果消息a在消息b前发布,那么所有的server上的消息a都是在消息b前发布的。
04 / Zookeeper数据一致性保证
刚刚我们看到了ZooKeeper有多个特点,但是我相信多个特点中,大家最好奇都就是Zookeeper是如何保证数据一致性的。ZooKeeper保证数据一致性用的是ZAB协议。通过这个协议来进行ZooKeeper集群间的数据同步,保证数据的一致性。
0x01、两阶段提交+过半写机制
ZooKeeper写数据的机制是客户端把写请求发送到leader节点上(如果发送的是follower节点,follower节点会把写请求转发到leader节点),leader节点会把数据通过proposal请求发送到所有节点(包括自己),所有到节点接受到数据以后都会写到自己到本地磁盘上面,写好了以后会发送一个ack请求给leader,leader只要接受到过半的节点发送ack响应回来,就会发送commit消息给各个节点,各个节点就会把消息放入到内存中(放内存是为了保证高性能),该消息就会用户可见了。那么这个时候,如果ZooKeeper要想保证数据一致性,就需要考虑如下两个情况,情况一:leader执行commit了,还没来得及给follower发送commit的时候,leader宕机了,这个时候如何保证消息一致性?情况二:客户端把消息写到leader了,但是leader还没发送proposal消息给其他节点,这个时候leader宕机了,leader宕机后恢复的时候此消息又该如何处理?
0x02、ZAB的崩溃恢复机制
针对情况一,当leader宕机以后,ZooKeeper会选举出来新的leader,新的leader启动以后要到磁盘上面去检查是否存在没有commit的消息,如果存在,就继续检查看其他follower有没有对这条消息进行了commit,如果有过半节点对这条消息进行了ack,但是没有commit,那么新对leader要完成commit的操作。
0x03、ZAB恢复中删除数据机制
针对情况二,客户端把消息写到leader了,但是leader还没发送portal消息给其他节点,这个时候leader宕机了,这个时候对于用户来说,这条消息是写失败的。假设过了一段时间以后leader节点又恢复了,不过这个时候角色就变为了follower了,它在检查自己磁盘的时候会发现自己有一条消息没有进行commit,此时就会检测消息的编号,消息是有编号的,由高32位和低32位组成,高32位是用来体现是否发生过leader切换的,低32位就是展示消息的顺序的。这个时候当前的节点就会根据高32位知道目前leader已经切换过了,所以就把当前的消息删除,然后从新的leader同步数据,这样保证了数据一致性。
关于ZooKeeper核心原理及应用场景是什么就分享到这里了,希望
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/157770.html