当前位置:   article > 正文

Zookeeper详解_zukepper

zukepper

一、概述

在这里插入图片描述

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。Zookeeper是Apache的一个java项目,属于Hadoop系统,扮演管理员的角色。它为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper提供一种集中式服务,用于维护配置信息,命名,提供分布式同步和提供组服务。所有这些类型的服务都以分布式应用程序的某种形式使用。每次实施它们都需要做很多工作来修复不可避免的错误和竞争条件,ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

    ZooKeeper用于分布式应用程序的分布式开源协调服务。它公开了一组简单的原语,分布式应用程序可以构建这些原语,以实现更高级别的服务,以实现同步,配置维护以及组和命名。它被设计为易于编程,并使用在熟悉的文件系统目录树结构之后设计的数据模型。它在Java中运行,并且具有Java和C的绑定,ZooKeeper包含一个简单的原语集,提供Java和C的接口。ZooKeeper背后的动机是减轻分布式应用程序从头开始实施协调服务的责任。
ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.

Zookeeper设计目标:

ZooKeeper允许分布式进程通过共享的分层命名空间相互协调,该命名空间的组织方式与标准文件系统类似。名称空间由数据寄存器组成 - 在ZooKeeper用语中称为znodes,zookeeper名字空间由节点znode构成 - 这些与文件和目录类似。znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据。如果在创建znode时Flag设置为EPHEMERAL(临时节点,znode有2种类型),那么当创建这个znode的节点和Zookeeper失去连接后,这个znode将不再存在在Zookeeper里,与专为存储而设计的典型文件系统不同,ZooKeeper数据保存在内存中,这意味着ZooKeeper可以实现高吞吐量和低延迟数量。
Zookeeper实现过程中非常重视高性能,高可用性严格有序的访问。ZooKeeper的性能方面意味着它可以在大型分布式系统中使用。可靠性方面使其不会成为单点故障。严格的排序意味着可以在客户端实现复杂同步原语。越来越多的分布式计算开始强依赖ZK,比如Storm、Hbase等;

使用场景:

集群管理、统一命名服务、分布式配置管理、分布式消息队列、分布 式锁、分布式通知协调等。

二、架构及概念

在这里插入图片描述
    zookeeper与它协调的分布式进程一样,ZooKeeper本身也可以在称为集合的一组主机上进行复制。组成ZooKeeper服务的服务器必须彼此了解。它们维护内存中的状态图像,以及持久性存储中的事务日志和快照。只要大多数服务器可用,ZooKeeper服务就可用。

    客户端连接到单个ZooKeeper服务器。客户端维护TCP连接,通过该连接发送请求,获取响应,获取监视事件以及发送心跳。如果与服务器的TCP连接中断,则客户端将连接到其他服务器;

架构解析:

Zookeeper Server数目一般为奇数 ;Leader选举算法采用了Paxos协议;Paxos核心思想:当多数Server写成功,则任务数据写 成功。也就是说: 如果有3个Server,则两个写成功即可; 如果有4或5个Server,则三个写成功即可。 如果有3个Server,则最多允许1个Server挂掉; 如果有4个Server,则同样最多允许1个Server挂掉,既然如此,为啥要用4个Server,3个已经足够?Server数目一般为奇数(3、5、7) 。

2.1 数据模型和分层命名空间

在这里插入图片描述
ZooKeeper提供的名称空间非常类似于标准文件系统。名称是由斜杠(/)分隔的路径元素序列。ZooKeeper名称空间中的每个节点都由路径标识。与标准文件系统不同,ZooKeeper命名空间中的每个节点都可以包含与之关联的数据以及子项。这就像拥有一个既是文件也是目录的文件系统。(ZooKeeper旨在存储协调数据:状态信息,配置,位置信息等,因此存储在每个节点的数据通常很小,在字节到千字节范围内。)我们使用术语znode来表明ZooKeeper的数据节点。

Znodes维护一个stat结构,其中包括数据更改,ACL更改和时间戳的版本号,以允许缓存验证和协调更新。每次znode的数据更改时,版本号都会增加。例如,每当客户端检索数据时,它也接收数据的版本。存储在命名空间中每个znode的数据以原子方式读取和写入。读取获取与znode关联的所有数据字节,写入替换所有数据。每个节点都有一个访问控制列表(ACL),限制谁可以做什么。

ZooKeeper也有短暂(临时)节点的概念。只要创建znode的会话处于活动状态,就会存在这些znode。会话结束时,znode将被删除。当您想要实现[tbd(?)时,短暂节点很有用。
zookeeper中支持watches的概念,客户端可以在znode上设置一个watch,当znode被更新时watch会被触发或删除;当watch被触发时,客户端会收到znode更新的反馈包,如客户端与zookeeper服务集群中的一个服务端中断连接,则客户端将收到本地通知。

2.2 架构中组件角色:

在这里插入图片描述
Observer :

Zookeeper需保证高可用和强一致性; 当集群节点数目逐渐增大为了支持更多的客户端,需要增加更多Server,然而Server增多,投票阶段延迟增大,影响性能。为了权衡伸缩性和高吞吐率,故引入Observer: Observer不参与投票; Observers接受客户端的连接,并将写请求转发给leader节点;
加入更多Observer节点,提高伸缩性,同时不影响吞吐率。

2.3 Zookeeper写流程:

在这里插入图片描述

2.4 Zookeeper数据模型:

在这里插入图片描述
组织结构:

zookeeper采用层次化的目录结构,命名符合常规文件系统规范;
每个目录在zookeeper中叫做znode,并且其有一个唯一的路径标识;

Znode:
  Znode可以包含数据和子znode(ephemeral类型的节点不能有子znode);
  Znode中的数据可以有多个版本,比如某一个znode下存有多个数据版本,那么查询这个路径下的数据需带上版本;
  客户端应用可以在znode上设置监视器(Watcher)
  znode不支持部分读写,而是一次性完整读写

Znode类型:
  Znode有两种类型,短暂的(ephemeral)和持久的(persistent);
  Znode的类型在创建时确定并且之后不能再修改;
  ephemeral znode的客户端会话结束时,zookeeper会将该ephemeral znode删除,ephemeralzn ode不可以有子节点;
  persistent znode不依赖于客户端会话,只有当客户端明确要删除该persistent znode时才会被删除;
  Znode有四种形式的目录节点,PERSISTENT、PERSISTENT_SEQUENTIAL、EPHEMERAL、PHEMERAL_SEQUENTIAL。

2.5 zookeeper提供简单的API

ZooKeeper的设计目标之一是提供一个非常简单的编程接口。因此,它仅支持以下操作:


create:在树中的某个位置创建一个节点

delete:删除节点

exists:测试某个位置是否存在节点

获取数据:从节点读取数据

设置数据:将数据写入节点

get children:检索节点的子节点列表

sync:等待传播数据
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这里插入图片描述

三、zookeeper集群

zookeeper集群部署如下:

server1:192.168.0.1
server2:192.168.0.2,
server3:192.168.0.3.

    1)下载zookeeper
    到http://zookeeper.apache.org/releases.html去下载最新版本Zookeeper-3.4.5的安装包zookeeper-3.4.5.tar.gz.将文件保存server1的~目录下
    2)安装zookeeper
    先在服务器分别执行a-c步骤
    a)解压  
    tar -zxvf zookeeper-3.4.5.tar.gz
    解压完成后在目录~下会发现多出一个目录zookeeper-3.4.5,重新命令为zookeeper
    b)配置
    cp zoo_sample.cfg zoo.cfg
    vi /opt/zookeeper/zoo.cfg
    #将conf/zoo_sample.cfg拷贝一份命名为zoo.cfg,也放在conf目录下。然后按照如下值修改其中的配置:

    # The number of milliseconds of each tick
    tickTime=2000  ##这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。用于客户端与服务器或者服务器与服务器之间维持心跳,也就是每个tickTime时间就会发送一次心跳。通过心跳不仅能够用来监听机器的工作状态,还可以通过心跳来控制Flower跟Leader的通信时间,默认情况下FL的会话时常是心跳间隔的两倍。
    # The number of ticks that the initial
    # synchronization phase can take
    initLimit=10  ##集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量),Zookeeper 接受(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。这个配置项是用来配置 当已经超过 5个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒;
    # The number of ticks that can pass between
    # sending a request and getting an acknowledgement
    syncLimit=5    ##标识 Leader 与Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是2*2000=4 秒;集群中flower服务器(F)跟leader(L)服务器之间的请求和答应最多能容忍的心跳数
    # the directory where the snapshot is stored.
    # do not use /tmp for storage, /tmp here is just
    # example sakes.
    dataDir=/home/wwb/zookeeper/data   ##是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。该属性对应的目录是用来存放myid信息跟一些版本,日志,跟服务器唯一的ID信息等。注意不要使用默认的/tmp来做存储快照的目录
    dataLogDir=/home/wwb/zookeeper/logs   
    ##dataDir,dataLogDir中的wwb是当前登录用户名,data,logs目录开始是不存在,需要使用mkdir命令创建相应的目录。并且在data 目录下创建文件myid文件,且serve1,server2,server3该文件内容分别为1,2,3。针对服务器server2,server3可以将server1复制到相应的目录,不过dataDir,dataLogDir目录下的文件myid内容分别为2,3
    # the port at which the clients will connect
    clientPort=2181   ##客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
    #
    # Be sure to read the maintenance section of the
    # administrator guide before turning on autopurge.
    #http://zookeeper.apache.org/doc/ ... html#sc_maintenance
    #
    # The number of snapshots to retain in dataDir
    #autopurge.snapRetainCount=3
    # Purge task interval in hours
    # Set to "0" to disable auto purge feature
    #autopurge.purgeInterval=1
    server.1=192.168.0.1:3888:4888   
    ##3888是服务器与集群中的 Leader 服务器交换信息的端口,4888表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
    server.2=192.168.0.2:3888:4888
    server.3=192.168.0.3:3888:4888
    ##如是单击多实例部署的伪集群方式,Zookeeper 各实例通信端口号不能一样
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

关于在各服务器上创建myid标识文件,在dataDir配置项指定的目录下创建myid文件,文件内容为当前节点在集群中的ID,在节点192.168.0.1上执行:

echo "1" > /home/wwb/zookeeper/data/myid
  • 1

在节点192.168.0.2上执行:

echo "2" > /home/wwb/zookeeper/data/myid
  • 1

在节点192.168.0.3上执行:

echo "3" > /home/wwb/zookeeper/data/myid
  • 1
  1. 依次启动server1,server2,server3的zookeeper

执行:/home/wwb/zookeeper/bin/zkServer.sh start,出现类似以下内容

   JMX enabled by default
    Using config: /home/wwb/zookeeper/bin/../conf/zoo.cfg
    Starting zookeeper ... STARTED
  • 1
  • 2
  • 3
  1. 测试zookeeper是否正常工作,在server1上执行以下命令

执行:/home/wwb/zookeeper/bin/zkCli.sh -server 192.168.0.2:2181,出现类似以下内容

    JLine support is enabled
    2013-11-27 19:59:40,560 - INFO      [main-SendThread(localhost.localdomain:2181):ClientCnxn$SendThread@736]- Session   establishmentcomplete on  localhost.localdomain/127.0.0.1:2181, sessionid =    0x1429cdb49220000, negotiatedtimeout = 30000
    WATCHER::
    WatchedEvent state:SyncConnected type:None path:null
    [zk: 127.0.0.1:2181(CONNECTED) 0] [root@localhostzookeeper2]#  
  • 1
  • 2
  • 3
  • 4
  • 5

如上述都正常,即代表zk集群构建成功了,如果出现错误那应该是第三步时没有启动好集群

5、验证

ps aux | grep zookeeper //查看是否有相应的进程, 没有话,说明集群启动出现问题,可以在每个服务器上尝试重启,执行:

 /home/wwb/zookeeper/bin/zkServer.sh stop
 /home/wwb/zookeeper/bin/zkServer.sh start
  • 1
  • 2

如果还是有问题,那么先stop再到bin的上级目录尝试执行

 /bin/zkServer.sh start
  • 1

注意:zookeeper集群启动运行时,zookeeper要求半数以上的机器可用,zookeeper才能提供服务。

/home/wwb/zookeeper/bin/zkServer.sh status
  • 1

注意:需要启动至少两个节点以后,通过上述命令查看时才能看到正常的状态。由于没有指定日志输出目录,默认会在zookeeper安装目录下的bin目录里生成日志文件,名为zookeeper.out

6、配置使用systemd启停ZooKeeper

创建并编辑/usr/lib/systemd/system/zkServer.service文件,文件内容如下:

[Unit]
Description=ZooKeeper Server
Documentation=https://zookeeper.apache.org/
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
User=zookeeper
Group=zookeeper
WorkingDirectory=/home/wwb/zookeeper
Environment=ZOO_LOG_DIR=/home/wwb/zookeeper/ogs
ExecStart=/home/wwb/zookeeper/bin/zkServer.sh start
ExecStop=/home/wwb/zookeeper/bin/zkServer.sh stop
Restart=on-failure
RestartSec=10s

[Install]
WantedBy=multi-user.target
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

配置简要说明:

Type: 这个配置项的值需要设置为“forking”,我一开始配置为“notify”,结果无法通过systemd启动。

User和Group: 指定启动zookeeper的用户和组,如果不指定,默认使用root用户启动。如果设置了用户和组,需要注意zookeeper相关目录和文件的权限问题,否则可能导致启动失败。

Environment: 定义环境变量,这里定义了环境变量“ZOO_LOG_DIR”,这个变量指定了zookeeper运行日志的输出目录。不指定也可以正常启动,配置了WorkingDirectory后,日志会生成在WorkingDirectory指定的目录下。

7、使用systemd启停zookeeper。

systemctl start zkServer   //启动
systemctl stop zkServer
systemctl enable zkServer.service
  • 1
  • 2
  • 3

注:zookeeper集群节点数推荐为奇数(2n+1)个,因为如果为偶数个节点,当有一半节点发生故障时,由于没有足够的节点数来选举新的leader节点(要求半数以上节点选举,不包含半数),会导致整个集群无法工作。如果只能部署两个节点,则不如使用单节点,因为两个节点的集群,只要任意一个节点发生故障,则集群无法工作。

8、客户端连接测试

在客户端电脑上,执行以下指令测试连接:

[hadoop@master ~]$ zkCli.sh -server server1:2181
#查看目录
[zk: slave1(CONNECTED) 0] ls /
  • 1
  • 2
  • 3

四、zk与kafka

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/593330
推荐阅读
相关标签
  

闽ICP备14008679号