Delos 起始于 2017 年,目标是为 Facebook 的控制面开发一个新的存储系统。我们的第一个场景是需求一个提供 Table API 的数据库。但是,最终我们需要支持其它多种 APIs(例如 ZooKeeper )。
为了快速地实现并部署 Delos ,我们利用了一种叫做 “virtual consensus” 的新技术,这种技术通过 VirtualLog 的抽象来存储和定序命令,以此来保持数据库多个副本间保持同步。VirtualLog 本身是架构在不同的共识协议之上的一层,这些不同的共识协议我们叫做 Loglets 并可以在它们之间切换,允许 Delos 在不停机的情况下改变它们的共识子系统。
“Virtual consensus” 交付到生产环境的第一个基于 Delos 的数据(DelosTable),使用 ZooKeeper 作为其底层的 Loglet 。简单地说,我们使用了久经考验 ZooKeeper 的共识协议,同时在基础之上支持 Table API。后来,我们将 DelosTable 切换到自定义构建的 NativeLoglet 协议以获得更好的性能并删除 ZooKeeper 作为关键路径依赖项。
但是,Delos 的最终目标不是构建一个具有固定 API 的单一数据库。相反,我们希望支持多种具有不同 APIs 的数据库,这样应用可以选择最适合他们场景的 API 。具体来说,我们紧接着的一个目标就是构建了另外一种数据库,它拥有和 ZooKeeper 一样的 APIs,并通过这个数据库替换了 Facebook 的 ZooKeeper 服务集群。随之而来的事情是,我们必须扩展 Delos :不仅在吞吐量和容量的常规维度上,更重要的是从需要理解、扩展和操作 Delos 的代码工程师的视角,来扩展和构建系统能力。
抽象使工程师快乐……对吧?
为了让开发和(运维)操作多个数据库更友好,我们将 Delos 设计为一个平台,这个平台用于构建数据库。每一个基于 Delos 的数据库(例如 DelosTable)都构建在 Delos 平台上,由非常薄的一层 API 相关的代码来承载。这个平台提供常见但非常复杂的基础支撑,例如:共识、本地存储、备份等。如此一来,通过自定义的 APIs 构建、部署、操作新的数据库变得非常简单,大多数代码和操作工具在多个数据库之间都是一样的。
这种分离能力允许 Facebook 的 ZooKeeper 团队开始在 Delos 平台开发 Zelos ,一个和 ZooKeeper APIs 完全一样的 ZooKeeper 替换系统。这样的直接受益是,ZooKeeper 团队可以专注于在 Delos 上实现复杂的 ZooKeeper API,并将之前的用户迁移过来。DelosTable 团队可以专注于开发 Table API。与此同时,Delos 平台团队则专注于改进共识和存储的底层代码,以获得更好的可靠性和性能。每一个团队都可以专注于自己的目标和核心竞争力,同时分摊开发和运营复杂服务的成本。换句话说,我们都是快乐的工程师!
但好景不长,我们很快就遭遇到了一些挑战。在 Zelos 需要的大多数 API 都和 DelosTable 相同的同时,它仍需要一定程度上的自定义能力。例如,ZooKeeper 需要 session 级别的有序,这个需求比其它数据库系统要强很多。因此,Zelos 团队需要对平台进行改进(例如,通过 Batch 模式来满足 ZooKeeper 的性能)。最终,通过单一代码库的统一平台将不同的团队联系起来的愿望,并没有实现!
虚拟化再一次出场!
“Use a good idea again.” — Butler Lampson, Hints for Computer System Design
为了打破这种僵局,我们发明了一种叫做「日志结构协议」的抽象:一种基于 VirtualLog 的协议。每个协议由在每个终端主机上执行的日志结构协议引擎(简称:引擎)组成,通过 VirtualLog 与其对应方进行交互。Delos 平台代码被组织为此类引擎的集合,每个引擎都提供特定的功能。每个数据库(例如 DelosTable 或 Zelos)都可以在一组自定义的这些协议上运行。
从某种意义上说,这种方法代表了一种形式的虚拟化。每个日志结构协议都是 VirtualLog 上的复制虚拟状态机。我们不是将数据库的功能构建为单个复制状态机,而是将其模块化为多个可重用的虚拟状态机。一个日志结构的协议只能访问它自己的本地数据库状态分区,从而实现协议之间的隔离。
此外,日志结构协议 — 顾名思义 — 是可以在应用程序和 VirtualLog 之间分层的协议。此类协议以与传统点对点网络中的网络协议相同的方式在 VirtualLog 之上添加功能。新的日志条目沿分层向下流向 VirtualLog,而日志中的现有条目沿分层向上流向数据库。与传统网络分层中的协议一样,引擎可以在上面生成的日志条目上搭载标头。它可以在日志条目到达更高层之前对其进行过滤或重新排序;并在它们到达较低层之前进行批处理、加密、压缩或其它动作。
Delos 中的日志结构协议,使具有不同目标、客户和理念的多个团队能够利用公共代码库。我们能够通过两个团队的个别工程师解锁创新,他们可以编写新协议而无需担心副作用和与其他代码的交互。例如:
此外,日志结构的协议允许 Delos 平台团队的工程师专注于具有挑战性的“最后一英里”,以实现一致性和持久性;不同数据库都可以受益,保护平台免受极端情况故障带来的影响。此外,由于存在用于不同数据库的单一、统一的工具链,工程师的 oncall 得到了显着简化。
从某种意义上说,虚拟化为复制数据库提供了与其他系统领域相同的好处:更快的开发和部署周期,以及更简单的操作。创新和影响在多个团队和角色中民主化:任何工程师都可以为新功能编写日志结构的协议,而无需对复杂的故障场景进行推理。最终,虚拟化对真正重要的指标产生了最大的影响:我们的工程师都很 Happy !