1. 首页
  2. Python

ZooKeeperPython

 
ZooKeeper是一个分布式的开源的分布式应用程序协调服务,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、命名服务、分布式同步、组服务等。
<font color="#FF0000">Z</font><font color="#F5000A">o</font><font color="#EB0014">o</font><font color="#E1001E">K</font><font color="#D70028">e</font><font color="#CD0032">e</font><font color="#C3003C">p</font><font color="#B90046">e</font><font color="#AF0050">r</font><font color="#A5005A">分</font><font color="#9B0064">布</font><font color="#91006E">式</font><font color="#870078">部</font><font color="#7D0082">署</font><font color="#73008C">及</font><font color="#690096">P</font><font color="#5F00A0">y</font><font color="#5500AA">t</font><font color="#4B00B4">h</font><font color="#4100BE">o</font><font color="#3700C8">n</font><font color="#2D00D2">连</font><font color="#2300DC">接</font><font color="#1900E6">管</font><font color="#0F00F0">理</font>

zookeeper的角色:
领导者(leader):负责进行投票的发起和决议,更新系统状态。
学习者(learner):包括跟随者(follower)和观察者(observer),follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票。Observer可以接受客户端连接,将写请求转发给leader,但observer不参与投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度。
客户端(client),请求发起方
<font color="#FF0000">Z</font><font color="#F5000A">o</font><font color="#EB0014">o</font><font color="#E1001E">K</font><font color="#D70028">e</font><font color="#CD0032">e</font><font color="#C3003C">p</font><font color="#B90046">e</font><font color="#AF0050">r</font><font color="#A5005A">分</font><font color="#9B0064">布</font><font color="#91006E">式</font><font color="#870078">部</font><font color="#7D0082">署</font><font color="#73008C">及</font><font color="#690096">P</font><font color="#5F00A0">y</font><font color="#5500AA">t</font><font color="#4B00B4">h</font><font color="#4100BE">o</font><font color="#3700C8">n</font><font color="#2D00D2">连</font><font color="#2300DC">接</font><font color="#1900E6">管</font><font color="#0F00F0">理</font>
 
zookeeper特性:
1最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。
2可靠性:具有简单、健壮、良好的性能,如果消息m被到一台服务器接受,那么它将被所有的服务器接受。
3实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
4等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。
5原子性:更新只能成功或者失败,没有中间状态。
6顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布;偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。
 
zookeeper的工作原理:
zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab(Zookeeper Atomic Broadcast)协议有两种模式,它们分 别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。
每个Server在工作过程中有三种状态:
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:leader已经选举出来,当前Server与之同步
 
zookeeper的读写机制:
zookeeper是由多个server组成的集群,一个leader,多个follower,每个server保存一份数据副本,全局数据一致,分布式读写,更新请求转发,由leader实施。
 
zookeeper的读写流程:
当Client向zookeeper发出读请求时,无论是Leader还是Follower,都直接返回查询结果。
zookeeper写入操作分为两种情况,
1、写入请求直接发送到leader节点
 Client向Leader发出写请求。Leader将数据写入到本节点,并将数据发送到所有的Follower节点,等待Follower节点返回,当Leader接收到一半以上节点(包含自己)返回写成功的信息之后,返回写入成功消息给client;
2、写入请求发送到Follower节点
Client向Follower发出写请求。Follower节点将请求转发给Leader,Leader将数据写入到本节点,并将数据发送到所有的Follower节点,等待Follower节点返回,当Leader接收到一半以上节点(包含自己)返回写成功的信息之后,返回写入成功消息给原来的Follower,原来的Follower返回写入成功消息给Client;

<font color="#FF0000">Z</font><font color="#F5000A">o</font><font color="#EB0014">o</font><font color="#E1001E">K</font><font color="#D70028">e</font><font color="#CD0032">e</font><font color="#C3003C">p</font><font color="#B90046">e</font><font color="#AF0050">r</font><font color="#A5005A">分</font><font color="#9B0064">布</font><font color="#91006E">式</font><font color="#870078">部</font><font color="#7D0082">署</font><font color="#73008C">及</font><font color="#690096">P</font><font color="#5F00A0">y</font><font color="#5500AA">t</font><font color="#4B00B4">h</font><font color="#4100BE">o</font><font color="#3700C8">n</font><font color="#2D00D2">连</font><font color="#2300DC">接</font><font color="#1900E6">管</font><font color="#0F00F0">理</font>

zookeeper的数据一致性:
数据更新原子性,一次数据更新要么所有节点成功,要么所有都失败,数据恢复到原来的样子。所以节点数据一致。在一定事件范围内,client总能读到最新数据。
 
zookeeper的节点类型:
zookeeper中的每个节点称为一个znode,每个znode维持一个数据结构。zookeeper中的数据是基于树形结构组织的。
znode有三种基本类型和两种组合类型:
Presistence znode 持久znode,当创建后会被持久化到存储中。若不特别指定,创建的znode默认为持久型。
Ephemeral znode − 临时znode,由客户端在连接时创建,当客户端断开之后,该znode将会被自动删除。同时,临时znode不允许有子节点。
Sequential znode − 序列znode,当节点被创建时,zookeeper会自动在节点后面添加数字后缀。
Presistence+Sequential znode,持久化顺序编号目录节点。
Ephemeral+Sequential znode,暂时化顺序编号目录节点。
zookeeper的leader选举:
半数通过机制。3台机器挂一台 2>3/2   ;  4台机器挂2台 2 !> 4/2
zookeeper集群一般是奇数,如3、5、7台等。如果有3个Server,则最多允许1个Server挂掉;如果有4个Server,则同样最多允许1个Server挂掉;3台服务器和4台服务器的的容灾能力是一样的,为了节省服务器资源,一般采用奇数个数作为服务器部署个数。
zookeeper选主流程:
当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的 Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。
fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和 zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。
zookeeper同步流程:
选完Leader以后,zk就进入状态同步过程
Leader等待server连接;Follower连接leader,将最大的zxid发送给leader; Leader根据follower的zxid确定同步点;完成同步后通知follower 已经成为uptodate状态;Follower收到uptodate消息后,又可以重新接受client的请求了。
 
zookeeper的应用场景:
数据发布与订阅:发布与订阅即所谓的配置管理,顾名思义就是将数据发布到zk节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。例如全局的配置信息,地址列表等就非常适合使用。
Name Service:这个主要是作为分布式命名服务,通过调用zk的create node api,能够很容易创建一个全局唯一的path,这个path就可以作为一个名称。
分布通知/协调:ZooKeeper 中特有watcher注册与异步通知机制,能够很好的实现分布式环境下不同系统之间的通知与协调,实现对数据变更的实时处理。
集群管理:集群机器监控:这通常用于那种对集群中机器状态,机器在线率有较高要求的场景,能够快速对集群中机器变化作出响应。Master选举则是zookeeper中最为经典的使用场景了。在分布式环境中,相同的业务应用分布在不同的机器上,有些业务逻辑,只需要让整个集群中的某一台机器进行执行,其余机器可以共享这个结果,这样可以大大减少重复劳动,提高性能。
通过Zookeeper来实现服务动态注册、机器上线与下线的动态感知,扩容方便,容错性好,且无中心化结构能够解决之前使用负载均衡设备所带来的单点故障问题。只有当配置信息更新时服务消费者才会去Zookeeper上获取最新的服务地址列表,其他时候使用本地缓存即可,这样服务消费者在服务信息没有变更时,几乎不依赖配置中心,能大大降低配置中心的压力。
 
分布式集群安装:
节点:172.20.10.5  172.20.10.6  172.20.10.8
环境:centos7 关闭firewalld selinux 每个节点都要安装java jdk
注意:从版本3.5.5开始,带有bin名称的包才是编译后的二进制的包,而tar.gz的包是源码的无法直接使用。
 
1、配置java jdk,编辑/etc/profile
export JAVA_HOME=/usr/local/jdk180171
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$PATH
source /etc/profile ;  java -version 查看版本信息
 
2、下载zookeeper安装包并解压
wget https://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.5.8/apache-zookeeper-3.5.8-bin.tar.gz
tar zxf apache-zookeeper-3.5.8-bin.tar.gz -C /usr/local/
cd /usr/local/ ; mv apache-zookeeper-3.5.8-bin/ zookeeper
 
3、修改配置文件
cd zookeeper/conf/ ; cp zoo_sample.cfg  zoo.cfg
mkdir -p /data/zk
vim zoo.cfg修改为如下:
tickTime=2000
initLimit=5
syncLimit=2
dataDir=/data/zk
clientPort=2181
server.1=172.20.10.8:2888:3888
server.2=172.20.10.5:2888:3888
server.3=172.20.10.6:2888:3888
 
4、拷贝zookeeper目录到其它两台节点
scp -r /usr/local/zookeeper/ root@172.20.10.5:/usr/local/
scp -r /usr/local/zookeeper/ root@172.20.10.6:/usr/local/
这两台机器都要mkdir -p /data/zk
 
5、分别在3个节点对应的dataDir中建立myid文件,里面输入服务器标识号
echo 1 > /data/zk/myid       #172.20.10.8
echo 2 > /data/zk/myid       #172.20.10.5
echo 3 > /data/zk/myid       #172.20.10.6
 
6、运行服务
可以在前台启动zk服务,观察启动日志
cd /usr/local/zookeeper/  ; bin/zkServer.sh start-foreground
/usr/local/zookeeper/bin/zkServer.sh status
没问题再在后台启动
cd /usr/local/zookeeper/  ;  bin/zkServer.sh start
cd /usr/local/zookeeper/ ; bin/zkServer.sh status
启动后查看端口、jps -l查看进程等
 
bin/zkServer.sh status    #查看Mode状态,3台可以看到1台leader,两台follower
测试集群的高可用性:
stop停掉Mode是leader的zk服务,查看另外两个节点的状态,有一个节点选举为leader;
再启动停掉的这个zk服务节点,查看Mode已经是follower。
 
7、配置环境变量
vim /etc/profile
export ZOOKEEPER_HOME=/usr/local/zookeeper
export PATH=$ZOOKEEPER_HOME/bin:$PATH
source /etc/profile
加载环境变量后就可以任意目录位置直接使用zookeeper的相关命令了。
 
8、使用zkCli.sh客户端连接zookeeper服务
可以直接使用zkCli.sh连接本机zk服务。
也可连接指定zookeeper集群中任意ip和2181端口的zk服务,如zkCli.sh -server 172.20.10.6:2181
连接zk服务后进行基础操作:
通过help命令可以可看zk下的所有命令和使用方法。
ls /     #查看所有节点目录
create命令用以创建节点,-s参数表示创建顺序节点,-e参数表示创建临时节点,无参数默认创建持久节点。
create -s /tt 000     #创建顺序节点,数据为000 ,是在节点名后面增加10位数字,数字是递增的
get /tt0000000000   #获取根下节点数据,可以加s参数,查看更多信息
create -e /tt-tmp 111   #创建临时节点,数据为111
create -s -e /temp 555 #创建临时有序节点
create /tt-pre  222     #创建持久化节点,数据为222
create /tt-pre/wz 666   #创建一个子节点
set /tt-pre 333 #set更改节点数据为333
delete /tt0000000001    #删除一个节点数据
#delete 用以删除节点,若该节点有子节点会无法删除,即不能递归删除节点。rmr命令可递归删除节点。
#集群节点间数据是同步一致的,任意节点的数据操作在集群节点间具有一致性和原子性。
 
##########zoo.cfg配置文件说明:#############
tickTime: 基本事件单元,用来指示一个心跳的时长。以毫秒为单位。
initLimit: 集群中Follower服务器初始化连接leader服务器时容忍的最长时间间隔,超时则连接失败。参数tickTime为2000毫秒,则连接超时时长为5*2000=10秒
syncLimit: Follower和Leader服务器之间发送消息以及请求/应答时所能等待的最多心跳数。2*2000=4秒
dataDir: Zookeeper存储数据的目录
clientPort:客户端的通信端口
server.id=host:port1:port2:server.x是每一个server的myid。 host是能够解析的主机名或者节点ip。port1是follower和leader之间的通信端口。port2选举用的端口。
 
Python连接和操作Zookeeper
1、安装kazoo
pip install kazoo
 
2、连接zk
可通过KazooClient模块连接zookeeper,支持多个host,默认端口2181可写可不写。
from kazoo.client import KazooClient
zk = KazooClient(hosts=’172.20.10.6:2181′)
zk.start()
print(zk)         —>  <kazoo.client.KazooClient object at 0x000001F56236F8D0>
 
3、创建节点
在KazooClient模块源码中可以看到:
def create(self, path, value=b””, acl=None, ephemeral=False,sequence=False, makepath=False, include_data=False):
参数含义分别是:
path 节点路径
value 节点对应的值,值的类型是bytes
ephemeral 若为True则建立一个临时节点,session断开后自动删除该节点
sequence 若为True则建议一个有序节点,和zookeeper服务中性质一样
makepath 若为False父节点不存在时抛NoNodeError。若为True父节点不存在时创建父节点。
执行如下代码:
from kazoo.client import KazooClient
zk = KazooClient(hosts=’172.20.10.6:2181′)
zk.start()
node_path = ‘/test/tt’
#创建节点,makepath置为True表示当父节点不存在则创建父节点,再创建子节点
zk.create(node_path, b’test value’, makepath=True)
 
4、查看节点
KazooClient模块提供 get_children() 和 get() 方法获取 子节点 和 节点对应的值。
from kazoo.client import KazooClient
zk = KazooClient(hosts=’172.20.10.6:2181′)
zk.start()
parent_path = ‘/test’
node_path = ‘/test/tt’
node = zk.get_children(parent_path)  #填写父目录,查找其下所有子节点
value = zk.get(node_path)            #获取一个节点的值
print(node, value)  —> [‘tt’] (b’test value’, ZnodeStat(czxid=21474836526, mzxid=21474836526…)
 
5、更改节点,使用set()方法
from kazoo.client import KazooClient
zk = KazooClient(hosts=’172.20.10.6:2181′)
zk.start()
node_path = ‘/test/tt’
zk.set(node_path, b’changed value’)
value = zk.get(node_path)            
print(value)       —> (b’changed value’, ZnodeStat(czxid=21474836526,mzxid=21474836544,…)
 
6、删除节点,使用delete()方法
from kazoo.client import KazooClient
zk = KazooClient(hosts=’172.20.10.6:2181′)
zk.start()
node_path = ‘/test/tt’
parent_path = ‘/test’
zk.delete(node_path,recursive=False)  
value = zk.get_children(parent_path)  #删除tt节点后再查看test下是否有节点
print(value)         —>  []        #打印为空,说明tt节点已经被删除
参数 recursive:置为False,当删除的节点存在子节点,会抛NotEmptyError;
若为True,则删除此节点及其该节点下的所有子节点。
 
7、watchers事件
ZooKeeper 允许客户端向服务端注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。
使用KazooClient下的DataWatch类,同时也是装饰器,它可以对指定节点进行事件监视,监视节点的每一次数据更新;可以监视不存在的节点,当这个不存在的节点发生变化时,其数据一样会被监视到;代码示例:
@client.DataWatch(‘/path/to/watch’)
def my_func(data, stat):
print(“Data is %s” % data)
print(“Version is %s” % stat.version)
# Above function is called immediately and prints
# Or if you want the event object
@client.DataWatch(‘/path/to/watch’)
def my_func(data, stat, event):
print(“Data is %s” % data)
print(“Version is %s” % stat.version)
print(“Event is %s” % event)
@客户端.DataWatch(’/path/to/watch’)
def my_func(数据,状态):
打印(“数据是%s”%Data)
打印(“版本为%s”%统计版本)
#立即调用上述函数并打印
#或者你想要事件对象
@客户端.DataWatch(’/path/to/watch’)
def my_func(数据、状态、事件):
打印(“数据是%s”%Data)
打印(“版本为%s”%统计版本)
打印(“事件为%s”%Event)
 
执行以下操作进行数据监视:
from kazoo.client import KazooClient
zk = KazooClient(hosts=’172.20.10.6:2181′)
zk.start()
node_path = ‘/test/tt’
@zk.DataWatch(node_path)
def mywatch(data, stat):    #可以加event
    print(data)
    print(stat)
    print(‘-‘ * 10)
zk.create(node_path,b’555′,makepath=True)
zk.set(node_path,b’666′)
zk.set(node_path,b’777′)  
zk.stop()
—> 打印输出结果如右,执行的3个操作都有记录
None
None
———-
b’555′
ZnodeStat(czxid=21474836564, mzxid=21474836564, version=0, dataLength=3, … pzxid=21474836564)
———-
b’666′
ZnodeStat(czxid=21474836564, mzxid=21474836565, version=1, dataLength=3, … pzxid=21474836564)
———-
b’777′
ZnodeStat(czxid=21474836564, mzxid=21474836566, version=2, dataLength=3, … pzxid=21474836564)
———-
#stat参数有很多,其中有一个参数是version,使用stat.version方法的时候,监视的客户端的节点必须存在,否则会报错AttributeError,空对象没有stat属性。
#可以在mywatch监视函数中加上evnet事件属性,可以监视事件的type、state、path。
 

原创文章,作者:wz,如若转载,请注明出处:https://www.wzstyle.cn/903.html

发表评论

邮箱地址不会被公开。 必填项已用*标注