分布式系统的管理员 ZooKeeper (一) 介绍
2017-09-03
背景
在调研或使用一些分布式系统的解决方案时,常常会发现ZooKeeper的身影,只知道它的主要功能是为分布式系统提供一致性协调(Coordination)服务。用得多了,就开始有兴趣想去了解它是怎样在分布式系统中起作用的,它自身是如何设计和实现的,所以就有了关于ZooKeeper的这一系列文章。
介绍
顾名思义,ZooKeeper(“动物园管理员”),起这个名字,查了下是因为ZooKeeper是Hadoop下面的一个子项目, 用来协调跟Hadoop相关的一些分布式的框架,如Hadoop, Hive, Pig等, 其实它们都是动物,ZooKeeper又是为了管理它们, 所以就叫这个名字了。 只是现在Zookeeper不仅仅在这些以动物命名的系统中使用,已经广泛的应用在其他分布式系统中了。
在介绍ZooKeeper的应用场景前,有必要先简单介绍一下它自身的一些实现。
- ZooKeeper在实现上类似于一个文件存储系统。它的数据可以挂在某个节点上,可以对这个节点进行增删改查。
- 每个节点叫做Znode,并且每个节点的路径是唯一的。它也可以有子Znode,并且Znode里可以存数据。
- Znode中的数据也可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本。
- Znode可以有不同的类型,Znode可以是临时节点,一旦创建这个Znode的客户端与服务器失去联系,这个Znode也将自动删除。
- Znode可以被监控,这是ZooKeeper的一个让人欣喜的特性,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,在不同的场景下我们就可以做不同的处理。
应用场景
ZooKeeper本身可以以一个单一进程的方式启动,也可以以一组ZooKeeper进程作为一个集群启动。 很明显,以集群的方式启动,会提高整个Zookeeper服务的可靠性,当然配置也复杂些,但是一些优秀的特性也是只有Zookeeper作为一个集群才能给我们提供的。
ZooKeeper的使用场景,主要在分布式系统管理和协调中,细分下来,常见的大概有这么几个:
互斥锁
单一的应用环境,线程、进程的同步,都可以通过操作系统提供的同步机制来完成。但是在分布式系统中,多台机器多个进程之间的同步,靠操作系统就没办法了。这时候就需要像ZooKeeper这样的分布式的协调(Coordination)服务来协助完成同步,原理和单一进程下的锁机制还是很像的:
-
多个进程尝试去在指定的目录下去创建一个临时性(Ephemeral)节点
-
只会有一个进程成功创建该结点,创建结点成功的进程就是抢到锁的进程
-
其它进程都只能对该节点进行Watch
-
当抢到锁的进程不再需要锁,可以显式删除该节点释放锁;或者是进程宕机后Session超时,ZooKeeper系统自动删除该结点释放锁。此时,其它进程就会收到ZooKeeper的通知,并尝试去创建该节点抢锁
这个时候,如果zookeeper是以集群的方式部署的,那么这个锁就是分布式锁,分布式锁的实现方式有不少,接下来的文章我们会对比一下ZooKeeper的分布式锁和Redis实现的分布式锁。
集群选Master
我们现在很多的分布式系统都是mater/slave结构,一般会有一台为master,其余的都是slave,不同角色负责的任务不同。master一般来说承担的责任更大,所以一旦master挂掉能够马上从slave中选出一个master作为替代,对于系统的稳定性是至关重要的。
具体来说,使用ZooKeeper来为集群选master,可以这样做:集群里的每台机器在启动的时候可以在ZooKeeper里创建类型为EPHEMERAL_SEQUENTIAL的节点(创建的节点路径可以用自己机器所在的IP等和其他机器进行区分),这样每个节点会自动被编号。 可以规定编号最小或者最大的为master,当我们对这些节点做监控的时候,得到服务器列表,只要所有集群机器逻辑认为最小或最大编号节点为master,那么master就被选出,而这个master宕机的时候,相应的znode会消失,然后新的服务器列表就被推送到客户端,然后每个节点逻辑认为最小或最大编号节点为master,这样就做到动态master选举。