Zookeeper学习笔记(中)

Zookeeper的基本原理和基本实现

深入了解ZK的基本原理

ZK的一致性:

  • ZAB 协议: Zookeeper 原子消息广播协议

      ZK通过选举保证 leader 的高可用, 
    
      三个阶段:
    * 发现:选举 leader
    * 同步:Follower 或者 Observer 从 leader 中同步最新数据
    * 广播: 服务器角色:
    * Leader:领导者, 所有更新操作通过 leader 进行
    * Follower:跟随者, 有投票权, leader挂了之后有权作为竞选者
    * Observer:只能读取数据, 没有投票权, 不能参与竞选 leader 服务器状态:
    * LOOKING
    * FOLLOWING
    * OBSERVING
    * LEADING 集群通讯: id大的向小的发起连接
  • Leader的选举

      选举算法:
    通过FastLeaderElection, tcp协议
    触发时机:
    1) 集群启动
    2) Leader宕机
    成为leader的因素 : zxid 和 myid 思考: 有3个全新节点组成一个集群,依次启动1,2,3, 哪个节点会成为 leader ? 选举过程:
    1) 每个节点状态为 LOOKING
    2) 每一个server发出一个投自己的投票(myid+zxid)
    3) 处理投票:将收到投票和自己投票相比(比较zxid,比较myid),有些节点修改投票,再次发送
    比较zxid的意义:过半数即认为OK, 只要半数中的机器有一个在新的选举中, 即它会成为新leader将数据同步给其他人
    4) 统计投票, 确定
    5) 修改服务器状态
  • 各个节点数据的同步:

      leader选举之后, leader同其他节点进行同步,同步完成, leader才真正变为leader
    leader同超过一半follower同步结束才OK
    follower选举完成后尝试连接leader,带上自己最大的 zxid, 来确定数据同步的过程 * 同步算法(DIFF): 适用于 follower 的最大事务id, 在 min , max 之间
    1. 发送同步请求
    2. 发送同步数据
    3. 一旦过半follower完成同步,leader发送信号结束同步流程,即可以对外服务 * 同步算法(TUNC): 适用于 leader 宕机, 恢复后作为 follower 加入, 其上有已经 proposal 的新事务, 其id > max
    宕机之后如果 TRUNC 之后, 新集群已经有数据修改, 则需要通过 DIFF 将新修改发送给加入节点
    简单说明步骤:
    1) 新节点加入后收到 trunc 命令, 将只存在于新节点上的数据回滚
    2) 确定是否新leader有新的提交,如有进行DIFF, 完成整个过程 * 同步算法(SNAP):全量
    适合宕机多时后恢复, 其id < min , 集群的事务日志文件已经有更新多个了 * 获取同步后的数据 读取前条用 sync 方法进行数据同步, 确保数据为最新
  • 以下为我在思考ZK选举原理过程中产生的一些问题, 有些还未完全获取到正确答案, 暂时提供出来供大家一起讨论

      1. zxid在一个主周期中是否肯定一致连续?

    2. 无 leader 的状态时, 是否可以接受消息更新? 只有leader选举完毕才能再继续对外服务(读写)?
    无 leader 状态不可接受, 需要等待到 leader 选举完毕
    3. 如果某zxid被废弃后, 客户端如何得知? 此种情况不会让客户端得知消息已接收确认的消息 ?
    客户端只有在消息被commit之后才会收到更新成功的确认
    4. 只经过proposal, 没有commit的数据不会返回给客户端?(前leader宕机,可能有些自己写入提交,但是别的节点还未获取的数据)这些数据会被认为是客户端正常提交的数据?
    5. 投票中每个节点都发给其他节点? 投票何时结束? 何时出发统计投票?
    6. 同步: observer 需要如何同步?
    7. 同步是否有可能失败,导致重新选举 leader?
    有可能
    8. 个别follower无法连接leader导致无法完成同步, 重新回到选举状态, 之后如何? 会真正再次进行选举?
    会再次选举
    9. 最大,最小事务id:需要理解存储机制, min 不在快照文件中的最小id, max :事务日志中的最大id, 只要在事务日志中,即都是已经在集群中commit(个别节点上没有)
    10. 修改的proposal 是发给所有节点? 为何 diff 同步还得再发一份 ?

ZK的具体实现

  1. 客户端连接:

     多个地址会随机排序,从前往后继续
    查看类 : org.apache.zookeeper.client.StaticHostProvider
  2. 会话:

     客户端和服务端的一个连接是TCP连接
    
     会话实现类 : SessionImpl
    Ticktime : 会话下次超时时间 会话状态:
    CONNECTING
    CONNECTED
    RECONNECTING
    RECONNECTED
    CLOSED 会话的维护
    * 服务器通过 SessionTracker 维护会话
    * 会话检查和清理都在 Leader 节点处理
    * 通过三个维度管理会话:
    sessionId , session
    失效时间, sessionSet
    sessionId, 失效时间 分桶策略: 用于会话失效检查和清除
    分桶策略的说明:根据失效时间划分不同的session
    把时间按照标准时间单位进行分割
    某会话由于操作(心跳也是一个操作)导致超时时间变化, 从一个桶移到下一个桶
    sessionTracker 中一个线程, 某次检查分桶中还有会话, 则说明超时 会话清理的步骤
    1. 状态设为 CLOSED
    2. 所有节点发送会话关闭
    3. 删除临时节点
    4. 会话列表中移出
    5. 网络断开 会话重连
    CONNECTION_LOSS
    SESSION_EXPIRED
    SESSION_MOVE 待解决:
    清除之后, 还是否可以通过设置 sessionId , 连接上一个session ? 连接时设置 sessionId 如何使用 ?
  3. 数据和存储:

     基本结构:
    ZKDatabase
    存储管理所有会话, datatree 的存储和事务日志
    定期向磁盘写入快照数据
    节点启动恢复内存数据 DataTree
    维护数据/目录/权限
    数据的领域模型 DataNode
    树形中每个节点,包括父节点,子节点,节点数据 事务日志:
    日志文件:
    datalog 或者配置的目录
    vsersion-2 代表日志格式的版本号
    大小64MB
    文件名为后缀16进制格式,其中包含了本日志文件第一个 zxid 日志格式:
    日志文件可以通过工具解析出: LogFormatter
    日志格式内容解析:
    各类会话,事件和内容都存储 日志写入:
    通过 FileTxnLog 实现日志写入, 使用 append 方式
    写入过程:
    1. 确定事务日志文件,确定是否需要扩容(新增文件会用0填满64MB)
    2. 事务序列化
    3. 生成checknum
    4. 写入文件流
    5. fsync, 写入磁盘 数据快照:
    ZK中某个时刻的完整数据,和事务日志是不同的文件
    文件后缀为快照中所包含的最新的zxid
    通过SnapshotFormatter可以查看内容 快照流程:
    1. 确定是否需要快照: 默认 snapCount 100000, 算法避免集群节点同时进行快照
    2. 切换事务日志文件
    3. 创建快照异步线程
    4. 生成快照数据文件
    5. 数据刷入快照文件 事务日志和数据快照的联系和异同:
    快照存储:
    当时内存中的数据模型
    一旦快照存储之后,会新开事务日志文件 事务日志:
    所有 commit 提交的数据都会记录在事务日志中
    事务日志文件 恢复使用:
    取最新的快照文件, 恢复到内存数据结构中
    最新的事务日志中有些数据未反应在快照中, 需要根据事务日志中的记录, 也恢复到数据结构中

Zookeeper学习笔记(中)的更多相关文章

  1. ZooKeeper 学习笔记

    ZooKeeper学习笔记 1.   zookeeper基本概念 zookeeper是一个分布式的,开放源码的分布式应用程序协调服务,是hadoop和Habase的重要组件,是为分布式应用提供一致性服 ...

  2. ZooKeeper学习笔记(二)——内部原理

    zookeeper学习笔记(二)--内部原理 1. zookeeper的节点的类型 总的来说可以分为持久型和短暂型,主要区别如下: 持久:客户端与服务器端断开连接的以后,创建的节点不会被删除: 持久化 ...

  3. ZooKeeper学习笔记(一)——概述

    zookeeper学习笔记(一)--概述 1. 概述 Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目.zookeeper从设计模式的角度来理解:是一个基于观察者设计 ...

  4. Zookeeper学习笔记(上)

    Zookeeper学习笔记 本篇主要是一些基本的介绍和API的使用介绍, 有些只是记录了知识点,而没有完全在笔记中详细解释, 需要自行查找资料补充相关概念 主要参考了课程中的内容: Zookeeper ...

  5. ZooKeeper学习笔记一:集群搭建

    作者:Grey 原文地址:ZooKeeper学习笔记一:集群搭建 说明 单机版的zk安装和运行参考:https://zookeeper.apache.org/doc/r3.6.3/zookeeperS ...

  6. ZooKeeper学习笔记三:使用ZooKeeper实现一个简单的配置中心

    作者:Grey 原文地址:ZooKeeper学习笔记三:使用ZooKeeper实现一个简单的配置中心 前置知识 完成ZooKeeper集群搭建以及熟悉ZooKeeperAPI基本使用 需求 很多程序往 ...

  7. ZooKeeper学习笔记四:使用ZooKeeper实现一个简单的分布式锁

    作者:Grey 原文地址: ZooKeeper学习笔记四:使用ZooKeeper实现一个简单的分布式锁 前置知识 完成ZooKeeper集群搭建以及熟悉ZooKeeperAPI基本使用 需求 当多个进 ...

  8. ZooKeeper学习笔记二:API基本使用

    Grey ZooKeeper学习笔记二:API基本使用 准备工作 搭建一个zk集群,参考ZooKeeper学习笔记一:集群搭建. 确保项目可以访问集群的每个节点 新建一个基于jdk1.8的maven项 ...

  9. Zookeeper学习笔记(下)

    这是ZK学习笔记的下篇, 主要希望可以分享一些 ZK 的应用以及其应用原理 我本人的学习告一段落, 不过还遗留了一些ZK相关的任务开发和性能测试的任务, 留待以后完成之后再通过其他文章来进行分享了 Z ...

随机推荐

  1. ARM过程调用标准——APCS

    APCS(ARM Procedure Call Standard) 1.ARM寄存器 ARM核支持9种工作模式——User/System/Hyp+/SVC/Abort/Undefined/Monito ...

  2. 【ASK】设置网卡启动遇到的事!

    上次动笔是16年的事情了,一晃3年过去了.算了,不感慨了.直奔主题吧. 1.今天朋友要把一批win10的机器设置成网卡启动. 2.网卡是intel集成的. 3.按照主板说明已经设置成功. 4.通过wi ...

  3. Sass 的 & 符号(ampersands)

    重复声明 有时您需要击败第三方 CSS 库的声明来获取样式的所有权: .parent.parent {} 这种方式比使用和 ID,内联样式或!important的压倒性弱,并且它可能比使用任意父元素限 ...

  4. Redis存储对象序列化和反序列化

    import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInpu ...

  5. 阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_7 Mybatis中使用代理Dao的执行过程分析

    另外一种情况,不写Mybits的dao实现类的情况. 切换工程到CRUD的工程.这里面是不写dao实现类的方式 进入到GetMaper里面.这里是创建代理对象 去找SqlSession的实现类Defa ...

  6. 阶段3 1.Mybatis_05.使用Mybatis完成CRUD_2 Mybatis的CRUD-保存操作

    增加的方法 修改映射配置 id是方法名 按照原来jdbc的写法 values里面应该是一堆问号,现在这里不能再去写问号了因为要取值 从我们要执行的方法传的参数里面去取值 所以参数的类型我们必须要告诉这 ...

  7. RESR API (二)之Responses

    Responses 与基本的HttpResponse对象不同,TemplateResponse对象保留 the details of the context that was provided by ...

  8. Nil Channels Always Block(Go语言中空管道总是阻塞)

    译自:https://www.godesignpatterns.com/2014/05/nil-channels-always-block.html 原作者:Alex Lockwood 在本篇文章中, ...

  9. 应用安全 - 工具 - 知道创宇 - CEYE检测平台

    DNS Query

  10. Charles抓包过滤的四种方式

    日常测试中,经常要抓包看请求的request,response是不是传的对,返回的字段值对不对,众多的请求中如何找到自己想要的请求,就需要过滤请求,Charles有4种过滤方式,用那一种都可以,看个人 ...