Twitter 是如何构建高性能分布式日志的

阅读数:7328 2015 年 9 月 22 日

在 Twitter,他们使用复制日志来解决分布式系统中存在的一系列问题。比如,他们有一个Manhattan 分布式键值数据库。该系统采用了一种灵活的最终一致性数据模型,允许开发者以一致性换取低延迟。写入操作会单独应用到数据集的所有副本,Manhattan 会保证各个副本的数据最终一致。但是,应用程序在查询一个刚刚更新过的数据集时可能会因为读取的副本不同而获取到不同的数据。为了防止这种不一致的情况,他们必须针对每个副本以同样的顺序应用所有更新。日志(一个严格有序的操作记录)是实现序列化更新的一种简单方式。在 Twitter,还有其它有类似情况的应用程序需要某种日志服务基础设施。于是,他们构建了 DistributedLog,一个高性能的“复制日志(replicated log)”服务。近日,Twitter 消息团队高级软件工程师Leigh Stewart撰文分享了他们构建该服务的经验。

他们根据自己构建分布式系统的经验,对复制日志服务提出了如下要求:

  • 可靠性:稳定,而且在出现各种常见问题(网络划分、集群拓扑变化、流量峰值等)时都能提供可以预见的性能;
  • 高吞吐量:在高峰时段可以支持每秒数以百万计的消息传递;
  • 低延迟:始终如一的低延迟;
  • 工作负载隔离:在一个以日志为中心的分布式系统中,工作负载可以分为如下三类:写日志尾、读日志尾和“追赶读(catch-up read)”。各类负载互不影响;
  • 可扩展性: 在地理、节点数量、每秒请求数、数据规模、租户数量等各个维度可扩展;

  • 可操作性:在扩展时易于操作,比如可以很容易地增加或移除节点;
  • 简单:接口简单,便于开发人员使用。

为了满足上述需求,他们评估了几种可选方案,其中包括:(一)使用类似 Kafka 的发布 / 订阅系统;(二)使用类似PaxosRaft的一致性算法构建新的服务或库;(三)使用一种像Apache BookKeeper那样的底层日志服务。对于 Kafka,他们对其 I/O 模型心存疑虑,并认为它缺乏强有力的稳定性保证;Paxos 和 Raft 颇具吸引力,但从头构建一个新系统需要一个很长的开发周期。于是,选项仅剩了 Apache BookKeeper。这个最初为 HDFS 设计的事务日志后台唯一关注的是存储效率和日志段(称为 Ledger)检索。另外,不同于 Kafka,它并不关注发布 / 订阅系统中的一些高级特性,如“分区归属(partition ownership)”、面向流的抽象等。以下是 Apache BookKeeper 的核心优势:

  • 灵活的复制功能:BookKeeper 采用了一种基于投票的复制机制。该机制直接由客户端驱动,可以避免引入主次复制方案中存在的延迟,使他们可以屏蔽数据库故障或速度慢的问题,实现可预见的延迟。此外,BookKeeper 复制设置高度可配置,并支持可插拔的“副本放置(replica placement)”策略。
  • 卓越的 I/O 性能:BookKeeper 节点使用不同的 I/O 组件处理上述三种核心日志存储负载,提供了卓越的 I/O 性能。

因此,他们认定,BookKeeper 是一个日志存储的上佳选择。不过,它虽然满足了上面列出的大部分关键需求,但是还缺少一些关键的特性,比如高级抽象、日志归属等。为此,他们在 BookKeeper 之上构建了一个服务层DistributedLog,提供一种可以满足上述需求的、端到端的服务,如下图所示:

BookKeeper提供稳定性和高可用的日志段存储;DistributedLog 提供简单的抽象,如命名、数据分割、保留策略等;应用程序层负责分区、路由、偏移量管理等高级特性。其中,DistributedLog具有如下特性:

  • 面向流的抽象DistributedLog只暴露了一些简单的实体,在大多数情况下,用户都只需考虑将数据附加到一个已命名的流对象上;
  • 命名和元数据:DistributedLog 提供了一种永久命名和元数据方案,用户可以将已命名的日志或主题视为Ledgers 集合的替代;
  • 日志归属方案:BookKeeper 没有规定一种专门的日志所有者方案,因此,DistributedLog 实现了一种基于ZooKeeper的方案;
  • 数据管理策略:DistributedLog 允许用户针对不同的场景调整数据保留策略,并提供了一种将日志分段以便在存储节点间平衡数据分布的控制机制;
  • 可调节的读写通道:在写入路径上,DistributedLog 提供了一种高度可调节的批处理机制;在读取路径上,它提供了一种可调节的预读机制;
  • 高效“扇入(fan-in)”和“扇出(fan-out)”的服务层:DistributedLog 是一个专门针对多租户数据中心环境优化过的服务层,可以通过聚合来自多个数据源的写入来支持不关注日志归属的应用程序。在有成千上万的读者消费同一数据流的情况下,该服务可以通过缓存日志数据优化读取路径;
  • 跨地理位置复制日志:可以保证日志跨多个数据中心可用;

在过去的两年里,DistributedLog 解决了许多分布式系统中颇具挑战性的问题,其本身也在发展。事实证明,基于 DistributedLog 的一致性写入路径非常可靠,而且性能令人称赞。将 DistributedLog 引入 Manhattan 的写入路径平均仅仅增加了 10 毫秒的写入延迟。


感谢郭蕾对本文的审校。

给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。