腾讯盈科如何使用Apache Kafka每天处理10T+消息

2020-08-04 06:20:36

作为世界上最大的互联网平台公司之一,腾讯利用技术丰富用户生活,帮助企业进行数字化升级。一个例子是广受欢迎的微信应用程序,它在全球拥有10多亿活跃用户。平台和内容集团(PCG)负责整合腾讯的互联网、社交和内容平台。盈科推动IP跨平台、多模式开发,总目标是打造更多元化的优质数字内容体验。自成立以来,许多主要产品-从著名的QQ、QQ空间、视频、应用商店、新闻和浏览器,到生态系统中相对较新的成员,如直播、动漫和电影-一直在巩固的基础设施和一套基础技术组件的基础上不断发展。

在我们的中心矗立着连接数据和计算的实时消息传递系统。我们自豪地围绕Apache Kafka建立了许多重要的数据管道和消息队列。我们的Kafka应用与其他组织类似:我们构建跨地域日志摄取的管道、机器学习平台、微服务之间的异步通信。独特的挑战来自沿多个维度扩展我们的架构,即可扩展性、定制和SLA。以下是一些值得注意的要求:

工作量。要全面掌握复杂应用中的数据动态,需要近距离、持续的观察。在一个月活跃用户超过10亿的消费互联网的高度季节性和多事性的环境中,产品推广和大规模的试验往往会导致交易量每天激增20倍。在高峰期,我们的管道需要为单个产品每秒传输400万封邮件(或64 GB/秒)。因此,我们的运营团队面临着管理和优化总共超过1000个物理节点的群集的挑战。

低延迟和高SLA。随着组织迅速转向利用实时分析来推动业务决策,对数据准确性和及时性的要求变得比以前更加严格。想象一下,当视频消费事件被提供给推荐算法时,或者当发现引导内容供应激励的热门趋势时-希望数据能够在发布后的几秒钟内使用,并且端到端损失率低至0.01%。

灵活性。现在的实时数据处理体系结构是组件化和可配置的。因此,消息传递系统需要在不影响性能的情况下处理使用者数量、访问模式和主题分布的频繁更改。我们不能像传统的摄取管道那样简单地针对静态拓扑优化系统。

理想情况下,我们需要一个多租户、巨大的pub/sub系统来满足所有这些需求。在高峰期,它应该可靠地支持每秒数百千兆位的数据传输。它应该几乎立即进行配置,而不会中断现有工作负载;它还需要容忍单节点和群集故障。考虑到接口问题,我们希望尽量兼容Kafka SDK。在探索了单个卡夫卡集群的局限性之后,我们进行了一系列的发展。

我们选择在Kafka生态系统中开发,因为它的成熟,丰富的客户端和连接器集,以及替代产品中的卓越性能。另一方面,使用Apache Kafka来满足上述要求还存在一些空白。例如,超出预期的是,我们发现在频繁使用期间,多个磁盘故障会导致副本不足,甚至群集级别的可靠性问题。此外,扩展群集的容量(即添加代理)需要大量的数据重新平衡,通常会造成数小时的操作延迟。如果没有完全自动化的容量管理,这将极大地限制我们支持大型企业的方式。

鉴于我们决定将最初的增强重点放在可伸缩性和容错性上,我们开始构建一个代理层,该层联合多个Kafka集群,并向提供者和消费者提供兼容的接口。代理层将逻辑主题呈现给Kafka客户端,并在内部将它们映射到每个Kafka集群中的不同物理主题。在下图中,一个有8个分区(P0-P7)的逻辑主题被分配到两个物理集群,每个集群有4个分区(P0-P3)。

逻辑主题的额外抽象层允许我们实现以下所需的行为。首先,我们可以用很少的(重新)同步开销来扩展数据管道的容量。如果达到最大大小的两个群集无法处理预测的峰值容量,我们可以轻松地部署另外两个群集,而无需调整任何现有数据。其次,较小的群集更易于管理容错,因为我们可以细粒度调配额外容量,并以较低成本重定向流量。最后,在(并不罕见)物理集群迁移事件中,透明代理消除了在应用程序端更改任何代码和配置的需要。我们只需要在旧群集完全排空之前将其设置为只读模式,同时将代理与新群集相关联。从逻辑主题的角度来看,这种维护是不可见的。

在本节中,我们将更详细地介绍我们构建的新组件以及它们在基本场景中如何交互,如下图所示。两个代理服务,一个用于生产者(Pproxy),另一个用于消费者(Cproxy),实现Kafka代理的核心协议。它们还负责将逻辑主题映射到它们的物理化身。应用程序使用相同的Kafka SDK直接连接到代理,代理充当代理。

为了处理这组代理代理,我们构建了一个轻量级名称服务来维护客户机ID和代理服务器集合之间的这种关系。SDK将在通信开始时使用客户端ID请求一次代理代理列表。在内部,我们实现的最复杂、最庞大的部分涉及管理联合集群的元数据,包括主题状态和代理节点的生命周期。我们将Kafka控制器节点的逻辑(如主题元数据)提取到一个单独的服务中,该服务也称为“控制器”,但它不同于Kafka自己的控制器功能。此服务负责收集物理集群的元数据,组成分区信息逻辑主题,然后将其发布给代理代理。

在最常见的操作过程中,我们可以看到这些组件与下面的Kafka集群之间交互的一些示例:

逻辑主题元数据检索1.控制器从配置数据库中读取逻辑主题和物理主题之间的映射。2.Controller扫描每个Kafka集群中所有物理主题的元数据。3.控制器从心跳报文中查找可用的pproxy列表。4.控制器编写逻辑主题的元数据。5.控制器将主题映射和主题元数据都推送到代理代理。6.将元数据发送到Kafka SDK。

群集设置工作流程1.提供一个空群集(群集3),并将其添加到群集1和群集2的现有联合。2.控制器从配置数据库加载从逻辑主题到物理主题的映射。3.控制器从集群3.4的物理主题加载元数据。4.控制器通过合并2的结果来重构元数据,递增版本。5.Controller将新版本发布给Proxy Broker,客户端刷新后SDK可以看到。

群集停用工作流程1.控制器在配置数据库中将群集(群集1)标记为以只读模式停用。2.当控制器从数据库获取元数据时,它会拾取此状态更改。3.控制器重建生产者的元数据,从物理集群中移除集群1。4.控制器将新版本的生产者元数据推送到代理。此时,数据停止写入集群1,而消费端不受影响。5.当集群中的所有主题都过期时,控制器再次重构消费者元数据,并移除不再有效的物理主题。6.消费者代理加载新的元数据,现在当新的消费者到达时,它将不再拾取集群1,这就完成了退役操作。

在过去的一年里,我们在腾讯盈科陆续上了很多产品,使用联合卡夫卡解决方案。除了群集,我们还一直在开发更好的监控和自动化管理工具。我们的设计原则很快就得到了许多关键业务用例的验证,例如实时分析、功能工程等。到目前为止,我们已经部署了几百个大小不一的集群,每天总共处理超过10万亿条消息。下表总结了我们的典型设置和操作基准。

由带有代理层的集群联合组成的第一种设计有两个明显的局限性。首先,逻辑分区的分布对于在生成消息时使用散列键指定分区的客户端是不透明的。因此,当我们添加新集群时,具有相同键的消息可能会被传递到不同的分区,因此顺序会打乱。事实证明,这不是我们当前用例的拦路器,原因有两个。首先,我们调查了产品团队,发现他们只是偶尔使用键控消息。此外,当他们面临应用程序级别的容错和可伸缩性之间的权衡时,他们通常更喜欢后者,有时会采用一种机制,在更新集群成员身份时暂时停止生产。

一个更根本的限制是,随着更多的功能需要公开,以及本机Kafka的发展,我们必须频繁地发展代理代理的接口。这会导致不必要的代码重复,并使整个系统更难管理。将来,我们将探索在Kafka中实现类似的语义,如下一节所述。

正如我们上面解释的,腾讯是全球最大的卡夫卡用户之一,每天处理数万亿条消息。这也意味着,为了支持我们的许多用例,我们已经成功地突破了卡夫卡的一些界限。我们知道Kafka社区内部正在进行的发展和提议,我们进一步发现,我们的一些想法,比如抽象出控制器和跨多个控制器的流量分片,与社区正在走向的方向是一致的。如果我们的联合解决方案与分层存储(KIP-405)和动物园管理员移除(KIP-500)等新功能集成,我们可能会看到显著的好处,我们期待着做出已经证明的贡献,帮助腾讯重返社区。

在本文中,我们将介绍为需要高可伸缩性和容错能力的业务用例构建联合Kafka集群的过程。通过强大的工程解决方案和运营投入,我们正在弥合差距,支持腾讯盈科的持续增长。我们的经验使我们对卡夫卡生态系统恢复了信心,并阐明了我们如何进一步扩展其能力。我们将继续沿着这个方向发展。

如果您想了解更多关于Kafka和活动流的信息,请查看Confluent Developer,找到最大的入门资源集合,包括端到端的Kafka教程、视频、演示、Meetup、播客等。

肯威·陈(Kenway Chen)是腾讯盈科(Tencent PCG)的技术主管和工程经理。他有10多年构建大规模分布式系统、应用程序和数据管道的经验。肯威为腾讯的许多基础技术做出了贡献,例如开源服务框架TARS及其消息队列。他还是Java应用程序、数据库查询引擎和微服务框架领域的专家。

卡恩·陈(Kahn Chen)是腾讯盈科(Tencent PCG)的高级工程师。他在数据基础设施和应用程序方面有七年的工作经验。具体地说,Kahn专注于消息传递平台和实时数据处理框架。

George Shu是腾讯盈科的总经理,负责其数据基础设施和平台,并支持所有产品和业务。他拥有10多年构建大型后端系统、机器学习基础设施和商业智能平台的经验。