分布式协调服务-zookeeper

1.分布式架构的优点:提高系统的性能和吞吐量
2.分布式环境的特点
分布性:任意节点可以分布在不同的服务器上,服务器可以在不同的城市
并发性:程序运行过程中,并发性操作是很常见的。比如同一个分布式系统中的多个节点,同时访问一个共享资源。数据库、分布式存储
无序性:进程之间的消息通信,会出现顺序不一致问题

3.分布式环境下面临的问题
网络通信:网络本身的不可靠性,因此会涉及到一些网络通信问题
网络分区(脑裂):当网络发生异常导致分布式系统中部分节点之间的网络延时不断增大,最终导致组成分布式架构的所有节点,只有部分节点能够正常通信
三态:在分布式架构里面,除了成功、失败、超时
分布式事务:ACID(原子性、一致性、隔离性、持久性)
Zookeeper(1) - 图2
注意:分布式事务就是一个节点对数据库的操作不成功,那么另外一个节点需要跟着回滚。
zookeeper能做什么:分布式数据一致性的解决方案
数据的发布/订阅(配置中心:disconf) 、负载均衡(dubbo利用了zookeeper机制实现负载均衡) 、命名服务、
master选举(kafka、hadoop、hbase)、分布式队列、分布式锁

Zookeeper能够解决的问题:
1. 协议地址的维护:就是保存url地址,记住多有服务的地址
2. 负载均衡:就是将请求分发到不同的集群中的节点上
3. 服务动态上下线感知:单点故障的时候进行剔除,分发到可用节点上

在zookeeper中当某个节点出现故障会及时感知到

1. 注册中心的实现:
Zookeeper采用的是push和pull相结合的方式,客户端向服务器端注册自己关注的服务节点,一旦节点数据发生变化,那么服务器端就会向客户端发送一个warth事件通知。客户端收到通知后,主动到服务器端更新数据。
Zookeeper(1) - 图3
2. 负载均衡:
Zookeeper(1) - 图4
3. 分布式锁:

zookeeper的特性

Zookeeper(1) - 图5
顺序一致性:保证了分布式的无序性,使其有顺序执行
从同一个客户端发起的事务请求,最终会严格按照顺序被应用到zookeeper中
原子性
所有的事务请求的处理结果在整个集群中的所有机器上的应用情况是一致的,也就是说,要么整个集群中的所有机器都成功应用了某一事务、
要么全都不应用
可靠性
一旦服务器成功应用了某一个事务数据,并且对客户端做了响应,那么这个数据在整个集群中一定是同步并且保留下来的

实时性
一旦一个事务被成功应用,客户端就能够立即从服务器端读取到事务变更后的最新数据状态;(zookeeper仅仅保证在一定时间内,近实时)

Zookeeper的实现原理:

Zookeeper的安装:默认的端口号是2181
1. 下载zookeeper的安装包
2. 将zookeeper解压放置在某个目录下(一般是/usr/local/zookeeper)
3. 然后进入到解压目录的conf目录下:
Zookeeper(1) - 图6
4. 然后将里面的zoo_sample.cfg文件复制一份,并且重命名为zoo.cfg(在启动的时候默认寻找的默认路径下的配置文件名就是zoo.cfg,而不是zoo_sample.cfg):cp xxx xxx
5. 然后进入到zoo.cfg配置文件里面去
Zookeeper(1) - 图7
6. 在安装目录里面有一个bin目录,里面全是shell脚本:
如果想要执行脚本,那么我们就进入到bin目录下使用命令执行脚本:sh ZkServer.sh xxxxx
Zookeeper(1) - 图8
在bin目录下执行:
一:想要启动zookeeper:sh zkServer.sh start (如果启动失败就去查看zookeeper.out文件)
:cat /usr/local/zookeeper/bin/zookeeper.out
想要关闭zookeeper:./zkServer.sh stop

注意:这里如果是单机应该是没有问题的,如果在zoo.cfg里面配置了集群的各个节点路径,那么就需要在/tmp/zookeeper/路径下创建一个data文件夹,再创建一个文件myid,里面的内容就是标志该节点在集群中的标识符

二:连接客户端:sh zkCli.sh -server ip:port(前提是安装好jdk)
在linux系统中缺少java命令:安装jdk
1.通过CRT上传linux版本的jdk,然后解压到相应目录下:/usr/local/java
在/usr/local目录下创建java目录:mkdir java
在~目录下解压jdk到java目录下:tar -zxf 压缩文件名 -C 目标目录

2.配置java的环境变量:vim /etc/profile(如果vim命令不存在就在在线安装一下:yum install vim )
export JAVA_HOME=/usr/local/java/jdk1.7.0_80
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JRE_HOME=$JAVA_HOME/jre

注意:配置好保存退出后执行命令使配置文件生效:source /etc/profile

客户端连接出现下面的页面表示安装成功。
Zookeeper(1) - 图9


集群环境的搭建:
集群中有三个角色:leader,follower,observer
Leader:接受所有follower提案请求并统一协调发起提案的投票,负责与所有的follower进行内部的数据交换(同步)
Follower:直接为客户端服务并参与提案的投票,同时与leader进行数据交换(同步)
Observer:直接为客户端服务但并不参与提案的投票,同时与leader进行数据交换(同步)

observer
observer 是一种特殊的zookeeper节点。可以帮助解决zookeeper的扩展性(如果大量客户端访问我们zookeeper集群,需要增加zookeeper集群机器数量。从而增加zookeeper集群的性能。 导致zookeeper写性能下降, zookeeper的数据变更需要半数以上服务器投票通过。造成网络消耗增加投票成本)
1.observer不参与投票。 只接收投票结果。
2.不属于zookeeper的关键部位。
在zoo.cfg里面增加
peerType=observer

搭建详细步骤:
1. 在每个zookeeper的zoo.cfg配置配件中添加节点信息(格式如下:)

server.1=192.168.32.128:2888:3181:observer
server.2=192.168.32.131:2888:3181
server.3=192.168.32.132:2888:3181
server.4=192.168.32.133:2888:3181

2888端口号是随便取的,只要和服务器中的服务端口不重复就行了:表示follower节点和leader节点通信的端口号
3181:是辅助型端口号:表示leader选举的端口号:如果leader节点挂掉需要一个端口去重新选举。

2.在zoo.cfg的配置文件里面配置的dataDir的路径下创建文件夹data,再在里面创建一个文本,里面的内容就是该zookeeper节点的id号(1~255范围)

注解:如果客户端的访问量突然增加(主要针对读操作),那么为了不影响性能,那么势必需要水平扩展集群中的机器,这样一来就会增加写的同步操作,从而增加网络消耗。导致写的性能下降。为了避免写性能的下降,那么可以增加机器,但是设置为observer角色,那么能够很好的解决这些问题。

Zookeeper(1) - 图10



四台服务器同时工作:
1. 在四台服务器上面同时安装好zookeeper服务。
2. 修改配置文件zoo.cfg(复制并重命名而得到),格式是
server.id=host:port:port
Id的取值范围是1~255,:用来标识在该集群中的机器号。
2181:是zookeeper的默认端口号。
3. 创建myid文件:在zoo.cfg配置文件的dataDir目录下创建这个文件。默认的路径是/tmp/zookeeper。在里面创建文件:vim myid。里面就一行内容,就是上面的id号。
4. 启动每一个zookeeper服务,启动后会在bin目录下生成一个zookeeper.out的日志文件。如果需要查看日志文件:tail (zookeeper.out)文件名

注意:1.这里可以在bin目录下使用sh zkServer.sh status来检查服务是否启动成功,出现node:folower之类的字样表示成功
2.检查各个节点的状态,需要开启所有节点的服务。

Zoo.cfg配置文件讲解:
Zookeeper(1) - 图11
tickTime=2000 zookeeper中最小的时间单位长度 (ms)
initLimit=10 follower节点启动后与leader节点完成数据同步的时间
syncLimit=5 leader节点和follower节点进行心跳检测的最大延时时间
dataDir=/tmp/zookeeper 表示zookeeper服务器存储快照文件的目录
dataLogDir 表示配置 zookeeper事务日志的存储路径,默认指定在dataDir目录下
clientPort 表示客户端和服务端建立连接的端口号: 2181

zookeeper中的一些概念

客户端的知识点:

数据模型

zookeeper的数据模型和文件系统类似,每一个节点称为:znode. 是zookeeper中的最小数据单元。每一个znode上都可以
保存数据和挂载子节点。 从而构成一个层次化的树形结构
节点特性
持久化节点 : 节点创建后会一直存在zookeeper服务器上,直到主动删除
持久化有序节点 :每个节点都会为它的一级子节点维护一个顺序
临时节点 : 临时节点的生命周期和客户端的会话保持一致。当客户端会话失效,该节点自动清理
临时有序节点 : 在临时节点上多勒一个顺序性特性

注意:临时节点下面不能挂载节点:


Zookeeper(1) - 图12

会话状态:

  1. 未连接
    2. 连接中
    3. 已连接
    4. 中断/关闭

    zookeeper的命令操作

    通过客户端访问成功之后:help查看命令集合

    1. create [-s] [-e] path data acl:创建节点

    -s 表示节点是否有序
    -e 表示是否为临时节点
    data:表示数据
    acl:不管
    默认情况下,是持久化节点

    2.ls /:查看某个路径下节点,并默认进入到该路径里面去

    2. get path [watch]

    获得指定 path的信息

    3.set path data [version]

    修改path节点对应的data
    4.删除节点:delete path:删除节点必须从最下面一层开始删除。
    乐观锁的概念
    数据库里面有一个 version 字段去控制数据行的版本号

    4.delete path [version]

    删除节点

    Zookeeper(1) - 图13
    Zookeeper(1) - 图14

    stat信息

    cversion = 0 子节点的版本号
    aclVersion = 0 表示acl的版本号,修改节点权限
    dataVersion = 1 表示的是当前节点数据的版本号

    czxid 节点被创建时的事务ID
    mzxid 节点最后一次被更新的事务ID
    pzxid 当前节点下的子节点最后一次被修改时的事务ID

    ctime = Sat Aug 05 20:48:26 CST 2017 创建时间
    mtime = Sat Aug 05 20:48:50 CST 2017 修改时间




    cZxid = 0x500000015
    ctime = Sat Aug 05 20:48:26 CST 2017
    mZxid = 0x500000016
    mtime = Sat Aug 05 20:48:50 CST 2017
    pZxid = 0x500000015
    cversion = 0
    dataVersion = 1
    aclVersion = 0
    ephemeralOwner = 0x0 创建临时节点的时候,会有一个sessionId 。 该值存储的就是这个sessionid
    dataLength = 3 数据值长度
    numChildren = 0 子节点数


    ——-这里不用看
    Java api的使用:
    Zookeeper(1) - 图15

    1.连接zookeeper
    Zookeeper(1) - 图16

    2.创建节点:
    Zookeeper(1) - 图17
    3.修改节点:
    Zookeeper(1) - 图18
    4.删除节点:
    Zookeeper(1) - 图19
    5. 获取节点下的子节点:
    Zookeeper(1) - 图20

    Zookeeper(1) - 图21

    ——-上面不用看



    Zookeeper的客户端的使用:建议使用curator
    Zookeeper(1) - 图22