Twitter如何升级Hadoop+Kafka架构实现实时处理数十亿个事件?


Twitter,我们每天实时处理大约 4000 亿个事件并生成 PB 级数据。我们消费数据的事件源有很多种,它们在不同的平台和存储系统中产生,例如 Hadoop、Vertica、Manhattan 分布式数据库、Kafka、Twitter Eventbus、GCS、BigQuery 和 PubSub。
为了处理这些来源和平台中的这些类型的数据,Twitter 数据平台团队构建了内部工具,例如用于批处理的 Scalding、用于流式处理的 Heron、用于批处理和实时处理的名为 TimeSeries AggregatoR (TSAR) 的集成框架,以及用于数据发现和消费的数据访问层。然而,随着数据的快速增长,大规模仍然挑战着工程师用来运行管道的数据基础设施。例如,我们有一个交互和参与管道,可以批量和实时处理大规模数据。随着我们的数据规模快速增长,我们面临着减少流延迟并提供更高的数据处理准确性以及实时数据服务的高要求。
对于交互和参与管道,我们从各种实时流以及服务器和客户端日志中收集和处理数据,以提取具有各种聚合级别、时间粒度和其他指标维度的推文和用户交互数据。聚合的交互数据尤其重要,并且是 Twitter 的广告收入服务和数据产品服务检索印象和参与度指标信息的真实来源。此外,我们需要保证跨数据中心对存储系统中交互数据的快速查询,低延迟、高准确率。为了构建这样一个系统,我们将整个工作流拆分为几个组件,包括预处理、事件聚合和数据服务。
 
旧架构
旧架构如下图所示。我们有一个包含批处理和实时处理管道的 lambda 架构,在 Summingbird 平台内构建并与 TSAR 集成。有关 lambda 架构的更多信息,请参阅什么是 Lambda 架构?批处理组件源是存储在 Hadoop 分布式文件系统 (HDFS) 上的 Hadoop 日志,例如客户端事件、时间线事件和 Tweet 事件。我们构建了几个 Scalding 管道来预处理原始日志并将它们作为离线源摄取到 Summingbird Platform 中。实时组件源是 Kafka 主题。 
实时数据存储在 Twitter Nighthawk 分布式缓存中,批量数据存储在曼哈顿分布式存储系统中。我们有一个查询服务来访问来自两个商店的实时数据,供客户服务使用。

目前,我们在 3 个不同的数据中心拥有实时管道和查询服务。为了降低批量计算成本,我们在一个数据中心运行批量管道并将数据复制到其他 2 个数据中心。 
 
现有架构的问题与挑战
由于我们实时处理的数据规模大、吞吐量大,因此实时管道可能会丢失数据和不准确。对于 Heron 拓扑,在需要处理的事件较多且 Heron bolt 无法及时处理的情况下,拓扑内部存在背压。此外,由于垃圾收集成本高,Heron bolts 会变慢。
当系统长时间处于背压下时,Heron bolt 会累积 spout 延迟,这表明系统延迟很高。通常发生这种情况时,拓扑滞后需要很长时间才能下降。更常见的是,如我们的 Heron 管道中所见,也有许多 Heron Stream Manager 死亡(Stream Manager 管理拓扑组件之间的元组路由),并且延迟不断增加。
当前的操作解决方案是重新启动 Heron 容器以启动流管理器,以便螺栓可以重新启动处理流。这可能会导致操作期间的事件丢失,从而导致 Nighthawk 存储中的聚合计数不准确。
对于批处理组件,我们构建了几个处理 PB 级数据并每小时运行一次以将数据汇入曼哈顿的繁重计算管道。集中式 TSAR 查询服务整合曼哈顿和夜鹰数据,为客户服务提供数据服务。由于潜在的实时数据丢失,TSAR 服务可能向我们的客户提供较少的聚合指标。
为了克服这个数据丢失问题,减少系统延迟并优化架构,我们建议在 kappa 架构中构建管道,以仅流模式处理事件。有关 kappa 架构的更多信息,请参阅什么是 Kappa 架构?在该解决方案中,我们移除了批处理组件并依靠实时组件来提供低延迟和高精度的数据,这简化了架构并消除了批处理管道中的计算成本。
 
Kafka 和数据流的新架构


上图是Kafka 和 Dataflow 的新架构 
新架构建立在 Twitter 数据中心服务和 Google Cloud Platform 之上。在内部,我们构建了预处理和中继事件处理,将 Kafka 主题事件转换为具有至少一次语义的发布订阅主题事件。在 Google Cloud 上,我们使用流式 Dataflow 作业来应用重复数据删除,然后执行实时聚合并将数据汇入 BigTable。
第一步,我们构建了几个事件迁移器作为预处理管道,它们执行转换和重新映射字段,然后将事件发送到 Kafka 主题。我们使用基于 Kafka 的内部定制流框架为至少一次语义创建了这些流管道。作为第二步,我们构建了事件处理器来以至少一次语义流式传输事件。事件处理器处理到 Pubsub 事件表示的转换,并生成由 UUID 和其他与处理上下文相关的元信息组成的事件上下文。UUID 用于下游的 Dataflow 工作器进行重复数据删除。我们为内部 Pubsub Publisher 应用几乎无限重试设置,以实现至少一次将消息从 Twitter 数据中心发送到 Google Cloud。创建新的 Pubsub 表示事件后,
在 Google Cloud 上,我们使用基于 Google Dataflow 构建的 Twitter 内部框架进行实时聚合。Dataflow 工作人员实时处理重复数据删除和聚合。重复数据删除过程的准确性取决于定时窗口。我们调整了我们的系统以在重复数据删除窗口中实现最大努力重复数据删除。我们通过同时将数据写入 BigQuery 并连续查询重复的百分比,证明了高重复数据删除的准确性,如下所述。最后,将带有查询键的聚合计数写入 Bigtable。
对于服务层,我们使用 Twitter 内部 LDC 查询服务,前端在 Twitter 数据中心和不同的后端,例如 Bigtable 和 BigQuery。整个系统每秒可以流式传输数百万个事件,延迟低至约 10 秒,并且可以在我们的本地和云流式传输系统中以高流量进行扩展。我们使用 Cloud Pubsub 作为消息缓冲区,同时保证我们的本地流媒体系统不会丢失数据。然后是重复数据删除以实现近乎一次的处理。
这种新架构节省了构建批处理流水线的成本,对于实时流水线,我们能够实现更高的聚合精度和稳定的低延迟。此外,我们不需要在多个数据中心维护不同的实时事件聚合。
 
。。。
结论
通过将基于 TSAR 的旧架构迁移到 Twitter 数据中心和谷歌云平台上的混合架构,我们能够实时处理数十亿事件,并实现低延迟、高精度、稳定性、架构简单和降低运营成本对于工程师。