zookeeper

作者: husky_1 | 来源:发表于2022-01-20 22:17 被阅读0次

    1 概述:

    1.开源的,分布式的,为分布式服务提供协调服务的Apache 项目。
    2.基于观察者模式设计的分布式服务管理框架, 负责存储和管理数据,接受观察者的注册, 一旦数据状态变化, 将通知已经注册的观察者做出反应

    2 特点

    1. Zookeeper 由一个领导者(leader, 有且只有一个), 多个跟随者(follower)组成的集群
    2. 集群中只有半数以上的节点存活,Zookeeper集群才能正常服务,所以zookeeper 适合安装奇数台服务器
    3. 全局数据一致性:每个存活的节点保存一份相同的数据副本, client无论链接到哪个节点,数据都是一致的
    4. 更新请求顺序执行, 来自同一个client的更新请求按其发送的顺序依次执行
    5. 数据更新原子性,一次数据更新要么成功,要么失败
    6. 实时性: 在一定时间范围内,client能读取到最新的数据

    3 节点

    zookeeper的数据模型和结构与unix文件系统类似, 整体可以看作是一棵树,每个节点称作为ZNode, 每个ZNode 默认能存储1MB的数据, 每个ZNode都可以通过其路径唯一标识

    数据结构
    3.1 节点类型:

    节点可分为持久节点,临时节点,持久顺序节点,临时顺序节点

    • 持久节点(PERSISTENT):
      客户端和服务器断开链接后,创建的节点不会被删除
    • 持久顺序节点(PERSISTENT_SEQUENTIAL):
      客户端和服务器断开链接后,创建的节点不会被删除, 而且对该节点进行顺序编号
    • 临时节点(EPHEMERAL):
      客户端和服务器断开链接后,创建的节点会被删除
    • 临时顺序节点(EPHEMERAL_SEQUENTIAL):
      对该节点进行顺序编号,客户端和服务器断开链接后,创建的节点会被删除
    3.2 节点信息

    例:创建一个值为test持久节点 /abcd

    [zk: localhost:2181(CONNECTED) 28] create /abcd "test"
    Created /abcd
    

    查看/abcd 节点信息

    [zk: localhost:2181(CONNECTED) 29] get -s /abcd
    test.     
    cZxid = 0x10000000b
    ctime = Thu Feb 10 20:12:28 CST 2022
    mZxid = 0x10000000b
    mtime = Thu Feb 10 20:12:28 CST 2022
    pZxid = 0x10000000b
    cversion = 0
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 4
    numChildren = 0
    
    名称 含义
    test 对应节点的值
    cZxid 创建节点的事务id
    ctime 创建节点的时间(ms), 从1970开始
    mZxid 节点最后更新的事务id
    mtime 节点最后更新的时间(ms),从1970开始
    pZxid 节点对应子节点事务ID
    cversion 节点对应子节点的版本号,子节点的变化数
    dataVersion 节点数据版本号
    aclVersion 节点权限版本号
    ephemeralOwner 判断是否是临时节点,如果不是,则为0 ,如果是则为对应的sessionId
    dataLength 节点数据长度
    numChildren 节点对应的子节点数
    3.3 节点监听(watch)

    使用watcher机制实现了数据的发布订阅功能功能,当订阅的对象发生变化时会异步通知客户端

    1. watch 特性
    特性 说明
    一次性触发 watcher 是一次性触发的,一旦被触发就会被移除,再次使用时需要重新注册
    客户端顺序回调 watcher 回调是顺序串行化执行的,只有回调后客户端才能看到最新的数据状态,一个watcher回调逻辑不应该太多,以免影响别的watcher执行
    轻量级 watchEvent 是最小的通信单元,结构上只包含通知状态,事件类型和节点路径,并不会告诉数据节点前后变化的具体内容
    实效性 watcher只有在当前的session彻底失效才会无效,若session有效期间内快速重新连接成功,则watcher依然有效,仍可收到通知
    1. watchEvent
      当数据有变化时,服务端会返回对应的watchEvent对象给客户端, 该对象中包括了通知的状态(keepState)和事件的类型(eventType)
      -. 通知状态(keepState)
      客户端和服务端连接状态发生变化时的对应通知类型
    属性 说明
    SyncConnected 客户端与服务器正常连接
    Disconnected 客户端与服务器断开连接时
    Expired 回话session失效时
    AuthFailed 身份认证失效时

    -. 事件类型(eventType)
    节点(znode)发生变化时对应的通知类型,EventType变化时keepState都会处于SyncConnected的通知状态下;当keepState发生变化时,EventType永远为None

    类型属性 说明
    None
    NodeCreated Watcher监听的数据节点被创建
    NodeDeleted Watcher监听的数据节点被删除
    NodeDataChanged Watcher监听的数据节点内容发生变更时(不论内容数据是否变化)
    NodeChildrenChanged Watcher监听节点的子节点列表发生变化

    注:客户端接收到的相关事件通知中只包含状态及类型等信息,不包括数据节点变化前后的具体内容,变化后的数据需要调用get等方法重新获取

    1. 捕获相应的事件
      在zookeeper 中采用zk.getChildren(path,watch), zk.exists(path,watch), zk.getData(path,watch)方式为某个节点注册监听
    注册方式 Created ChildrenChanged Changed Deleted
    zk.getChildren(path,watch) 可监控 可监控
    zk.exists(path,watch) 可监控 可监控 可监控
    zk.getData(path,watch) 可监控 可监控
    3.4 节点权限(ACL)

    ACL:Access Control List 访问控制列表
    使用 scheme:id:perm 来标识,主要涵盖 3 个方面:
      权限模式(Scheme):授权的策略
      授权对象(ID):授权的对象
      权限(Permission):授予的权限

    其特性如下:
      -.ZooKeeper的权限控制是基于每个znode节点的,需要对每个节点设置权限
      -.每个znode支持设置多种权限控制方案和多个权限
      -.子节点不会继承父节点的权限,客户端无权访问某节点,但可能可以访问它的子节点

    3.4.1 权限模式

    scheme 采用何种方式授权

    1. world:默认方式,相当于全部都能访问
    2. auth:代表已经认证通过的用户(cli中可以通过addauth digest
      user:pwd 来添加当前上下文中的授权用户)
    3. digest:即用户名:密码这种方式认证,这也是业务系统中最常用的。 用 username:password 字符串来产生一个MD5串,然后该串被用来作为ACL ID。认证是通过明文发送username:password 来进行的,当用在ACL时,表达式为username:base64 ,base64是password的SHA1摘要的编码。
    4. ip:使用客户端的主机IP作为ACL ID 。这个ACL表达式的格式为addr/bits ,此时addr中的有效位与客户端addr中的有效位进行比对。
    5. super: 在这种scheme情况下,对应的id拥有超级权限,可以做任何事情(cdrwa)
    3.4.2 授权对象
    授权模式 授权对象
    world 只有一个用户:anyone, 代表登陆zookeeper的所有人(默认)
    ip 通常是一个ip地址或者段,例如:192.169.19.22 或者 192.169.19.1/24
    auth 使用已添加的认证的用户认证 username:password
    digest 与auth类似,只不过password需要加密处理,username:BASE64(SHA-1(username:password))
    super 与digest一致
    3.4.3 授予的权限

    CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、删、改、查、管理权限,这5种权限简写为crwda

    注意:这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限

    更详细的如下:

    权限 缩写 含义
    CREATE c 可以创建子节点
    DELETE d 可以删除子节点(仅下一级节点)
    READ r 可以读取节点数据及显示子节点列表
    WRITE w 可以设置节点数据
    ADMIN a 可以设置节点访问控制列表权限

    4 选举机制

    首先了解如下几个概念:

    1. SID: 服务器id,用来表示集群中该机器,每台机器不能重复,与myid一致
    2. ZXID:事物id ,用来标识一次服务器状态的变更,在某一时刻,集群中的每一台服务器的ZXID不一定相同
    3. Epoch:每个leader任期的代号,没有leader时,同一轮投票选举逻辑时钟是一致的,每投完一轮,这个数据就会增加
    4.1 初次启动选举机制

    假设有5台服务器组成的的zookeeper集群,server ID为1~5,同时他们是最新启动的,且没有历史数据,在存放数据量上面是一样的


    WX20220210-154003@2x.png

    此时依次按顺序启动服务,
    1.服务器1 启动,此时没有leader节点,服务器1 发起选举投票,并投给自己,此时投票不超过半数(3票),选举失败,此时服务1处于looking状态,

    1. 服务器2 启动,此时再次发起leader选举,服务器1和2 分别投票给自己,并互相交换选举结果,此时服务器1 发现自己的myid小于服务器2的,并且都没有历史数据,服务器1就会更改投票给服务器2,此时服务器2 有2 票,服务器1 有0票,都没有超过半数投票,选举失败,服务器1 和2 都处于looking状态
    2. 服务器3 启动,如果服务器2 启动时一样,再次选举,由于服务器3的myid最大,最终服务器3 有3 票,满足超过半数投票,服务器3 就选举为leader节点,服务器1,2为follower几点,集群启动成功
    3. 服务器4 启动,leader节点已经存在,此时服务器4 成为follwer节点
    4. 服务器5 启动,和服务器4一样,也成为follower节点
    4.2 非第一次启动选举
    image.png

    当集群中的一台服务器出现以下情况时,此时会进入选举机制

    1. 服务器初始化启动
    2. 服务器运行期间和leader节点丢失通信

    当一台机器开始选举时,会出现如下几种情形之一:
    1.集群中已经有leader了,此时该机器发起选举时,会被告知leader节点信息,此时该机器只要和leader节点建立连接并完成同步就行

    1. 集群中leader节点挂了,
      假设 5台服务器的sid为1,2,3,4,5, ZXID为8,8,8,7,7。
      此时服务器3(leader)和服务器5(follower)挂了,此时剩下的1,2,4 服务器重新开始选举.

    选举规则: Epoch大的直接胜出, Epoch相同,ZXID大的胜出,Epoch和ZXID都相同的,服务器id大的胜出

    由于1,2,4的Epoch 相同, 但是2的ZXID,serverID 相对于最大,此时服务器2 就被选举为新的leader

    5 安装(Ver 3.5.7)

    5.1 配置参数解读:

    参数名 含义
    clientPort 客户端连接server的端口,即对外服务端口,一般设置为2181
    dataDir 存储快照文件snapshot的目录。默认情况下,事务日志也会存储在这里。建议同时配置参数dataLogDir, 事务日志的写性能直接影响zk性能
    tickTime ZK中的一个时间单元。ZK中所有时间都是以这个时间单元为基础,进行整数倍配置的。例如,session的最小超时时间是2*tickTime
    dataLogDir 事务日志输出目录。尽量给事务日志的输出配置单独的磁盘或是挂载点,这将极大的提升ZK性能
    globalOutstandingLimit 最大请求堆积数。默认是1000。ZK运行的时候, 尽管server已经没有空闲来处理更多的客户端请求了,但是还是允许客户端将请求提交到服务器上来,以提高吞吐性能。当然,为了防止Server内存溢出,这个请求堆积数还是需要限制下的
    preAllocSize 预先开辟磁盘空间,用于后续写入事务日志。默认是64M,每个事务日志大小就是64M。如果ZK的快照频率较大的话,建议适当减小这个参数
    snapCount 每进行snapCount次事务日志输出后,触发一次快照(snapshot), 此时,ZK会生成一个snapshot.文件,同时创建一个新的事务日志文件log.。默认是100000.(真正的代码实现中,会进行一定的随机数处理,以避免所有服务器在同一时间进行快照而影响性能)
    traceFile 用于记录所有请求的log,一般调试过程中可以使用,但是生产环境不建议使用,会严重影响性能
    maxClientCnxns 单个客户端与单台服务器之间的连接数的限制,是ip级别的,默认是60,如果设置为0,那么表明不作任何限制。请注意这个限制的使用范围,仅仅是单台客户端机器与单台ZK服务器之间的连接数限制,不是针对指定客户端IP,也不是ZK集群的连接数限制,也不是单台ZK对所有客户端的连接数限制。指定客户端IP的限制策略,这里有一个patch,可以尝试一下:[http://rdc.taobao.com/team/jm/archives/1334](http://rdc.taobao.com/team/jm/archives/1334
    clientPortAddress 对于多网卡的机器,可以为每个IP指定不同的监听端口。默认情况是所有IP都监听 clientPort 指定的端口
    minSessionTimeoutmaxSessionTimeout 事务日志输出时,如果调用fsync方法超过指定的超时时间,那么会在日志中输出警告信息。默认是1000ms
    fsync.warningthresholdms 用于记录所有请求的log,一般调试过程中可以使用,但是生产环境不建议使用,会严重影响性能
    autopurge.purgeInterval 在上文中已经提到,3.4.0及之后版本,ZK提供了自动清理事务日志和快照文件的功能,这个参数指定了清理频率,单位是小时,需要配置一个1或更大的整数,默认是0,表示不开启自动清理功能
    autopurge.snapRetainCount 这个参数和上面的参数搭配使用,这个参数指定了需要保留的文件数目。默认是保留3个
    electionAlg 在之前的版本中, 这个参数配置是允许我们选择leader选举算法,但是由于在以后的版本中,只会留下一种“TCP-based version of fast leader election”算法,所以这个参数目前看来没有用了,这里也不详细展开说了
    initLimit Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许F在 initLimit 时间内完成这个工作。通常情况下,我们不用太在意这个参数的设置。如果ZK集群的数据量确实很大了,F在启动的时候,从Leader上同步数据的时间也会相应变长,因此在这种情况下,有必要适当调大这个参数了
    syncLimit 在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态。如果L发出心跳包在syncLimit之后,还没有从F那里收到响应,那么就认为这个F已经不在线了。注意:不要把这个参数设置得过大,否则可能会掩盖一些问题
    leaderServes 默认情况下,Leader是会接受客户端连接,并提供正常的读写服务。但是,如果你想让Leader专注于集群中机器的协调,那么可以将这个参数设置为no,这样一来,会大大提高写操作的性能
    server.x=[hostname]:nnnnn[:nnnnn] 这里的x是一个数字,与myid文件中的id是一致的。右边可以配置两个端口,第一个端口用于F和L之间的数据同步和其它通信,第二个端口用于Leader选举过程中投票通信。
    group.x=nnnnn[:nnnnn]weight.x=nnnnn 对机器分组和权重设置,可以 参见这里
    cnxTimeout Leader选举过程中,打开一次连接的超时时间,默认是5s
    zookeeper.DigestAuthenticationProvider.superDigest ZK权限设置相关,具体参见 使用super **身份对有权限的节点进行操作 **》 ZooKeeper **权限控制 **》
    skipACL 对所有客户端请求都不作ACL检查。如果之前节点上设置有权限限制,一旦服务器上打开这个开头,那么也将失效
    forceSync 这个参数确定了是否需要在事务日志提交的时候调用 [FileChannel ](http://rdc.taobao.com/team/%5C/java%5C/jdk1.6.0_22%5C/jre%5C/lib%5C/rt.jar%3Cjava.nio.channels(FileChannel.class%E2%98%83FileChannel).force来保证数据完全同步到磁盘
    jute.maxbuffer 每个节点最大数据量,是默认是1M。这个限制必须在server和client端都进行设置才会生效
    5.2. 单机节点
    1. 解压安装包
    tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz
    
    1. 修改配置文件
      将 解压后文件夹下的conf 路径下的zoo_sample.cfg 改为zoo.cfg,
      设置配置文件中参数 dataDir
      配置文件:
    # 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
    syncLimit=5
    # the directory where the snapshot is stored.
    # do not use /tmp for storage, /tmp here is just 
    # example sakes.
    dataDir=/root/zookeeper/apache-zookeeper-3.5.7-bin/data
    # the port at which the clients will connect
    clientPort=2181 
    # the maximum number of client connections.
    # increase this if you need to handle more clients
    #maxClientCnxns=60
    
    1. 启动
      在解压文件的bin目录中
    [root@iZuf6g3hri8hvnuqng6id7Z bin]  ./zkServer.sh --config ../conf start
    /usr/bin/java
    ZooKeeper JMX enabled by default
    Using config: ../conf/zoo.cfg
    Starting zookeeper ... 、STARTED
    
    
    1. 停止
    [root@iZuf6g3hri8hvnuqng6id7Z bin]  ./zkServer.sh stop
    /usr/bin/java
    ZooKeeper JMX enabled by default
    Using config: /root/zookeeper/apache-zookeeper-3.5.7-bin/bin/../conf/zoo.cfg
    Stopping zookeeper ... STOPPED
    
    
    1. 查看状态
    [root@iZuf6g3hri8hvnuqng6id7Z bin]# ./zkServer.sh  status
    /usr/bin/java
    ZooKeeper JMX enabled by default
    Using config: /root/zookeeper/apache-zookeeper-3.5.7-bin/bin/../conf/zoo.cfg
    Client port found: 2181. Client address: localhost.
    Mode: standalone
    
    
    5.3. 集群

    示例: 在三个服务器上部署三个zookeeper节点,组成集群

    1. 解压安装:
      和单机节点安装一样,在三台服务器上分别解压设置dataDir目录
    2. 配置服务器编号
      在参数dataDir 目录下创建myid文件, 此文件说明当前zookeeper在集群中的唯一编号,在文件中填写对应server的编号(例如1,2,3)
    3. 配置集群文件
      在每个节点的配置文件中添加集群的信息
    # server.A=B:C:D
    #A: serverId 与myid文件的编号对应
    #B:服务器地址
    #C:follower 与leader 通信的端口
    #D:leader节点挂了之后,重新选举时的端口号
    server.1=139.196.58.234:2888:3888
    server.2=139.196.58.235:2888:3888
    server.3=139.196.58.236:2888:3888
    
    1. 分别启动zookeeper 节点

    6 客户端操作

    6.1 常用节点操作
    语法 含义
    ls path 查看当前节点的子节点。-w 监听子节点变化, -s 附加次级信息
    create path 创建节点 -e 创建临时节点, -s 创建顺序节点
    get path 获得节点对应的值 -w 监听节点内容变化 -s 附加次级信息
    set path value 设置节点具体值
    state path 查看节点状态
    delete path 删除节点
    deleteall path 递归删除节点
    6.2 权限操作
    1. 获取节点权限
      客户端操作指令:getAcl path
    #创建一个/abcd节点, 观察节点的权限,此时默认是world:anyone:cdrwa 的权限
    [zk: localhost:2181(CONNECTED) 4] create /abcd "test"
    Created /abcd
    [zk: localhost:2181(CONNECTED) 5] getAcl  /abcd
    'world,'anyone
    : cdrwa
    
    1. 设置节点权限
      指令 setAcl path acl
    #world 权限设置 setAcl path world:anyone:<perm>
    #设置/abcd 节点没有创建子节点的权限,此时就不能创建子节点了
    [zk: localhost:2181(CONNECTED) 6] setAcl /abcd world:anyone:drwa
    [zk: localhost:2181(CONNECTED) 8] getAcl  /abcd
    'world,'anyone
    : drwa
    [zk: localhost:2181(CONNECTED) 7] create /abcd/a "a"
    Authentication is not valid : /abcd/a
    
    #ip 权限设置 setAcl path ip:<ip>:<perm>
    [zk: localhost:2181(CONNECTED) 9] setAcl /abcd ip:127.0.0.1:cdrwa
    [zk: localhost:2181(CONNECTED) 10] getAcl  /abcd
    'ip,'127.0.0.1
    : cdrwa
    # 此时/abcd 节点的cdrwa 权限只能是ip为127.0.0.1的客户端才拥有
    # 可同时支持设置多个ip地址的权限, 以逗号分隔
    [zk: localhost:2181(CONNECTED) 11] setAcl /abcd ip:127.0.0.1:cdrwa,ip:192.162.12.11:cdrwa
    [zk: localhost:2181(CONNECTED) 12] getAcl  /abcd
    'ip,'127.0.0.1
    : cdrwa
    'ip,'192.162.12.11
    : cdrwa
    
    
    
    
    1. 添加认证用户
      指令 addauth digest <auth>
    #添加 用户名为gagaya 密码为123456的认证用户
    [zk: localhost:2181(CONNECTED) 0] addauth digest gagaya:123456
    # auth授权模式, 需要现通过addauth 添加认证用户(登陆)
    [zk: localhost:2181(CONNECTED) 1] setAcl /abcd auth:gagaya:cdrwa 
    [zk: localhost:2181(CONNECTED) 2] getAcl /abcd
    'digest,'gagaya:MiCKcSLnJ5sLUpkr1wj81iMhnKQ=
    : cdrwa
    
    #digest 授权模式,
    #setAcl  path digest username:password(加密处理):<perm>,
    # 在Linux中可用以下指令获取加密密码 
    #echo -n <username>:<password> | openssl dgst -binary -sha1 |openssl base64 
    [root@iZuf6g3hri8hvnuqng6id7Z ~]# echo -n gagaya:123456 | openssl dgst -binary -sha1 |openssl base64
    MiCKcSLnJ5sLUpkr1wj81iMhnKQ=
    
    # 使用digest授权模式相比于auth 模式需要提供用户密码的加密密钥
    [zk: localhost:2181(CONNECTED) 7] setAcl /abcd digest:gagaya:MiCKcSLnJ5sLUpkr1wj81iMhnKQ=:cdrwa 
    [zk: localhost:2181(CONNECTED) 8] getAcl /abcd
    'digest,'gagaya:MiCKcSLnJ5sLUpkr1wj81iMhnKQ=
    : cdrwa
    
    1. 多种授权模式
      同一个节点可以设置多种授权的模式
    # 用逗号分隔
    [zk: localhost:2181(CONNECTED) 11] setAcl /abcd digest:gagaya:MiCKcSLnJ5sLUpkr1wj81iMhnKQ=:cdrwa,ip:127.0.0.1:cdrwa 
    [zk: localhost:2181(CONNECTED) 12] getAcl /abcd
    'digest,'gagaya:MiCKcSLnJ5sLUpkr1wj81iMhnKQ=
    : cdrwa
    'ip,'127.0.0.1
    : cdrwa
    
    
    1. 超级管理员(super)
      超级管理员,可以访问任何权限的节点,只能在启动服务器的时候添加。
      假设这个超管是:super:admin
      先获取加密后的密码:
    [root@iZuf6g3hri8hvnuqng6id7Z ~]# echo -n super:admin | openssl dgst -binary -sha1 |openssl base64
    xQJmxLMiHGwaqBvst5y6rkB6HQs=
    

    打开zk目录下的/bin/zkServer.sh服务器脚本文件,找到如下一行:

    nohup $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}"
    

    这就是脚本中启动zk的命令,默认只有以上两个配置项,我们需要加一个超管的配置项

    "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="
    

    那么修改以后这条完整命令变成了:

    nohup $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="\
        -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
    

    之后启动zk集群, 然后在客户端链接集群后,添加对应的超级用户,此时客户端就是超级管理员了

    addauth digest super:admin
    
    7. 共识协议

    7 应用场景

    提供的服务包括:统一命名服务, 统一配置管理,通知集群管理等,服务节点动态上下线,软负载均衡等

    4.1 统一命名服务
    4.2 统一配置管理

    相关文章

      网友评论

          本文标题:zookeeper

          本文链接:https://www.haomeiwen.com/subject/fdeshrtx.html