Apache BookKeeper源码分析-recover原理


提要

Apache Bookkeeper github地址:https://github.com/apache/bookkeeper
本源码分析基于bookkeeper 4.14版本

术语说明

  1. bk: Bookkeeper中bookie节点的简称
  2. ledger/fragment/entry: ledge是Bookkeeper中分布式日志分段,由多个fragment组成。fragment由多个entry组成。
  3. e : 为了简述,文中e(E)表示fragment的ensemble size,即fragment的全部可写bookie集合大小。文中部分语境e指fragment的全部可写bookie集合。
  4. qw: 为了简述,文中qw(Qw)表示entry的write quorum size,即entry的写集合大小。文中部分语境qw指entry的写集合。文中entry读取时的读集合等同于写集合。
  5. qa: 为了简述,文中qa(Qa)表示entry的ack quorum size,即entry写入时至少qa数量的bk返回写入成功时bk client即可认为entry写入成功。
  6. 读集合,bookkeeper中只有writeSet(写集合)的概念,读集合其实等同于writeSet。文中在读语境里用“读集合”描述,在写语境里用“写集合”描述。

前言

因为从事Pulsar研发工作,因此本文从pulsar层面介绍Bookkeeper中recover操作的重要性。Pulsar中利用Bookkeeper存储消息,架构图如下:
在这里插入图片描述
pulsar中broker作为bk client创建topic对应的ledger,并持续写入消息,关闭ledger再创建新的ledger并写入,如此往复。
下面通过两个场景来引入recover操作的作用。

broker脑裂:

在Apache Pulsar中,broker使用ZooKeeper来决定哪些broker拥有哪些topic。任何一个给定的topic只能由一个broker持有,这个broker使用 BookKeeper的客户端来创建、写入和关闭它持有的每个topic中的Ledger。

如果broker宕机,那么这broker上topic的所有权就会转移到其他broker上。每个获得给定topic所有权的broker会创建一个BookKeeper客户端来关闭该topic的最后一个 Ledger(由其他broker的BK客户端创建),创建一个新的Ledger,并继续为这个topic提供写服务。

一个更糟糕的情况是,原始的客户端并没有宕机,可能由于长时间GC或网络分区导致客户端在一段时间内无法访问。如果一个客户端正在关闭 Ledger,而原来的客户端仍然在尝试对这个Ledger执行写操作,此时会发生数据覆盖导致数据丢失,这就是所谓的脑裂。

因此,我们需要一种安全的方式来让一个客户端关闭另一个客户端的Ledger,这就是Ledger的recover。当一个客户端关闭另一个客户端的 Ledger 时,均通过该机制完成。

bk下线:

在Bookkeeper运维过程中,有时需要对bk缩容、替换、故障下线等。需要通过如下命令将bk下线,

$bin/bookkeeper shell decommissionbookie -bookieid <target bookieid

并且开启AutoRecovery模块,该模块会处理下线bk的全部ledger。将closed状态的ledger复制到新的bk上,并将新bk信息更新到元数据ledgerMetadata。针对OPEN/IN_RECOVERY状态的ledger执行recover操作,fence该ledger使得pulsar broker无法继续写入,后续pulsar broker会创建新的ledger写入以避免继续写下线bk。达到bk优雅下线的目的。同时AutoRecovery模块还能监视bk宕机,处理宕机bk的全部ledger。

几种bookie下线操作的安全性比较:

最安全:先将其设置为只读,然后等待数据保留策略来删除所有数据,如pulsar中等待消息过期后下线bk。正常bk的下线可以这样操作,且无需复制数据。
安全:通过上述decommissionbookie命令先迁移数据,然后再下线 bookie。因磁盘容量不足需替换bk可以这样操作,需要复制数据。
兜底:通过AutoRecovery模块监听bk下线如宕机等,处理宕机bk的全部ledger,用于bk异常的兜底操作,需要复制数据。

更多关于 bookie 下线文档见:Decommission Bookies
AutoRecovery模块原理分析见:Apache BookKeeper源码分析-AutoRecovery模块原理


一、recover概述

recover操作中,先将ledger状态改为IN_RECOVERY,再fence该ledger并从bookie中读取lac(取E个bookie中的最大lac,但可能低于实际写入成功的最大entryId),取lac和ensemble的最新fragment的起始entryId的最大值作为startRead,从startRead+1位置读取entry,再将读取的entry写入bookie,且写入entry是幂等的不会造成entry重复写并保证已成功写入entry有足够的副本数。若写入失败则会选出新的ensemble重新写入。写入成功则更新lac,最后将ledger从IN_RECOVERY改成CLOSED,并保存更新后的lac。

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值