BookKeeper概念和架构

序言,关于cap

CAP是分布式系统中的一个特别重要的理论。

BookKeeper概念和架构

CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。CAP是NOSQL数据库的基石。

分布式系统的CAP理论:理论首先把分布式系统中的三个特性进行了如下归纳:

  • 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
  • 可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
  • 分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。

关于分区容错性,需要解释一下:所谓分区指的是网络分区的意思,详细一点解释,比如你有A B两台服务器,它们之间是有通信的,突然,不知道为什么,它们之间的网络链接断掉了。那么现在本来AB在同一个网络现在发生了网络分区,变成了A所在的A网络和B所在的B网络。所谓的分区容忍性,就是说一个数据服务的多台服务器在发生了上述情况的时候,依然能继续提供服务。

如果不能满足p,就不能再网络分区的情况下保证服务,那么就是单个节点的情况,和分布式系统的设计初衷是背离的。所以讨论cap是,一般都是满足p的前提下,来选在满足a还是满足c。

如果满足C,即所有节点都需要有相同的数据,如果没有就不可服务,满足不了A;

如果满足A,即服务可以一直存在,那么在节点故障等场景下,就满足不了C。

BookKeeper是满足CP特性的分布式系统,并且同时提供了较高的可用性,下文会有论述。

BookKeeper是企业级的存储系统,提供强持久性、一致性和低延迟的保证。最初起源于Yahoo!,用来解决HDFS NN的单点问题。2011年作为ZooKeeper的子项目在Apache孵化,2015成为*项目。

BookKeeper

一个企业级、实时的存储平台需要满足一下要求:

  • 读写低延迟(< 5ms)
  • 数据存储要持久、一致并且支持容错
  • 对写入数据提供流式传播或者tail传播的功能
  • 高效的存储,可以提供对实时数据以及历史数据的访问

BK是一个可扩展、支持容错并且可以保证低延迟的存储服务。满足了以上的要求,适用于很多场景:

  • 为分布式存储提供高可用/副本机制(HDFS NN,Manhattan(KV store in Twitter))
  • 在单个集群或者多个集群之间提供复制功能
  • 为订阅/发布系统提供存储能力(EvnentBus in Twitter and Apache pulsar)
  • 为流式作业存储不可变对象(比如checkpoint 数据快照)

BK概念和术语

Records(Entry)

数据在BK以record的形式而非bytes的形式写入BK。Record是最小的I/O单位,也是地址单元。每个record都包含了一个***(单调递增的long性数)。Client从某一个record开始读取数据,或者tail一个序列,即监听添加到log的下一个record。可以单条或者批量接收record。***也可以用来随机检索record。

Entry除了包含写入bookie的实际数据之外,还包含一些元数据信息

字段 说明 类型
Ledger Number Entry写入的ledger ID long
Entry number Entry的唯一ID long
Last confirmed (LC) 最后记录的Entry ID long
Date 数据 byte[]
Authentication code 鉴权数据 which includes all other fields in the entry byte[]

Logs(BK的存储)

BK为提供了两种存储原语:

  • ledger,即 log segment
  • stream ,即 log stream

一个Ledger是数据records的序列,ledger在客户端显式的关闭或者writer写入失败时终止。一旦一个ledger 终止以后,就不能append记录。ledger是最底层的存储原语,可以用于存储有限的序列或者无限的流。

BookKeeper概念和架构

Ledgers是entry的序列,Entry是bytes序列。Entry写入ledger时,是

  • 顺序的
  • at most once

ledgers支持 append-only的语义。Entry写入到ledgers之后,就不可以被修改了。Client应用决定写入的顺序。

一个stream是*的,无限的record序列。Leger可以被打开多次来append record。一个stream物理上会有多个ledger组成,每个ledger会根据时间或者空间滚动策略来滚动。stream会存在很长时间,所以保留数据策略是truncating,会根据时间或者空间策略来丢弃老的数据。
BookKeeper概念和架构

ledge和stream为历史数据或者实时数据提供了统一的存储抽象。Log streams提供了数据tail或者stream能力。实时数据存储在ledger中,随着时间会变成历史数据。

NameSpackes

Log stream通常在namespacke下分类、管理。NameSpace是租户创建流时会使用到的一种机制。一个namespace是数据存储策略的部署和管理单元。在同一个namespace下的所有stream继承相同的配置,数据存储在存储策略配置的存储节点上。可以方便的管理过个stream。

Bookie

BK在多个server之间备份存储数据entry,这些server成为Bookie。Bookie是个独立的Bk存储服务。

Bookies是处理ledgers(更具体一些,是ledger的片段)的server。Bookies作为ensemble的一部分起作用

一个bookie是一个独立的BookKeeper存储服务。出于性能的考虑,Bookie储存ledger的片段,而不是真个ledgers。对于任意的一个ledger, ensemble是存储这个ledger entries的bookies组。entry写入ledger时,会在ensemble中进行条带化的存储。

向ledger写入entry时,entry会被条带化到ensemble中(bookie的子集不是全部)。

Metadata

BK的元数据主要是可用的BK以及ledger信息。使用ZK存储。

与BookKeeper交互

BookKeeper客户端主要有两个角色:创建和删除ledgers,向ledgers写入或者从ledgers中读取entry。

主要两种方式和BK交互:

  • 创建ledger或者stream来写数据
  • 打开ledger或者stream来读数据

BK提供了两种API:

  • ledger API: 底层API,可以直接操作ledger,比较灵活。
  • Stream API: higher-level面向流的API,通过Apache DistributedLog提供,直接操作流,不用关心与ledger交互的复杂性。

选择哪种API,应该基于应用对于ledger的控制粒度。两种API可以在应用*同使用。

BookKeeper 框架图

BookKeeper概念和架构

注意:

  • BK的典型安装会包含:Metadata store,bookie cluster,多个cilent
  • Bookie自己向metadata store注册自己
  • Bookie在进行GC来清理数据时需要和metadata store交互
  • 应用程序使用Client lib来和BK交互
    • 使用Ledger API获取细粒度的管控
    • 不需要底层ledger控制,则使用stream api