zookeeper官网:http://zookeeper.apache.org/
下载:https://zookeeper.apache.org/releases.html#download
学习:https://zookeeper.apache.org/doc/current/zookeeperOver.html
zk的leader也是会挂的,导致服务不可用,但事实是zookeeper集群及其高可用,通过快速恢复出一个leader。zookeeper集群有两种运行状态:可用状态和不可用状态(leader挂掉了),不可用状态恢复到可用状态应该越快越好。
ZooKeeper:分布式应用程序的分布式协调服务
ZooKeeper是用于分布式应用程序的分布式,开放源代码协调服务。它公开了一组简单的原语,分布式应用程序可以基于这些原语来实现用于同步,配置维护以及组和命名的更高级别的服务。它的设计易于编程,并使用了按照文件系统熟悉的目录树结构样式设置的数据模型。它以Java运行,并且具有Java和C的绑定。
众所周知,协调服务很难做到。它们特别容易出现诸如比赛条件和死锁之类的错误。ZooKeeper背后的动机是减轻分布式应用程序从头开始实施协调服务的责任。(比如redis的分布式锁)
不可用状态->可用状态:
设计目标
ZooKeeper很简单。ZooKeeper允许分布式进程通过共享的分层名称空间相互协调,该命名空间的组织方式类似于标准文件系统。名称空间由数据寄存器(在ZooKeeper看来,称为znode)组成,它们类似于文件和目录。与设计用于存储的典型文件系统不同,ZooKeeper数据保留在内存中,这意味着ZooKeeper可以实现高吞吐量和低延迟数。
ZooKeeper实施对高性能,高可用性,严格有序访问加以重视。ZooKeeper的性能方面意味着它可以在大型的分布式系统中使用。可靠性方面使它不会成为单点故障。严格的排序意味着可以在客户端上实现复杂的同步原语。
ZooKeeper是有序的。ZooKeeper用一个反映所有ZooKeeper事务顺序的数字标记每个更新。后续操作可以使用该命令来实现更高级别的抽象,例如同步原语。
ZooKeeper很快。在“读取为主”的工作负载中,它特别快。ZooKeeper应用程序可在数千台计算机上运行,并且在读取比写入更常见的情况下,其性能最佳,比率约为10:1。
zookeeper是一个树级目录:
数据模型和分层名称空间
ZooKeeper提供的名称空间与标准文件系统的名称空间非常相似。名称是由斜杠(/)分隔的一系列路径元素。ZooKeeper命名空间中的每个节点都由路径标识。
zookeeper的保证:
zookeeper实操:
在linux安装好java,
用wget获得下载zookeeper-3.4.6.tar.gz,
#tar xf zookeeper-3.4.6.tar.gz
#mkdir /opt/mashibing
#mv zookeeper-3.4.6 /opt/mashibing
#cd /opt/mashibing/zookeeper-3.4.6(bin/conf)
#ll(有zkserver.sh,zkcli.sh)
#cd conf
#cp zoo_sample.cfg zoo.cfg(zk启动默认加载的文件名是zoo.cfg)
#ll
#vi zoo.cfg
tickTime=2000:leader和follower之间心跳的时间
initLimit=10:follower与leader建立连接时,leader允许等待follower2s*10
syncLimit=10:同步,2s*5,leader下达数据同步,follower有10s没给回馈,认为有问题
dataDir=/var/mashibing/zk:存放zk的日志,快照等数据文件
clientPort=2181:client连接server的端口号
maxClientCnxns=60:客户端最大连接数
----zk要在配置文件下面新开一行,写下如下内容----
server.1=node01:2888:3888(zk没有redis的发布订阅,要人为地把zk集群都有谁给写进来)
server.2=node02:2888:3888
server.3=node03:2888:3888
server.4=node04:2888:3888
(写下这些结点之后,行数/2+1=过半数)
(端口号:2888/3888,在选出leader前(没有leader时),通过3888端口建立通信选出leader,选完leader后,leader起一个2888,leader与follower的通信在2888)
(把id最大的选为leader,有3台机器(过半)投票就可以选leader了,要么3,要么4)
#mkdir -p /var/mashibing/zk
#cd /var/mashibing/zk(持久化的数据在这个目录出现)
#vi myid
1(server.1就是node01,有四台机器,四个node,每台机子写自己的)
#cd /opt
#scp -r ./mashibing/ node02:'pwd'(scp:linux发起远程的拷贝,拷贝当前路径下mashibing这个目录到node02的当前目录下)
#scp -r ./mashibing/ node03:'pwd'
#scp -r ./mashibing/ node04:'pwd'
在node02里头:
#cd /opt/mashibing/zookeeper-3.4.6
#ll(内容是相同的,同一个集群的不同node)
#mkdir -p /var/mashibing/zk
#echo 2 > /var/mashibing/zk/myid(输出2重定向到/var/mashibing/zk的myid这个文件中去)
#cat /var/mashibing/zk/myid
在node03里头:
#mkdir -p /var/mashibing/zk
#echo 3 > /var/mashibing/zk/myid
在node04里头:
#mkdir -p /var/mashibing/zk
#echo 4 > /var/mashibing/zk/myid
它的命令想在任何地方使用,必须把执行目录pass到环境变量里:
vi /etc/profile
export ZOOKEEPER_HOME=/opt/mashibing/zookeeper-3.4.6
export PATH=$PATH:$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin
#. /etc/profile(.重新加载配置文件到内存)
#zk (按tab就可以发现指令)
#scp /etc/profile node02:/etc(分发)
#scp /etc/profile node03:/etc
#scp /etc/profile node04:/etc
#source /etc/profile
-----------下面启动zookeeper-----------
->zkserver.sh help
可以看到{start|start-foreground|stop|restart|status|upgrade|print-cmd}
->zkserver.sh start-foreground(前台启动,zk在前台阻塞,日志在前台打印)
node01:
->zkServer.sh start-foreground
node02:
->zkServer.sh start-foreground
node03:
->zkServer.sh start-foreground
node04:
->zkServer.sh start-foreground
只要起3个,已经可以过半投票了,投出一个leader。边启动机器,边看各个node日志的变化可以看出很多东西。
在node04
->zkCli.sh
->help(打印出所有可以用的命令)
->ls /(显示根目录)
->create /ooxx(根目录下创建ooxx目录,但是没有数据,但没报错,没有数据就不能创建成功)
->create /ooxx ""(创建ooxx成功,cZxid:0x2000000002)
->create /ooxx/xxoo ""(cZxid: 0x2000000003)
->ls /ooxx
->get /ooxx(看ooxx的数据)
->set /ooxx "hello"(mZxid: 0x2000000004)
->get /ooxx
"hello"(只能放1M,并且它是二进制安全的,外面的客户端给什么字节数组就存什么)
一些逻辑的信息:
cZxid = 0x2000000002(c:创建,Zxid:事务id。一共有64位,后32位是事务递增序列,前32位表示leader的纪元,即你是第几个leader)
mZxid = 0x2000000004(修改的事务id)
pZxid = 0x2000000003(当前节点下,创建的最后的那个节点的id号)
ephemeralOwner = 0x0(0x0:表示当前节点没有归属者,创建时没有带选项,即它是持久节点)
->create [-s] [-e] path data acl (-e:就是表示创建一个ephemeral临时节点)
->zkCli.sh(可以看到日志,一个客户端连接时会创建一个session ID:0x46d3a399275002)
->create -e /xoxo "asdasd"
->get /xoxo
可见ephemeralOwner是0x46d3a399275002,归属于当前sesstion
->
在node02,
#zkCli.sh
->ls /
[zookeeper, ooxx, xoxo] (可见不同的node之间统一视图,持久节点ooxx和临时节点xoxo都能看到,不仅节点统一视图,session都会统一视图)
->get /xoxo
能看到他归属于0x46d3a399275002,当0x46d3a399275002这个session quit之后,
->ls /
[zookeeper, ooxx]
->
在node04上:
->create /xoox ""
->get /xoox
cZxid = 0x200000010
在node02上,客户端连接:
#zkCli.sh
->
在node04上:
->create /oxxo "asdasd"
->get /oxxo
cZxid = 0x200000012(node02只是连接了一下客户端,看似并没有做任何事务,但是cZxid相差了2,其实在连node02的时候会有一个session id,走leader把id 写给所有人的内存)
以上实验说明:临时节点是和session绑定的,且session是需要消耗一个事务id的。
在node04上:
->create /abc ""
->ls /
->create -s /abc/xxx "asdasd"(加入有很多客户端,他们都想在abc目录下存数据,可能会存在覆盖错误,如何规避错误,使用-s,序列的意思,会在创建的文件夹后面自动拼一个序列,形成分布式id)
->rmr /abc/xxx0000000000 (删了这个节点)
->rmr /abc/xxx0000000001 (删了这个节点)
->create -s /abc/xxx ""
/abc/xxx0000000002
HA是大数据,拿zookeeper去选主,选出哪个是active,哪个是standby
在node01上:
#netstat -natp | egrep '(2888|3888)'(egrep是开启正则表达式,可以看到node01上关于2888跟3888所有的信息z)
3888的连接如下图所示: