Zookeeper笔记分享


Zookeeper采用zap协议来保证数据的一致性 常见的数据一致性协议采用raft协议   参数解读:   tickTime=2000:心跳包发送间隔时长   initLimit=10:leader与follower之间初始化时的最大超时时间,10X2000(理解为第一次连接时的超时时长)   syncLimit=5:leader与follower之间正常通讯超时时长,5X2000(集群正常启动之后的通讯超时时长)   clientPort=2181:客户端访问服务端的端口号 选举机制: 半数机制,推荐奇数台服务器 先选自己,如果不行就优先选择myid最大的,先入为主    

Zookeeper简介

  ZooKeeper 是一种分布式协调服务,用于管理大型主机。在分布式环境中协调和管理服务是一个复杂的过程。ZooKeeper 通过其简单的架构和 API 解决了这个问题。ZooKeeper 允许开发人员专注于核心应用程序逻辑,而不必担心应用程序的分布式特性。

分布式应用

  分布式应用可以在给定时间(同时)在网络中的多个系统上运行,通过协调它们以快速有效的方式完成特定任务。通常来说,对于复杂而耗时的任务,非分布式应用(运行在单个系统中)需要几个小时才能完成,而分布式应用通过使用所有系统涉及的计算能力可以在几分钟内完成。 通过将分布式应用配置为在更多系统上运行,可以进一步减少完成任务的时间。分布式应用正在运行的一组系统称为集群,而在集群中运行的每台机器被称为节点。   分布式应用有两部分, Server(服务器) 和 Client(客户端) 应用程序。服务器应用程序实际上是分布式的,并具有通用接口,以便客户端可以连接到集群中的任何服务器并获得相同的结果。 客户端应用程序是与分布式应用进行交互的工具。     ZooKeeper 是一个分布式协调服务的开源框架。主要用来解决分布式集群中应用系统的一致性的问题,例如怎样避免同时操作同一数据造成脏读的问题。ZooKeeper 本质上是一个分布式的小文件存储系统。提供基于类似于文件系统的目录树方式的数据存储,并且可以对树种 的节点进行有效管理。从而来维护和监控你存储的数据的状态变化。将通过监控这些数据状态的变化,从而可以达到基于数据的集群管理。诸如:统一命名服务(dubbo)、分布式配置管理(solr的配置集中管理)、分布式消息队列(sub/pub)、分布式锁、分布式协调等功能。  

Zookeeper 架构图

 

zkCli指令 

zkCli.sh --server host:port:连接到指定的服务端 创建节点必须要设置数据 create (path | znode) data :创建持久节点 create -s (path | znode) data :创建持久顺序编号目录节点 create -e (path | znode) data :创建短暂节点 create -e -s (path | znode) data :创建短暂顺序编号目录节点 get znode:可以获取节点内存储的数据和源数据 get znode watch:注册某个节点的监听服务 set znode newData:设置节点的值 ls znode:查看节点下的子节点 ls znode watch:注册某个节点所有子节点的监听服务 ls2 znode:查看节点的元数据 delete znode:删除节点 rmr znode:递归删除节点 stat znode:查看节点状态   zookeeper就两种集群部署方式:单机部署和集群部署   zk来最适合进行选主,和分布式锁(串行化方式)   ZK写操作   任何一个分布式系统都要满足分区容错性 P,因为不能因为集群中某一的节点宕机,就导致整个集群不具备容错性而导致不能再正常提供服务     什么是AP模型?简单的说就是集群中一般以上节点宕机之后集群仍然可以提供服务,但其实它还涉及到一点,就是服务端每一次的请求都能收到响应,而ZK必须满足一半以上节点存活才能提供服务,而且在选举Leader期间也是不对外提供服务的,由此推断ZK输入CP模型       1 eureka AP eureka 保证了可用性,实现最终一致性。 Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性),其中说明了,eureka是不满足强一致性,但还是会保证最终一致性 2 zookeeper CP zookeeper在选举leader时,会停止服务,直到选举成功之后才会再次对外提供服务,这个时候就说明了服务不可用,但是在选举成功之后,因为一主多从的结构,zookeeper在这时还是一个高可用注册中心,只是在优先保证一致性的前提下,zookeeper才会顾及到可用性
  • C(一致性):所有的节点上的数据时刻保持同步
  • A(可用性):每个请求都能接受到一个响应,无论响应成功或失败
  • P(分区容错):系统应该能持续提供服务,即使系统内部有消息丢失(分区)
高可用、数据一致是很多系统设计的目标,但是分区又是不可避免的事情:
  • CA without P:如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。但其实分区不是你想不想的问题,而是始终会存在,因此CA的系统更多的是允许分区后各子系统依然保持CA。
  • CP without A:如果不要求A(可用),相当于每个请求都需要在Server之间强一致,而P(分区)会导致同步时间无限延长,如此CP也是可以保证的。很多传统的数据库分布式事务都属于这种模式。
  • AP wihtout C:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类。

Zookeeper怎么保证数据的一致性?

  ZooKeeper写数据的机制是客户端把写请求发送到leader节点上(如果发送的是follower节点,follower节点会把军请求转发到leader节点), leader节点会把数据通过proposal请求发送到所有节点(包括自己),所有的节点接受到数据以后都会写到自己到本地磁盘上面,写好了以后会发送一个ack请求给leader,leader只要接受到过半的节点发送ack响应回来,就会发送commit消息给各个节点,各个节点就会把消息放入到内存中(放内存是为了保证高性能),该消息就会用户可见了。那么这个时候,如果ZooKeeper要想保证数据一致性,就需要考虑如下两个情况∶     情况一∶leader执行commit了,还没来得及给follower发送commit的时候,leader宕机了,这个时候如何保证消息一致性?   解决︰当leader宕机以后,ZzooKeeper会选举出来新的Leader,新的leader后动以后要到磁盘上面去检查是否存在没有comit到消息,如果存在,就继续检查看其他follower有没有对这条消息进行了commit,如果有过半节点对这条消息进行了ack,但是没有commit,那么新对1eader要完成commit对操作。   情况二︰客户端把消息写到leader了,但是leader还没发送proposal消息给其他节点,这个时候leader宕机了,leader宕机后恢复的时候此消息又该如何处理?   解决∶客户端把消息写到leader了,但是leader还没发送portal消息给其他节点,这个时候leader宕机了,这个时候对于用户来说,这条消息是写失败的。假设过了一段时间以后leader节点又恢复了,不过这个时候角色就变为了follower了,它在检查自己磁盘的时候会发现自己有一条消息没有进行commit,此时就会检测消息的编号,消息是有编号的,由高32位和低32位组成,高32位是用来体现是否发生过leader切换的,低32位就是展示消息的顺序的。这个时候当前的节点就会根据高32位知道目前leader已经切换过了,所以就把当前的消息删除,然后从新的leader同步数据,这样保证了数据一致性。 Zookeeper的Observer节点 对应一个ZooKeeper集群,我们可能有多个客户端,客户端能任意连接其中一台ZzooKeeper节点,但是所有的客户端都只能往leader节点上面去写数据,所有的客宁端能从所有的节点上面读取数据。如果有客户端连接的是follower节点,然后往follower上发送了写数据的请求,这个时候follower就会把这个写请求转发给1eader节点处理。leader接受到写请求就会往其他节点(包括自己)同步数据,如果过半的节点接受到消息后发送回来ack消息,那么leader节点就对这条消息进行commit,commit后该消息就对用户可见了。因为需要过半的节点发送ack后,l1eader才对消息进行comnit,这个时候会有一个问题,如果集群越大,那么等待过半节点发送回来ack消息这个过程就需要越久,也就是说节点越多虽然会增加集群的读性能,但是会影响到集事的写性能,所以我们一般建议ZooKeeper的集群规模在3到5个节点左右。为了解决这个问题,后来的Zookeeper中增加了一个observer 的角色,这个节点不参与投票,只是负责同步数据。比如我们leader写数据需要过半的节点发送ack响应,这个observer节点是不参与过半的数量统计的。它只是负责从leader同步数据,然后提供给客户端读取,所以引入这个角色目的就是为了增加集群读的性能,然后不影响集群的写性能。用户搭建集群的时候可以自己设置该角色