为什么Twitter决定采用kafka作为其发布订阅系统?


Twitter系统的实时性质为Twitter工程团队带来了独特而具有挑战性的问题。我们需要快速发布突发新闻,向用户提供相关广告,并解决许多其他实时用例。Twitter的Pub / Sub系统为Twitter团队提供了处理此工作负载的基础架构。
Twitter的Messaging团队过去几年一直在运行一个内部Pub / Sub系统EventBus(建立在Apache DistributedLog之上),但我们最近决定转向Apache Kafka,在这篇博文中,我们将讨论为什么我们选择采用Kafka作为Twitter的Pub / Sub系统以及我们在此过程中遇到的不同挑战。

什么是卡夫卡?
Apache Kafka是一个开源的分布式流媒体平台,可以以高吞吐量和低延迟传输数据。Kafka最初是在LinkedIn构思并于2011年开源的,并且从那时起被社区广泛采用,包括在其他公司,使其成为业界首选的事实上的实时消息系统。
Kafka的核心是基于日志构建的Pub / Sub系统,具有许多理想的属性,例如水平可伸缩性和容错性。从那以后,Kafka已经从消息系统发展成为一个成熟的流媒体平台(参见Kafka Streams)。

为什么迁移?
您可能想知道为什么Twitter首先选择构建内部消息传递系统。Twitter几年前实际上使用过Kafka(0.7),但是我们发现了它不适合我们的用例的问题 - 主要是在追赶读取期间进行的I / O操作的数量以及缺乏持久性和复制。然而,硬件和卡夫卡都已经经过了漫长的发展道路,现在已经解决了这些问题。
硬件的改进已经使SSD的价格足够便宜,这有助于我们在HDD上看到的随机读取的先前I / O问题,并且服务器NIC具有更多的带宽,使得分割服务和存储的吸引力降低图层(EventBus)。此外,较新版本的Kafka现在支持数据复制,提供我们想要的持久耐用性保证。
将所有Twitter的Pub / Sub用例迁移到一个全新的系统将是一个昂贵的过程。所以,自然而言,搬到卡夫卡的决定不是自发的,而是经过精心策划和数据驱动。迁移到卡夫卡的动机可归纳为两个主要原因:成本和社区。

成本
在整个公司宣布搬到Kafka的决定之前,我们的团队花了几个月的时间评估Kafka比较我们运行在EventBus上的类似工作负载 - 持久写入,拖尾读取,追赶读取和高扇出读取,以及一些灰色故障情况(例如,减慢群集中的特定代理)。
在性能方面,我们看到Kafka的延迟显着降低,无论吞吐量如何,从消息创建时到消费者阅读消息时的时间戳差异来衡量。
这可归因于几个因素,可能包括但不限于:

  • 在EventBus中,服务层和存储层是分离的,这引入了额外的跳(网络时间和时间都通过JVM代理层),而在Kafka中只有一个进程处理存储和请求服务(参见下图) )。
  • EventBus显式阻止对fsync()调用的写入,而Kafka在后台依赖操作系统到fsync()。
  • 卡夫卡使用零拷贝

从成本的角度来看,EventBus需要服务层(针对高网络吞吐量进行了优化)和存储层(针对磁盘进行了优化)的硬件,而Kafka使用单个主机来提供这两者。因此,EventBus需要更多的机器才能来提供与Kafka相同的工作负载。
对于单个消费者用例,我们节省68%的资源,对于拥有多个消费者的扇出案例,我们节省75%的资源
一个问题是,对于极其带宽繁重的工作负载(非常高的扇出fanout 读取),EventBus理论上可能更有效,因为我们可以独立地扩展服务层。但是,我们在实践中发现,我们的扇出不够极端,不值得分离服务层,特别是考虑到现代硬件上的可用带宽。

社区
如上所述,卡夫卡已被广泛采用。这有助于我们首先让我们利用数百名开发人员为Kafka项目做出贡献的错误修复,改进和新功能,而不是工作在EventBus / DistributedLog上的八名工程师。此外,我们的Twitter客户在EventBus中想要的许多功能已经在Kafka中构建,例如流媒体库,至少一次HDFS管道,以及一次性处理。
此外,当我们在客户端或服务器上遇到问题时,我们可以通过快速搜索网络轻松找到解决方案,因为很可能其他人遇到了同样的问题。同样,对于不太受欢迎的项目来说,采用良好的项目的文档通常比文档更详尽。
采用和回馈卡夫卡等热门项目的另一个重要方面是招聘目的。一方面,通过回馈卡夫卡,人们可以了解Twitter的工程。另一方面,由于新工程师已经熟悉该技术,因此为团队招聘工程师要容易得多。这消除了EventBus所需的任何必要的加速时间。

挑战
尽管转移到卡夫卡的声音,但这并不是一帆风顺的。我们在这个过程中遇到了许多技术挑战和适应性挑战。
从技术角度来看,我们遇到的一些挑战包括配置调优和Kafka Streams库。与许多分布式系统一样,为了支持Twitter的实时用例,需要对大量配置进行微调。在运行Kafka Streams时,我们发现Kafka Streams库中的元数据大小存在一些问题,这些问题是由于过时的客户端在关闭后仍然保留其元数据。
另一方面,Kafka与EventBus存在架构差异,这要求我们以不同方式配置系统和调试问题。这方面的一个例子是如何在EventBus(仲裁写入)和Kafka(主从复制)中完成复制。写请求在EventBus中并行发送,而Kafka要求从节点仅在主机收到写请求后才复制写请求。此外,两个系统之间的持久性模型是非常不同的 - EventBus仅在数据持久化(fsync'd)到磁盘时确认写入,而Kafka表明复制本身将保证持久性并且数据持久存储在磁盘上之前就确认写入请求。

期待
在接下来的几个月里,我们的计划是将我们的客户从EventBus迁移到Kafka,这将有助于降低运营Twitter Pub / Sub系统的成本,并使我们的客户能够使用Kafka提供的其他功能。我们将持续关注生态系统中的不同消息传递和流媒体系统,并确保我们的团队为我们的客户和Twitter做出正确的决策,即使这是一个艰难的决定。