分布式系统:是若干独立计算机的集合,这计算机对用户来说就像单个相关系统。
(1)提升性能和并发,操作被分发到不同的分片,相互独立
(2)提升系统的可用性,即使部分分片不能用,其他分片不会受到影响
(3)提升系统的扩展性。
Zookeeper:一种用于分布式应用程序的高性能协调服务(维护配置信息,命名,提供分布式同步和提供组服务)。并且是开源的分布式的,为分布式应用提供协调服务的Apache项目
从设计模式分析:一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理相关数据(如注册在其上面各个服务器的状态和数据的变化等),然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应,从而实现集群中类似Master/Slave管理模式
Zookeeper工作机制:
Zookeeper=文件系统+通知机制
Zookeeper结构特点:
- Zookeeper:一个领导者(leader),多个跟随者(follower)组成的集群。
- Leader负责进行投票的发起和决议,更新系统状态
- Follower用于接收客户请求并向客户端返回结果,在选举Leader过程中参与投票
- 集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。建议集群数量为奇数
- 全局数据一致:每个server保存一份相同的数据副本,client无论连接到哪个server,数据都是一致的。同步数据
- 更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行。
- 数据更新原子性,一次数据更新要么成功,要么失败。
- 实时性,在一定时间范围内,client能读到最新数据。
Zookeeper数据模型:
ZooKeeper数据模型的结构与Unix文件系统很类似,整体上可以看作是一棵树,每个节点称做一个ZNode。每一个ZNode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识。 路径是绝对路径。
ZooKeeper树中的节点特点:
1.ZooKeeper中每一个节点Zonde通过路径引用,该路径必须是绝对的,必须由斜杠字符来开头,并且必须是唯一的,同时路径由Unicode字符串组成,并且有一些限制。字符串"/zookeeper"用以保存管理信息,比如关键配额信息。另外,
-
空字符(\ u0000)不能是路径名的一部分。(这会导致C绑定出现问题。)
-
无法使用以下字符,因为它们无法正常显示或以令人困惑的方式呈现:\ u0001 - \ u001F和\ u007F - \ u009F。
-
不允许使用以下字符:\ ud800 - uF8FF,\ uFFF0 - uFFFF。
2. ZooKeeper中每一个节点Zonde由三部分组成:stat:此为状态信息, 描述该Znode的版本(每次znode的数据更改时,版本号都会增加), 权限(acl)等信息;data:与该Znode关联的数据;children:该Znode下的子节点。其用来管理协调数据,比如分布式应用中的配置文件信息、状态信息、汇集位置等等。这些数据的共同特性就是它们都是很小的数据,通常以KB为大小单位。
3.每一个节点还存在监控(watch),watch监控节点状态,当其发生改变时(Znode的增、删、改)将会触发watch所对应的操作。当watch被触发时,ZooKeeper将会向客户端发送且仅发送一条通知,因为watch只能被触发一次,这样可以减少网络流量。
4.存储在命名空间中每个znode的数据以原子方式读取和写入。读取获取与znode关联的所有数据字节,写入替换所有数据。每个节点都有一个访问控制列表(ACL),限制谁可以做什么。
5.Znode有两种类型:短暂/持久
短暂(ephemeral):客户端和服务器端断开连接后,创建的节点自动删除
持久(persistent):客户端和服务器端断开连接后,创建的节点不删除
6. Znode上可以添加顺序标识,形成顺序节点,添加方式是在路径结尾添加一个递增的计数。这个计数对于此节点的父节点来说是唯一的,它的格式为"%10d"(10位数字,没有数值的数位用0补充,例如"0000000001")。当计数值大于232-1时,计数器将溢出。
ZooKeeper的API:
操作 | 描述 |
create | 船舰Zonde(父节点必须存在) |
delete | 删除节点(节点没有子节点) |
exists | 验证节点是否存在,并候取它的元数据 |
getACL/setACL | 获取/设置节点权限 |
getChildren | 获取节点所有子节点的列表 |
getData/setData | 获取/设置节点相关数据 |
sync | 是客户端的节点视图与zookeeper同步 |
- update操作是有限制的。delete或setData必须明确要更新的Znode的版本号,可以调用exists找到。如果版本号不匹配,更新将会失败。
- update操作是非阻塞式的。因此客户端如果失去了一个更新(由于另一个进程在同时更新这个Znode),他可以在不阻塞其他进程执行的情况下,选择重新尝试或进行其他操作。
- 文件非常的小置使整体读写的,所以不需要打开、关闭或是查找的操作。