中国加油,武汉加油!
篇幅较长,配合目录观看
案例准备
- 装了zookeeper的Centos7的虚拟机或者服务器
1. zookeeper介绍
- ZooKeeper是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。
- 简单来说zookeeper=文件系统+监听通知机制。
- ZooKeeper最为主要的使用场景,是作为分布式系统的分布式协同服务。
- 在学习zookeeper之前,先要对分布式系统的概念有所了解。
2. zookeeper树形结构
每个子目录项如 NameService 都被称作为 znode(目录节点),和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。
2.1 znode类型
节点 | 描述 |
---|
ERSISTENT | 持久化目录节点,客户端与zookeeper断开连接后,该节点依旧存在 |
PERSISTENT_SEQUENTIAL | 持久化顺序编号目录节点,客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号 |
EPHEMERAL | 临时目录节点,客户端与zookeeper断开连接后,该节点被删除 |
EPHEMERAL_SEQUENTIAL | 临时顺序编号目录节点,客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号 |
3. zookeeper常用命令
节点 | 描述 |
---|
ls path | 显示节点下的子节点 |
create [-s] [-e] path | 创建节点 [-s] 顺序节点,[-e] 临时性节点 |
get path | 获取节点内容 |
set path value | 设置节点的内容 |
delete path | 删除节点 |
4. zookeeper监听通知机制(watch)
- zookeeper提供了节点watch的功能,zookeeper的client监控zookeeper上的节点,当节点变动的时候,client会收到变动事件和变动后的内容。
- 基于zookeeper的这个特性,我们可以给服务器集群中的所有机器都注册watch事件,监控特定znode,节点中存储部署代码的配置信息,需要更新代码的时候,修改znode中的值,服务器集群中的每一台server都会收到代码更新事件,然后触发调用,更新目标代码。
- 也可以很容易的横向扩展,可以随意的增删机器,机器启动的时候注册监控节点事件即可。
5. zookeeper应用场景
5.1 配置文件管理
- 程序通常会需要进行一些配置文件进行配置的管理。但是如果对于分布式项目来说,可能会部署在不同的服务器上,这样每台服务都会有自己的一套配置,如果需要对某些配置进行调整,则需要逐一的对各个服务器进行修改。zookeeper能够实现统一的配置文件管理。
- 将需要统一管理的配置全部放到zookeeper上去,保存在 zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 zookeeper的通知,然后从 zookeeper获取新的配置信息应用到系统中。
5.2 集群管理
- 所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。
- 一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除。新机器加入也是类似,
- 我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。
5.3 分布式锁
- 我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。
- 所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。
- 用完删除掉自己创建的distribute_lock 节点就释放出锁
5.4 命名服务(Dubbo监控中心原理)
- 在日常开发中,我们会遇到这样的场景:服务A需要访问服务B,但是服务B还在开发过程中(未完成),那么服务A(此时已完成)就不知道如何获取服务B的访问路径了,使用zookeeper的服务就可以简单解决。
- 服务B部署成功后,可以先到zookeeper注册服务(即在zookeeper添加节点/service/B和节点数据)。
- 服务A开发结束后,部署到服务器,然后服务A监控zookeeper服务节点/service/B。
- 如果发现节点有数据了,那么服务A就可以访问服务B了。
5.5 发现服务
- 注册一个持久节点/service/business/what,他下面的每个子节点都是一个可用服务,保存了服务的地址端口等信息。
- 服务调用者通过zookeeper获取/service/business/what所有子节点信息来得到可用的服务。下面的节点都是临时节点,服务器启动的时候会过来注册一个临时节点,服务器挂掉之后或主动关闭之后,临时节点会自动移除。
- 这样就可以保证使用者获取的what服务都是可用的,而且可以动态的扩容缩容。
6. zookeeper集群
- zookeeper集群存在两个角色,一个是Leader其他都是Follower。
- 一个zookeeper集群同一时刻只会有一个 Leader,其他都是 Follower。
- Leader 负责数据的读写,而Follower只负责数据的读,如果Follower遇到写操作,会提交到Leader。
- ZooKeeper 集群的所有机器通过一个 Leader 选举过程来选定一台被称为『Leader』 的机器,Leader服务器为客户端提供读和写服务。Follower只提供读服务,不能提供写服务。
4.1. 如果有机器要对节点做更新,这个机器先告诉Leader。
4.2. Leader收到后广播给所有的节点进行写操作,每个角色都在自己的机器中写。
4.3. 每个机器写完后都给Leader汇报是否写入成功
4.4. 如果有一半的机器写成功了Leader就下发第二个指令
4.5. 广播提交事务
6.1 Leader选举
- 所有节点都有两个属性,sid和zxid。
- 选举的目的就是选目前所有节点中拥有最大zxid的节点作为Leader。
- 如果拥有的zxid相同,就选取sid最大的节点作为Leader,其他节点变为Follower。
- zxid:服务器中存放的最大数据ID,值越大说明数据越新,在选举算法中数据越新权重越大,每次数据变动都会自增。
- sid:该投票信息所属的serverId(比如有三台服务器,编号分别是1,2,3)。
6.2 过半数存活原则
- 在zookeeper集群中,当存活的机器数量超过总机器的一半的时候,整个集群才能正常工作,否则拒绝访问。
- 基于过半数存活原则,zookeeper的集群机器数量一定是奇数台。
- 因为2N+1和2N+2的容灾能力是一样的,基于成本考虑2N+1台的选择方案更优。
6.3 为什么zookeeper需要设计一个过半数存活机制?
- 脑裂问题:集群中的节点监听不到leader节点的心跳, 就会认为leader节点出了问题,此时集群将分裂为不同的小集群, 这些小集群会各自选举出自己的leader节点, 导致原有的集群中出现多个leader节点。
- 为了防止网络脑裂,保证数据的强一致性,因为整个集群中,有可能因为网络问题"脑裂",导致整个集群分为2个甚至多个集群。
- 如果没有过半数存活机制,那么整个zookeeper会变成多个集群,那么zookeeper提供的数据无法再保证数据一致性;