Zookeeper的数据存储与恢复

【关于作者】

关于作者,目前在蚂蚁金服搬砖任职,在营销投放领域工作了多年,目前在专注于内存数据库相关的应用学习,如果你有任何技术交流或大厂内推及面试咨询,都可以从我的个人博客(https://0522-isniceday.top/)联系我~

事务日志

类型

  • 日志文件

命名

  • log.XX(十六进制的数字-高32位代表epoch、低32位代表操作序号)

内容

01:07:41 session 0x144699552020000 cxid 0x0 zxid 0x300000002 createSession 30000
01:08:40  session  0x144699552020000  cxid  0x2  zxid  0x300000003  create
/test_log,#7631,v{s{31 ,s{/w orld,'anyone}}},F,2

FileTxnLog

  • 复制维护日志的相关操作:事务日志的相关写入、读取以及数据恢复

  • 写入事务日志流程

    • 1.判断当前类是否关联一个日志文件,如果没有关联就以当前事务id为文件后缀创建一个日志文件,同时创建日志头,然后将文件流存入集合StreamsToFlush

    • 2.每次写入都触发磁盘空间大小的检查,如果不足4kb则提前触发宽容(申请)64mb,扩容内容在没使用的情况下用0占满

      • zookeeper.preAllocSize可调节扩容大小
    • 3.将待写入的信息进行序列化,计算checkNum

    • 4.将序列化后的事务头、事务体、checkNum写入文件流

      • 注意:再故障leader选举后,可能存在之前的leader节点的zxid大于选举后的leader节点,这个时候新的leader节点会发送TRUNC命令给这个follower节点。强制对这部分日志进行截断,会从文件中将该部分的事务日志删除

Snapshot数据快照

概念

  • 记录某一时刻zookeeper上的全量内容

命名

  • 使用zxid的十六进制作为文件后缀

FileSnap类

  • 复制处理快照的写入、读取

  • 根据事务记录的个数snapCount来触发快照文件的创建

  • 流程

    • 1.每次事务日志的写入都会去判断是否写入快照文件

      • 比较算法:logCount > (snapCount /2 + randRoll),randRoll为snapCount /2~snapCount /2-1大小的一个值
    • 2.事务日志在写入snapCount个事务后,会重新创建一个事务日志文件,并会单独创建一个线程去执行快照的dump操作

    • 3.根据已提交的最大的zxid来命名快照文件,并将序列化过后的文件头信息、会话信息、DataTree分别序列化写入文件

数据的初始化

FileTxnSnapLog类

  • 流程

    • 1.事物日志操作类–FileTxnSnapLog和快照管理类–FileSnap的初始化
    • 2.初始化一些节点,例如/zookeeper、/zookeeper/quota.,创建PlayBackListener监听器,用于数据修正时候的回调
    • 3.先读取100个快照文件,按照zxid的顺序从大开始读取,校验checkNum校验完整性,如果校验失败则放弃这个快照文件继续读取下一个。如果100个都检验失败了则直接启动失败
    • 4.当全量数据恢复完成后,这个时候有DataTree实例和sessionsWithTimeOuts集合了,能够从快照中得到当前的zxid,再找到比该zxid大的事务日志(也就是还未存入快照的事务)。每一条事务日志恢复后同通过PlayBackListener回调生成proposal提议同步到follower
    • 5.事务日志恢复完成后,得到最大的zxid并解析出epoch,同时在磁盘的currentEpoch和acceptedEpoch文件读取上次记录的epoch进行校验,至此数据初始化流程完成

数据同步

开始阶段

  • 当zookeeper初始化完成后,集群选举后,Learner服务器会向Leader完成注册以后,就会触发数据同步环节

概念

  • leader将没有在learner服务器上同步过的数据同步给learner服务器

流程

  • 获得learn状态

    • 1.learner服务器初始化完成后,learner服务器发送ACKEPOCH数据包给leader服务器,leader服务器从中获得learner服务器的currentEpoch和lastZxid
  • 数据同步初始化

    • 开始数据同步之前,leader服务器先数据同步初始化,会从zookeeper内存数据库TreeData中提取出“提议缓存队列”:proposals,也就是说选举出了leader,leader就立马先从快照、日志给自己先初始化数据

      接着Leader服务器会从Zookeeper内存数据库中提取出事务对应的提议缓存队列:proposals

      • 完成下面三个zxid的初始化(这几个参数都是从内存中读到的并非日志等文件)

        • peerLastZxid:该Learner服务器最后处理的ZXID。
        • minCommittedLog: Leader服务器提议缓存队列committedLog中的最小ZXID。
        • maxCommittedLog:Leader服务器提议缓存队列committedLog中的最大ZXID
  • 数据化同步

    • 流程

      • 首先leader节点会优先使用全量同步的方式进行数据同步,然后根据leader与learner之间的差异决定同步方式
    • 同步方式

      • 直接差异化同步(DIFF 同步)

        • 场景(触发条件)

          • peerlastZxid介于minCommittedLog和maxCommittedLog之间
          • leader再第一阶段提交的proposal还没有commit给follower,然后该leader就挂了,然后某个接收到这个proposal的节点选举为master,然后重新数据初始化,再进行数据同步时,其他节点的lastZxid则会触发DIFF同步,因为他们只是将上个leader的proposal写入了日志文件但是没有接受到commit指令同步到内存
        • 同步流程

          • leader首先发送一个DIFF指令,通知learner进入数据差异化同步阶段,即将推送proposal给learner

            • 实际推送是推送两个包,proposal内容数据包和commit指令数据包
          • 数据包推送完成后,leader会将learner放入forwardingFollowers或observingLearners队列,并发送一个newleader指令通知learner数据已同步

          • learner接收到newleader指令之后发送ack消息表示接收到了同步的数据包

          • leader接收到ack包之后进入“过半”策略的等待,即接收到过半的leader发送的ack包,此时再发送uptodata数据包给所有已完成数据同步的learner

          • learner接收到uptodata指令之后会结束数据同步流程并再次发送ack包给leader

      • 先回滚再差异化同步(TRUNC+DIFF 同步)

        • 场景

          • 是Leader服务器在已经将事务记录到了本地事务日志中,但是没有成功发起Proposal流程的时候就挂了
        • 同步流程

          • 当leader服务器发现learner包含了一条自己没有的事务记录,那么就会让learner进行事务回滚到leader服务器存在且最接近于peerLastZxid的事务

            • 解决了故障恢复阶段第二个问题

              • leader服务器再第一阶段提交的消息,但是并没有发送给learner服务器,需要保证该事务消息被丢弃
          • 再进行DIFF差异同步

      • 仅回滚同步(TRUNC 同步)

        • 场景

          • peerLastZxid>maxCommittedLog
        • 同步流程

          • leader服务器要求learner同步回滚到maxCommitteLog
      • 全量同步(SNAP同步)

        • 场景

          • peerLastZxid 小于minCommittedLog。

          • Leader 服务器上没有提议缓存队列,peerLastZxid 不等于lastProcessedZxid(Leader服务器数据恢复后得到的最大ZXID)

            • 也就是说当前leader从事务日志中找不到比快照最大的zxid还要大的事务id,并且leader最大的zxid又和learner出现了不一致,这个时候就只能全量同步数据
        • 同步流程

          • leader先向learner发送SNAP全量同步指令
          • Leader会从内存数据库中获取到全量的数据节点和会话超时时间记录器,将它们序列化后传输给Learner
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈哈张大侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值