zoukankan      html  css  js  c++  java
  • Zookeeper



    学习Dubbo需要用到注册中心,前来学习


    1. 概述

    ZooKeeper本身是分布式的,是一个为分布式应用提供协调服务的一个Apache项目,常用于注册中心

    底层基于观察者模式设计,主要负责存储和管理数据并且接收观察者的注册,数据更新时通知观察者


    1.1 特点

    • 可组成集群:一个Leader,多个Follower
    • 集群中半数以上节点存活,Zookeeper集群才能正常服务
    • 全局数据一致,集群每个数据内容都一致
    • 更新请求顺序进行:来自同一个Client的更新请求按其发送顺序依次执行
    • 数据更新原子性:集群集群都成功应用了某个事务
    • 实时性:一定时间范围内能读取到最新的数据,也是ZK突出的特点

    1.2 数据结构

    ZK的数据模型和Linux的文件系统类似,整体看成一棵树,每个节点称为ZNode。每一个ZNode默认可存储1MB的数据,每个ZNode通过其路径唯一标识,其主要用于协调服务,而不是存储数据


    1.2.1 节点类型分为:

    • 持久(Persistent)型,客户端和服务器断开连接,创建的节点不删除
    • 持久顺序型(Persistent_Sequential),在持久性基础上,名字中添加了序号
    • 短暂型(Ephemeral),客户端和服务器断开连接,创建的节点自己删除,并且只能做叶子节点,不能创建子节点
    • 短暂顺序型(Ephemeral_Sequential),同理


    1.2.2 节点数据分为:

    • stat :状态信息
    • data :节点存放的数据的具体内容
    [zk: 127.0.0.1:2181(CONNECTED) 0] get /dubbo
    
    # data 存放的数据
    192.168.XXX.XXX		
    
    # stat 格式化输出有下表内容
    
    node 状态信息 解释
    cZxid create ZXID,即该数据节点被创建时的事务 id
    ctime create time,即该节点的创建时间
    mZxid modified ZXID,即该节点最终一次更新时的事务 id
    mtime modified time,即该节点最后一次的更新时间
    pZxid 该节点的子节点列表最后一次修改时的事务 id,只有子节点列表变更才会更新 pZxid,子节点内容变更不会更新
    cversion 子节点版本号,当前节点的子节点每次变化时值增加 1
    dataVersion 数据节点内容版本号,节点创建时为 0,每更新一次节点内容(不管内容有无变化)该版本号的值增加 1
    aclVersion 节点的 ACL 版本号,表示该节点 ACL 信息变更次数
    ephemeralOwner 创建该临时节点的会话的 sessionId;如果当前节点为持久节点,则 ephemeralOwner=0
    dataLength 数据节点内容长度
    numChildren 当前节点的子节点个数

    ACLZooKeeper 采用 ACL(AccessControlLists)策略来进行权限控制,类似于 UNIX 文件系统的权限控制


    1.3 应用场景

    • 统一配置管理:将多个系统共用的配置文件放入ZooKeeper里监听变化即可
    • 统一命名管理:根据指定名字来获取资源或服务的地址
    • 统一集群管理:集群中保证数据一致性
    • 服务器节点动态上下线:
    • 负载均衡:
    • 分布式锁:数据更新的原子性使用version的乐观锁
    • 数据发布/订阅:watcher监听机制
    • 分布式协调/通知:采用了Watcher(事件监听器),即在特定节点上注册监听器,事件触发时通知客户端

    1.4 安装

    • 下载 安装包并解压
    • 修改conf里面的配置,并重命名为zoo.cfg
    # 修改数据的存放地址
    dataDir=../zkData
    
    • 启动ZK(zkServer:2181)
    • 启动ZK客户端(zkCli)

    客户端操作需要添加依赖 Curator


    1.5 身份认证

    • world:默认方式,所有用户都可无条件访问
    • auth:不使用任何 id,代表任何已认证的用户
    • digest:用户名:密码认证方式: username:password
    • ip:对指定 ip 进行限制




    2. 基本命令与使用

    命令比较简单,列出概要自己探索一下即可

    # 创建节点
    create [-e/-s] 节点 关联内容						create /howl 12346
    
    # 更新节点内容
    set 节点 关联内容									set /howl 11111
    
    # 查看某路径的子节点
    ls 节点路径										  ls /howl
    
    # 获取节点内容
    get [watch监听] 节点							  get /howl
    
    # 删除节点
    delete/rmr 节点                                  delete /howl
    
    # 退出客户端
    quit
    




    3. 底层原理


    3.1 选举机制

    其为半数机制,即集群中半数以上存活才有效。虽然配置文件中没有指定Master和Slave,但Leader是通过内部的选举机制临时产生的,其流程如下:

    假设5台服务器一个个依次启动:

    • 服务器1启动:给自己投票,然后发投票信息。由于没有通信对象,服务器1处于Looking(选举状态)
    • 服务器2启动:给自己投票,与之前启动的服务器1交换选举数据,服务器2编号大胜出,但投票数没有大于半数,所以两个服务器的状态依然是LOOKING
    • 服务器3启动:给自己投票,与之前启动的服务器1,2交换选举数据,服务器3的编号最大所以服务器3胜出,此时投票数大于半数,所以服务器3成为Leader,服务器1,2成为Slave
    • 服务器4启动:给自己投票,与之前启动的服务器1,2,3交换信息,虽然服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为Slave
    • 服务器5启动:同理服务器5成为Slave

    3.2 分布式部署

    • 解压安装Zookeeper到各个服务器(hadoop可以同步各个服务器??)
    • 配置每个服务器的编号(myid)
    # 在 /zkData 目录下创建一个myid文件
    touch myid
    
    # 往里面添加编号,一个数字即可
    1
    
    • 配置zoo.cfg文件
    #############Cluster###############
    server.2 = 127.0.0.1:22:22
    server.3 = 127.0.0.1:23:23
    server.4 = 127.0.0.1:24:24
    
    • 逐个启动

    3.3 监听器原理

    1. 首先要有一个main()线程
    2. 在main线程中创建Zookeeper客户端,内有两个线程,分别负责网络连接(Connect)和监听(Listener)
    3. Connect将需要监听的事件发给Zookeeper
    4. Zookeeper进行监听事件的注册
    5. 发生监听的事件,Zookeeper将消息发送给Listener
    6. Listener线程内部调用process()方法

    3.4 写数据流程

    • Client向Zookeeper的follower写数据,那么follower会将请求转发给Leader
    • Leader再将请求广播给每个follower,follower写成功后会通知Leader
    • Leader收到半数以上的写成功通知后会认为写数据成功,然后通知最初的follower
    • 最初的follower会进一步通知Client写数据成功

    3.5 Session

    客户端与ZooKeeper建立会话是用TCP长连接的,使用心跳检测来保持会话有效,这个连接可请求响应,以及接收监听事件。断开时长不超过sessionTimeout,那么重连后之前创建的会话有效


    3.6 分布式锁

    多个系统访问锁节点,那么每个系统都会在锁节点下创建一个带序号的临时节点

    序号最小的临时节点获取到锁,执行完操作则删除自身的临时节点

    其余临时节点监听序号比自己小1的节点


    3.7 集群

    最常见的集群就是主从复制了,采用Master选举方法。

    Master负责提供写服务、而其他Slave负责异步同步数据,提供读服务


    3.8 一致性问题CAP 和 算法

    • 2PC(二阶段提交)
    1. 协调者向参与者发送prepare,要参与者执行事务但不提交并记录undo,redo日志,执行后反馈给协调者
    2. 当所有参与者准备好后,协调者发送commit请求,即参与者全提交、所有参与者没有准备则进行rollback
    
    单点故障问题:协调者挂了
    阻塞问题:协调者发送prepare请求阻塞挂了,参与者占有资源不释放
    数据不一致:协调者发送了一部分commit就挂了
    
    • 3PC(三阶段提交)
    1. 向所有参与者发送CanCommit,查看是否都可以执行事务,是就进入预备状态
    2. 向所有参与者发送PreCommit,参与者执行事务不提交写日志响应结果。若收到一阶段NO或超时,会群发中断请求
    3. 在二阶段全部YES之后,群发DoCommit进行提交事务,并接收响应。若收到二阶段NO或超时,群发中断请求
    
    解决了阻塞问题,有超时机制
    
    • Paxos
    Paxos算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一
    
    1. 每个提案者提案时获取一个全局唯一性编号N,赋予提案
       每个表决者接受某提案后,将编号存到本地,以后仅接受大于本地编号的提案,最后将最大编号反馈给提案者
       
    2. 当提案者的提案超过半数表决者接受,那么此提案为真,群发此提案内容和编号
       表决这收到为真的提案,比较自己本地最大编号,大于则接受,小于则反馈NO
       
    有提案A被批准,提案B又批准,那么A编号小于B,重新提出编号+1的死循环
    解决思路:只有一个提案者
    


    参考:

    JavaGuide


  • 相关阅读:
    Ubuntu下安装、激活并配置Pycharm
    高分辨率下firefox字体和界面自动放大的问题
    Java如何根据IP获取当前定位
    WebSocket介绍和一个简单的聊天室
    java注解处理
    TCP/IP协议三次握手与四次握手流程解析
    mybatis如何做分页处理
    xshell学习笔记
    正交表生成工具 PICT 成对组合覆盖 收藏
    Ready api groovy script 参数化
  • 原文地址:https://www.cnblogs.com/Howlet/p/13837546.html
Copyright © 2011-2022 走看看