Distributed topic triple: Zookeeper Cluster Setup

Because cluster environment is simulated in a stand-alone environment, we need to use different ports to simulate different hosts.
Before building a cluster, we start to understand the role Zookeeper clusters;

The role of a cluster of

1) leader (Leader): responsible for initiating and vote on the resolution of the final status update.
2) follower (Follower): Follower for receiving a client request and the result returned to the client. Vote Leader initiated.
3) a viewer (observer): Oberserver may receive client connections, the leader node forwards the request to write. But the Observer does not participate in the voting process, just sync leader of the state. Observer provides a method for the system expansion.
4) learners (Learner): leader and the state synchronization server collectively Learner, and Observer Follower above are Learner.
Here Insert Picture Description

Second, why have Observer

ZooKeeper service can serve each of the plurality of Client Server, and Client Server may be connected to a service ZK either submit a request. If the read request by a local copy of the database on each Server's direct response. Server status change if the write request is handled by the coherence protocol that is Zab protocol we described earlier.

简单来说,Zab协议规定:来自Client的所有写请求,都要转发给ZK服务中唯一的Server—Leader,由Leader根据该请求发起一个Proposal。然后,其他的Server对该Proposal进行投票。之后,Leader对投票进行收集,当投票数量过半时Leader会向所有的Server发送一个通知消息。最后,当Client所连接的Server收到该消息时,会把该操作更新到内存中并对Client的写请求做出回应。

ZooKeeper 服务器在上述协议中实际扮演了两个职能。它们一方面从客户端接受连接与操作请求,另一方面对操作结果进行投票。这两个职能在 ZooKeeper集群扩展的时候彼此制约。例如,当我们希望增加 ZK服务中Client数量的时候,那么我们就需要增加Server的数量,来支持这么多的客户端。然而,从Zab协议对写请求的处理过程中我们可以发现,增加服务器的数量,则增加了对协议中投票过程的压力。因为Leader节点必须等待集群中过半Server响应投票,于是节点的增加使得部分计算机运行较慢,从而拖慢整个投票过程的可能性也随之提高,写操作也会随之下降。这正是我们在实际操作中看到的问题——随着 ZooKeeper 集群变大,写操作的吞吐量会下降

所以,我们不得不,在增加Client数量的期望和我们希望保持较好吞吐性能的期望间进行权衡。要打破这一耦合关系,我们引入了不参与投票的服务器,称为 Observer。

Observer可以接受客户端的连接,并将写请求转发给Leader节点。但是,Leader节点不会要求 Observer参加投票。相反,Observer不参与投票过程,仅仅在上述第3歩那样,和其他服务节点一起得到投票结果。

这个简单的扩展,给 ZooKeeper 的可伸缩性带来了全新的镜像。我们现在可以加入很多 Observer 节点,而无须担心严重影响写吞吐量。但他并非是无懈可击的,因为协议中的通知阶段,仍然与服务器的数量呈线性关系。但是,这里的串行开销非常低。因此,我们可以认为在通知服务器阶段的开销无法成为主要瓶颈。

三、Zookeeper中的CAP

Zookeeper至少满足了CP,牺牲了可用性,比如现在集群中有Leader和Follower两种角色,那么当其中任意一台服务器挂掉了,都要重新进行选举,在选举过程中,集群是不可用的,这就是牺牲的可用性。

但是,如果集群中有Leader、Follower、Observer三种角色,那么如果挂掉的是Observer,那么对于集群来说并没有影响,集群还是可以用的,只是Observer节点的数据不同了,从这个角度考虑,Zookeeper又是牺牲了一致性,满足了AP

四、集群环境搭建

(一)复制配置文件

cd {zookeeperurl}/conf/
cp zoo.cfg zoo1.cfg
cp zoo.cfg zoo2.cfg
cp zoo.cfg zoo3.cfg
cp zoo.cfg zoo_ob.cfg

(二)创建数据以及日志文件目录

mkdir -p /zookeeper/data_1
mkdir -p /zookeeper/data_2
mkdir -p /zookeeper/data_3
mkdir -p /zookeeper/data_ob

mkdir -p /zookeeper/logs_1
mkdir -p /zookeeper/logs_2
mkdir -p /zookeeper/logs_3
mkdir -p /zookeeper/logs_ob

(三)创建myid文件

echo “1” > /zookeeper/data_1/myid
echo “2” > /zookeeper/data_2/myid
echo “3” > /zookeeper/data_3/myid
echo “4” > /zookeeper/data_ob/myid

(四)修改配置文件

zoo1.cfg

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/zookeeper/data_1
clientPort=2181
dataLogDir=/zookeeper/logs_1
#server.x中的x和myid中的一致,
#第一个端口用户Leader和Learner之间的同步,
#第二个端口用于选举过程中的投票通信
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
server.4=localhost:2890:3890:observer

zoo2.cfg

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/zookeeper/data_2
clientPort=2181
dataLogDir=/zookeeper/logs_2
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
server.4=localhost:2890:3890:observer

zoo3.cfg

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/zookeeper/data_3
clientPort=2181
dataLogDir=/zookeeper/logs_3

server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
server.4=localhost:2890:3890:observer

zoo_ob.cfg

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/zookeeper/data_ob
clientPort=2181
dataLogDir=/zookeeper/logs_ob
peerType=observer

server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
server.4=localhost:2890:3890:observer

(五)启动集群

zkServer.sh start {zookeeperUrl}/apache-zookeeper-3.5.5-bin/conf/zoo1.cfg
zkServer.sh start {zookeeperUrl}/apache-zookeeper-3.5.5-bin/conf/zoo2.cfg
zkServer.sh start {zookeeperUrl}/apache-zookeeper-3.5.5-bin/conf/zoo3.cfg
zkServer.sh start {zookeeperUrl}/apache-zookeeper-3.5.5-bin/conf/zoo_ob.cfg

(六)验证

zkServer.sh status {zookeeperUrl}apache-zookeeper-3.5.5-bin/conf/zoo1.cfg
zkServer.sh status {zookeeperUrl}apache-zookeeper-3.5.5-bin/conf/zoo2.cfg
zkServer.sh status {zookeeperUrl}apache-zookeeper-3.5.5-bin/conf/zoo3.cfg
zkServer.sh status {zookeeperUrl}apache-zookeeper-3.5.5-bin/conf/zoo_ob.cfg

可以看到server1:Mode: follower
可以看到server2:Mode: leader
可以看到server3:Mode: follower
可以看到server4:Mode: observer

关闭指令:

zkServer.sh stop {zookeeperUrl}apache-zookeeper-3.5.5-bin/conf/zoo1.cfg
zkServer.sh stop {zookeeperUrl}apache-zookeeper-3.5.5-bin/conf/zoo2.cfg
zkServer.sh stop {zookeeperUrl}apache-zookeeper-3.5.5-bin/conf/zoo3.cfg
zkServer.sh stop {zookeeperUrl}apache-zookeeper-3.5.5-bin/conf/zoo_ob.cfg
Here Insert Picture Description
打开四个命令行客户端分别连上四个server
zkCli.sh -server localhost:2181
zkCli.sh -server localhost:2182
zkCli.sh -server localhost:2183
zkCli.sh -server localhost:2184

连上之后,在三个客户端执行ls /可以分别查到4个server的当前目录结构都是一样的。
在server1上执行命令create /firstNode “server1创建的”,执行完成后可以看到在server2、server3、server4都能同步被创建成功。

Observer
节点配置中增加

peerType=observer

servers列表中增加:

server.4=localhost:2890:3890:observer

(七)排坑

如果启动异常,可以查看日志
bash zkServer.sh start-foreground …/conf/zoo_ob.cfg

我搭建集群是,复制粘贴写最下面的端口时,末尾不小心打了一个空格,所以总是启动报错,大家搭建集群的时候也要注意细节哦。

五、Zookeeper能做什么?

(一)统一命名服务

命名服务也是分布式系统中比较常见的一类场景。在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息。被命名的实体通常可以是集群中的机器,提供的服务地址,远程对象等等——这些我们都可以统称他们为名字(Name)。其中较为常见的就是一些分布式服务框架中的服务地址列表。通过调用ZK提供的创建节点的API,能够很容易创建一个全局唯一的path,这个path就可以作为一个名称。

(二)配置中心

配置的管理在分布式应用环境中很常见,例如同一个应用系统需要多台 PC Server 运行,但是它们运行的应用系统的某些配置项是相同的,如果要修改这些相同的配置项,那么就必须同时修改每台运行这个应用系统的 PC Server,这样非常麻烦而且容易出错。

像这样的配置信息完全可以交给 Zookeeper 来管理,将配置信息保存在 Zookeeper 的某个目录节点中,然后将所有需要修改的应用机器监控配置信息的状态,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中。

集群管理与Master选举

集群机器监控:这通常用于那种对集群中机器状态,机器在线率有较高要求的场景,能够快速对集群中机器变化作出响应。这样的场景中,往往有一个监控系统,实时检测集群机器是否存活。过去的做法通常是:监控系统通过某种手段(比如ping)定时检测每个机器,或者每个机器自己定时向监控系统汇报“我还活着”。
利用ZooKeeper有两个特性,就可以实时另一种集群机器存活性监控系统:

  1. 客户端在节点 x 上注册一个Watcher,那么如果 x?的子节点变化了,会通知该客户端。
  2. 创建EPHEMERAL类型的节点,一旦客户端和服务器的会话结束或过期,那么该节点就会消失。

例如,监控系统在 /clusterServers 节点上注册一个Watcher,以后每动态加机器,那么就往 /clusterServers 下创建一个 EPHEMERAL类型的节点:/clusterServers/{hostname}. 这样,监控系统就能够实时知道机器的增减情况,至于后续处理就是监控系统的业务了。
在分布式环境中,相同的业务应用分布在不同的机器上,有些业务逻辑(例如一些耗时的计算,网络I/O处理),往往只需要让整个集群中的某一台机器进行执行,其余机器可以共享这个结果,这样可以大大减少重复劳动,提高性能,于是这个master选举便是这种场景下的碰到的主要问题。

(三)分布式锁

分布式锁,这个主要得益于ZooKeeper为我们保证了数据的强一致性。锁服务可以分为两类,一个是保持独占,另一个是控制时序。
所谓保持独占,就是所有试图来获取这个锁的客户端,最终只有一个可以成功获得这把锁。通常的做法是把zk上的一个znode看作是一把锁,通过create znode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。

Control of the timing is that all attempts to acquire the lock of the client, are ultimately will be scheduled for execution, but there is a global timing up. And substantially similar to the above practices, where only / distribute_lock already pre-existing, the client creates an ordered temporary node (which can be controlled by property node: CreateMode.EPHEMERAL_SEQUENTIAL specified) below it. Zk parent node (/ distribute_lock) maintain a sequence, to ensure that the timing of the creation of a child node, thus forming a global timing for each client.

The above are Luban School learning materials, we welcome the report classes, really recommend!

Published 143 original articles · won praise 49 · Views 250,000 +

Guess you like

Origin blog.csdn.net/weixin_36586564/article/details/104170099