15.8 BooKeeper
BooKeeper具有副本的功能,目的是提供可靠的日志记录。在BooKeeper中,服务器被称为账本(Bookies),在账本之中有不同的账户(Ledgers),每一个账户由一条条的记录(Entry)组成。如果使用普通的磁盘存储日志数据,那么日志数据可能遭到破坏,当磁盘发生故障的时候,日志也可能被丢失。BooKeeper为每一份日志提供了分布式的存储,并且采用了大多数(quorum,相对于全体)的概念,也就是说,只要集群中的大多数机器可用,那么该日志一直有效。
BooKeeper通过客户端进行操作,客户端可以对BooKeeper进行添加账户、打开账户、添加账户记录、读取账户记录等操作。另外,BooKeeper的服务依赖于ZooKeeper,可以说BooKeeper是依赖于ZooKeeper的一致性及分布式的特点在其之上提供了另外一种可靠性服务。如图15-12为BooKeeper的架构。
从上图中可以看出,BooKeeper中总共包含四类角色,分别为:账本(Bookie)、账户(Ledger)、客户端(BooKeeper Client)以及元数据存储服务(Metadata Storage Service)。下面我们来简单介绍这四类角色的功能。
账本(Bookie):账本是BookKeeper的存储服务器,它存储的是一个个的账本,可以将账本理解为一个节点。在一个BookKeeper系统中存在有多个账本(节点),每个账户被不同的账本所存储。若要写一条记录到指定的账户中,该记录将被写到维护该账户的所有账本节点中。为了提高系统的性能,这条记录并不是真正地被写入到所有节点中,而是选择集群的一个大多数集进行存储。该系统独有的特性使得BookKeeper系统有良好的扩展性。即,我们可以通过简单地添加机器节点的方法提高系统的容量。
图 15-12 BooKeeper架构
账户(Ledger):账户中存储的是一系列的记录(Entry),每一条记录包含一定的字段。记录通过写操作一次性写入,只能进行附加操作不能进行修改。每条记录包含如下字段,见表15-6。
当满足下列两个条件时,某条记录才被认为是存储成功:
1)之前所记录的数据被账本节点的大多数集所存储;
2)该记录被账本节点的大多数集所存储。
客户端(BookKeeper Client):客户端通常与BookKeeper应用程序进行交互,它允许应用程序在系统上进行操作,包括创建账户,写账户等。
元数据存储服务(Metadata Storage Service):元数据信息存储在ZooKeeper集群当中,它存储关于账户和账本的信息,例如,账本由集群中的哪些节点进行维护,账户由哪个账本进行维护等。
应用程序在使用账本的时候,首先需要创建一个账户。在创建账户时,系统首先将该账本的Metadata信息写入到ZooKeeper中。每一个账户在某一时刻只能有一个写实例。在其它实例进行读操作之前首先需要将写实例关闭。如果写操作由于故障而未能正常关闭,那么下一个尝试打开账户的实例将需要首先对其进行恢复并正确关闭写操作。在进行写操作时同时需要将最后一次的写记录存储到ZooKeeper中,因此恢复程序仅需要在ZooKeeper中查看该账户所对应的最后一条写记录,然后将其正确地点写入到账户中,再正确关闭写操作。在BookKeeper中该恢复程序由系统自动执行,不需要用户的参与。