当前位置: 首页 > 科技观察

Hulu如何扩展InfluxDB以支持每秒百万级TPS

时间:2023-03-12 10:19:22 科技观察

简介:InfluxDB是最常用的时序数据库之一,其开源版本被广泛使用。但是,其开源版本缺少一些与高可用性相关的功能。本文介绍Hulu在使用InfluxDB过程中遇到的问题及解决方法。值得一读。随着Hulu的不断发展,时序数据库已成为公司监控系统的重要组成部分。这可以像机器性能指标或来自应用程序本身的数据一样简单。由于我们拥有的数据量很大,因此创建支持冗余和可扩展性的架构至关重要。为什么时间序列数据很重要?时间序列数据使我们能够评估趋势,从而发现问题并采取行动。下图用于识别影响在特定数据中心运行的应用程序版本的最近内存泄漏。GraphiteArchitecture最初,每个开发团队都有自己的时间序列数据解决方案。由于大多数团队都有类似的需求,这种情况绝对是一种资源浪费。为了解决这个问题,我们构建了原始时序数据管道,它为整个工程团队提供了一个时序数据库。管道基于Graphite并将数据存储到OpenTSDB。在其高峰期,Graphite集群的吞吐量为每秒140万个指标。在维护这个过程的同时,我们遇到了一些随着我们继续发展而变得更加普遍的问题。其中许多问题源于在Hulu的所有开发团队中提供数据管道共享服务,这需要支持巨大的吞吐量和基数,而其他问题则源于固有的可扩展性问题。数据管道挑战消费者经常无意中在其标准命名空间中发送唯一数据,例如时间戳或其他唯一标识符。例如:stats.application.dc1.1557471341.count11557471341stats.application.dc1.1557471345.count11557471345stats.application.dc1.1557471346.count11557471346这导致命名空间中的基数激增,影响了摄取速度和整体管道稳定性。虽然可以防止这些行为,但这样做非常困难,因为需要在不影响合法指标的情况下匹配有问题的指标。由于吞吐量限制,我们可以创建的规则的复杂性和数量受到限制,因为必须针对收到的每个指标评估所有规则。这需要在与度量数据接触的节点一样多的节点上以滚动方式完成。因此通常很少添加条件来阻止有问题的指标,通常首选阻止应用程序发送指标。不幸的是,在大多数情况下,花费的时间会导致数据丢失。在检索数据时,许多用户无意中运行了长时间或资源密集型查询,最终导致为他们提供数据的后端超时并崩溃。没有任何限制可以阻止这种行为,这也影响了整个系统的稳定性。发送的指标也有问题。由于格式未标准化,因此要确定哪个服务正在发送特定指标需要大量猜测,而且在我们实际需要时非常困难。最后,由于我们的设置,所有指标都被发送到两个数据中心之一。如果发生故障,整个数据中心的指标将无法访问。此外,由于我们只有一个统一的接口来检索这些指标,因此我们更喜欢一个数据中心。这是有问题的,因为如果用户将指标发送到第一优先级数据中心,但随后决定使用另一个数据中心,他们将无法访问他们的新指标,因为命名空间已经存在于第一个数据中心,从而导致问题。InfluxDB初始架构为了解决这些问题,我们决定基于InfluxDB从头开始重建统计管道。对于我们的第一次尝试,我们创建了两个集群,在两个主要数据中心(DC1和DC2)中各有一个。两个集群将包含相同的数据。一个指标中继集群建立在这个之上。所有指标都将发送到中继集群。该集群的唯一目的是将接收到的所有指标推送到两个InfluxDB集群中。这允许从任何数据中心检索所有指标,完全消除了Graphite架构中遇到的指标可用性问题。我们在每个数据中心都有指标中继层。在这个指标中继层之上,我们还实现了必需的标签,这是Hulu中每个应用程序的唯一标识符。这使我们能够轻松地追溯每个指标的来源。没有此必需标签的任何指标都将被删除。所有Hulu机器都运行Telegraf守护程序(https://github.com/influxdata/telegraf)。我们已将守护程序配置为报告所有机器统计信息并监听本地主机上的指标。我们鼓励所有开发人员将指标发送到本地主机,因为我们已将Telegraf配置为自动将标准标签添加到它接收的所有指标。这些标签包括原始数据中心、计算机名称和计算机ID。此设置效果很好。我们已经测试了每秒超过200万个指标的吞吐量,没有任何问题。然而,我们很快遇到了一个问题,导致我们重新评估当前的设置。具体来说,我们的一个集群在一段时间内不可用,导致所有指标仅被推送到一个(在线)数据中心,然后在被复制到另一个集群之前被丢弃。一旦有问题的集群再次可用,数据就会发生分歧,需要手动重新同步集群。我们意识到我们需要一种方法来更优雅地解决此类问题并减少人工干预。InfluxDB改进的架构我们在设计中创建了两个新层,其中包括每个数据中心内的Kafka队列,以及一个InfluxDB编写器层来解决这个问题。指标仍然发送到原始中继集群,但不再从那里直接路由到InfluxDB集群。相反,它被发送到数据中心内的Kafka队列。InfluxDB写入层在InfluxDB集群所在的每个数据中心创建。该层的唯一目的是连接到所有数据中心的Kafka队列,并将它们写入本地InfluxDB集群。如果其中一个InfluxDB集群出现故障,该数据中心的写入程序将停止写入该集群,但另一个数据中心将继续提取其指标。一旦有问题的集群重新联机,该数据中心的写入器将继续工作并写入本地集群。最终两个集群将再次处于一致状态。这种设计还允许我们完全禁用大部分基础设施(甚至整个数据中心)并将它们路由到另一个数据中心而不影响最终用户。虽然这种设计解决了我们的许多问题,但仍然存在两个问题。查询限制我们仍然遇到长时间运行的查询或有问题的查询的问题。消费者有时会进行很长的查询(通常是偶然的),这会导致其他用户使用时性能下降。为此,我们创建了一个新的微服务InfluxImposer。该应用程序登录到我们的两个InfluxDB集群并每分钟检查一次正在运行的查询。如果它超过某个阈值(比如60秒)或者是危险/资源密集型查询,则将其杀死。我们还实现了终止查询的日志记录,并大大提高了系统稳定性。阻止/过滤“不良”指标消费者可能仍会在命名空间中发送带时间戳的指标,或发送一些可能导致数据集基数非常高的数据。为了解决这个特定问题,我们创建了另一个名为Barricade的微服务。Barricade是一个数据库支持的API,包含动态黑名单。如果在任何时候需要将标签、指标或几乎任何其他信息列入黑名单,它将被添加到该数据库中。数据库更改将同步到InfluxDBwriter上的所有本地配置。这些机器不断轮询Barricade以获取其更新的黑名单规则。如果检测到更改,编写器将重新生成其本地备用配置。在InfluxDBwriter层这样做的原因是该层的任何更改都不会破坏指标获取,因此添加新的黑名单对上层查询没有影响。时间序列数据已经并将继续成为Hulu评估和响应趋势能力的重要组成部分。我们能够解决之前管道中的所有问题,现在正在将所有用户从旧平台上移走。在撰写本文时,我们的新统计数据流已经每秒处理超过一百万个指标,而且这个数字每天都在增长。