zookeeper的原理以及安装、配置

产生背景

问题:如果一个集群中有100个节点,如何实现数据的一致性?
这里先介绍一下一致性的概念:
一致性分为:强一致性、弱一致性和最终一致性

  • 强一致性
    特点:写入什么 就读到什么
    例如:从任意一个节点写入数据,其他节点读取到写入后的数据。如果集群中只有一个节点, 一致性是最强的。集群中节点个数越多 强一致性越难保证。
  • 弱一致性
    特点:写入什么,尽量保证读到什么
    不保证最终读取的结果一定对的
  • 最终一致性
    弱一致性的特殊情况
    允许一定的时间延迟的
zookeeper是什么?

zookeeper 就是做分布式一致性的。分布式情况下,多个节点的一致性(数据、状态等一致性)。

zookeeper来源:
paxos   过半选举
zookeeper 是paxos算法的最完美的实现

分布式算法  演变:
	CAP 
		c:强一致性  一个节点
		a:高可用性   节点越多可用性越高
		p:机架策略  
		实验环境下
	base:
		c-- 最终一致性   a :基本可用
zookeeper的安装:

安装版本:
3.4.10
安装准备:
jdk1.8
安装节点:
最好是奇数台 至少3台 3-11
安装步骤:

  • 1)上传
  • 2)解压
    tar -xvzf zookeeper-3.4.10.tar.gz
  • 3)配置环境变量
    export ZOO_HOME=/home/jacob/app/zookeeper-3.4.10
    export PATH= P A T H : PATH: PATH:ZOO_HOME/bin
    在这里插入图片描述
    重新加载配置文件
    source /etc/profile
    在这里插入图片描述
  • 4)修改zookeeper配置文件
    cd /home/jacob/app/zookeeper-3.4.10/conf
    在这里插入图片描述
    首先将配置文件的名字修改为 zoo.cfg
    mv zoo_sample.cfg zoo.cfg
    在这里插入图片描述
#The number of milliseconds of each tick  每次心跳的时间间隔
tickTime=2000
#The number of ticks that the initial 
#synchronization phase can take    初始化阶段的心跳次数
initLimit=10
#The number of ticks that can pass between 
#sending a request and getting an acknowledgement  发送请求  接受响应 5次心跳
syncLimit=5
#the directory where the snapshot is stored. 快照存储目录(核心文件,选主快照。)
#zookeeper的核心文件存储目录  快照目录:存储每一个节点的id 
#do not use /tmp for storage, /tmp here is just 
#example sakes.
dataDir=/home/jacob/data/zookeeperdata
#the port at which the clients will connect 客户端连接zookeeper的端口
clientPort=2181
#the maximum number of client connections.
#increase this if you need to handle more clients
#maxClientCnxns=60
#绑定节点  和 id 
#server.id = 主机名:2888:3888  一行一个节点
server.1=hadoop01:2888:3888
server.2=hadoop02:2888:3888
server.3=hadoop03:2888:3888

在这里插入图片描述
zk中每一个节点都会有一个id, int型的数字,数值区间为: 0~255,便于投票使用。
同一个集群中 不同节点的id 不可重复

hadoop01 1
hadoop02 2
hadoop03 3

  • 5)添加id文件
    /home/jacob/data/zookeeperdata (此下创建文件名myid的文件)
    myid存储当前节点的id
    myid 不要有多余的空格 也不要有多余的换行符

  • 6)远程发送zk的安装包 其他节点
    scp -r zookeeper-3.4.10 hadoop02:/home/jacob/app/
    scp -r zookeeper-3.4.10 hadoop03:/home/jacob/app/

    sudo scp /etc/profile hadoop02:/etc/
    sudo scp /etc/profile hadoop03:/etc/
    分别在对应的机器上加载配置文件:
    source /etc/profile

  • 7)到hadoop02 hadoop03 创建 myid文件

先创建目录
mkdir -p /home/jacob/data/zookeeperdata/
再创建myid文件
vim myid

  • 8)启动
    注意:启动之前一定保证防火墙关闭的,时间是同步的
    sudo ntpdate ntp1.aliyun.com
    在这里插入图片描述
    在这里插入图片描述
    三个节点都要执行
    启动hadoop01

    zkServer.sh start
    出现:21698 QuorumPeerMain zookeeper的进程
    有这个进程 不代表启动成功
    验证启动成功 zk的状态
    zkServer.sh status
    有可能会出现: Error contacting service. It is probably not running. 的错误。不过不要着急,出现这种情况,也可能是zookeeper集群启动不到一半导致的,忽略它,继续启动其它节点(机器)。

启动hadoop02

zkServer.sh start
查看zk状态:zkServer.sh status
Mode: leader
hadoop01的mode为:follower

启动hadoop03

zkServer.sh start
查看zk状态:zkServer.sh status
Mode: follower

问题1
查看zookeeper.out文件发现有错误:

2019-09-22 20:13:47,005 [myid:3] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:ServerCnxn@318] - The list of known
 four letter word commands is : [{1936881266=srvr, 1937006964=stat, 2003003491=wchc, 1685417328=dump, 1668445044=crst,
1936880500=srst, 1701738089=envi, 1668247142=conf, 2003003507=wchs, 2003003504=wchp, 1668247155=cons, 1835955314=mntr,
1769173615=isro, 1920298859=ruok, 1735683435=gtmk, 1937010027=stmk}]
2019-09-22 20:13:47,006 [myid:3] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:ServerCnxn@319] - The list of enabl
ed four letter word commands is : [[wchs, stat, stmk, conf, ruok, mntr, srvr, envi, srst, isro, dump, gtmk, crst, cons]
]
2019-09-22 20:13:47,006 [myid:3] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@883] - Processing srv
r command from /127.0.0.1:53802
2019-09-22 20:13:47,019 [myid:3] - INFO  [Thread-1:NIOServerCnxn@1044] - Closed socket connection for client /127.0.0.1
:53802 (no session established for client)
2019-09-22 20:40:21,300 [myid:3] - WARN  [RecvWorker:2:QuorumCnxManager$RecvWorker@1028] - Connection broken for id 2,
my id = 3, error =
java.io.EOFException
        at java.io.DataInputStream.readInt(DataInputStream.java:392)
        at org.apache.zookeeper.server.quorum.QuorumCnxManager$RecvWorker.run(QuorumCnxManager.java:1013)
2019-09-22 20:40:21,304 [myid:3] - WARN  [RecvWorker:2:QuorumCnxManager$RecvWorker@1031] - Interrupting SendWorker

提示Connection refused的异常,其实一开始先不急着百度这个问题,其实要所有节点上都启动zookeeper后再看看运行状态,现在查看运行状态都是没运行的,也找不到相应的进程:
在这里插入图片描述
不要着急,到其他节点服务器上都启动zookeeper,过一会儿后每个服务器查看状态:
在这里插入图片描述
如果有Mode和QuorumPeerMain,就说明已经启动成功了。
如果要关闭zookeeper,需要在每个节点上执行:
在这里插入图片描述
问题2
当zookeeper在集群启动不到一半的时候,会报如下的错误
Error contacting service. It is probably not running.
在这里插入图片描述
碰到这个错误暂时不要着急,不用理它,因为启动机器的数量不过半,无法进行选举,所以才出现这样的错误。继续启动其它机器,之后就会正常了。

启动顺序和投票机制:

启动顺序 和 myid 有关

  • 启动顺序如果是:
    先启动 hadoop01—1
    再启动 hadoop02—2
    最后启动 hadoop03—3
  • 1)hadoop01启动,找集群中的leader,发现没有leader,发起选主,但是集群中只有一个节点 他自己, 这个时候hadoop01 就将选票投给自己,这时候hadoop01获取1票(总数3票),没有过半,选主失败,这个时候hadoop01的状态 无状态(It is probably not running)
  • 2)hadoop02启动,找集群中的leader,发现没有leader,发起选主,集群中有hadoop01–1 hadoop02—2,每个节点开始投票,zk内部规定id小的节点强制将自己的票投给id大的。
    hadoop01投票给–>id=2
    hadoop02投票给–>id=2
    id=2(hadoop02)获取两票,已经过半了,hadoop02就是选举的leader,hadoop01 就主动的将自己的状态切为follower.
  • 3)hadoop03启动,找集群leader,发现集群中已经有leader,主动将自己的状态切为follower。
  • 所以最终结果是:hadoop01是follower,hadoop02是leader,hadoop03是follower

批量启动和关闭
一台一台服务器去执行命令有点麻烦,写一个脚本批量执行:

#!/bin/bash
#下面变量修改zookeeper安装目录
zooHome=/opt/zookeeper
if  [ $1 != ""  ]
    then
        confFile=$ZOOHOME/conf/zoo.cfg
        slaves=$(cat "$confFile" | sed '/^server/!d;s/^.*=//;s/:.*$//g;/^$/d')
        for salve in $slaves ; do
            ssh $salve "$ZOOHOME/bin/zkServer.sh $1"
        done
    else
        echo "parameter empty! parameter:start|stop"
fi

将上面脚本保存为zooManager文件,调用执行:

sh zooManager start
sh zooManager stop

zookeeper的原理:

zookeeper中的角色:

  • leader :
    发起提议
    接受客户端的读写请求,主要处理写请求
    具有选举权 和 被选举权
    时刻具备最新数据
  • follower
    接受客户端的读写请求,读请求可以自己处理。如果接受到客户端的写请求,将写请求转发给leader。
    具备选举权 和 被选举权
  • observer
    配置: server.4=hadoop04:2888:3888:observer
    不具备选举权 和被选举权
    作用:分担集群的读数据的压力,接收到写请求,转发leader。
    实际应用中,读写比例可能为: 95:5

整个写入数据过程中, leader最先写入, follower|observer 从leader进行数据同步。
如果follower|observer 数据更新过程中, leader宕机了, 则重新选主。

详解stat信息:

cZxid = 0x200000075
ctime = Mon Aug 05 23:52:15 CST 2019 节点创建时间
mZxid = 0x200000075
mtime = Mon Aug 05 23:52:15 CST 2019 节点修改时间
pZxid = 0x20000007e
cversion = 6 创建版本
dataVersion = 0 数据版本
aclVersion = 0 权限版本
ephemeralOwner = 0x0 节点的生命周期标识
永久节点 0x0
ephemeralOwner = 0x16c5d8f0a950009 临时节点
sessionid = 0x16c5d8f0a950009
dataLength = 0 数据长度
numChildren = 6 子节点个数

数据版本id,数据版本越大,数据越新,全局的
cZxid 创建节点事件id : 创建节点 id+1
mZxid 修改节点事件id : 修改节点内容,id+1
pZxid 子节点变化的事件id :创建一个节点的子节点的时候,发生变化。

cZxid mZxid pZxid 整体无论修改了哪一个 , 都会全局顺序递增
上面的3个id 共同标识整个集群中的这个机器的数据更新程度,如果zxid 最大,这个机器中的数据最新的。

非全新集群的选主
集群运行一段时间之后,如果leader宕机,则集群重新选主。
依据:
	1)myid 
	2)zxid 
	3)逻辑时钟  投票的轮数

选举规则:
1)先根据逻辑时钟,如果逻辑时钟不统一,先统一逻辑时钟。
2)统一完成逻辑时钟之后,按照zxid进行选择,  zxid大的胜出。
3)在zxid大的里面选myid, myid大的胜出
最终选的leader,数据版本是最新的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值