为什么Discord放弃了Redis并重新在Kubernetes上构建搜索功能

无论是Netflix的“Java秘密”还是Uber使用Kubernetes,支撑这些全球个人和企业广泛使用的热门平台背后的高科技,始终是一个值得关注的焦点。

对于Discord而言,其于2017年基于Elasticsearch构建的高性能系统,最终在公司快速增长的巨大压力下崩溃,迫使工程团队彻底重新设计搜索架构。

当成功成为问题

多年来,Discord的即时通讯系统一直高效地运行在Elasticsearch集群上。这些集群为每个Discord服务器和直接消息流分配独立的分片进行消息存储。然而,随着平台规模的扩大,一些根本性限制开始显现,这些问题无法通过渐进式改进来解决。

Discord 的原始搜索基础设施基于扎实的工程原则设计,但即使是最周密的计划也可能在指数级增长面前崩溃。最初在早期阶段表现优异的 Redis 支持的消息索引队列,随着消息量激增成为关键的故障点。

“当我们的索引队列因任何原因出现堵塞时——这在 Elasticsearch 节点故障时经常发生——Redis 集群便成为故障源,一旦 CPU 因队列中消息过多而达到峰值,便开始丢失消息,”Discord 团队在一篇博客文章中解释道。

最初为性能优化而设计的批量索引策略,在规模化后产生了意想不到的漏洞。来自不同索引和节点的消息批量处理导致了相互关联的故障。因此,单个节点的故障可能严重扰乱大量操作。

“如果一个节点故障,假设分布均匀,某个批次中至少有一条消息发送到该故障节点的概率约为40%。这意味着单个节点故障会导致约40%的批量索引操作失败!”Discord团队在博客中强调。

该公司解释称,系统规模庞大且脆弱,导致关键维护工作几乎无法进行。无法执行滚动重启或软件升级意味着Discord被迫运行过时版本,既错失安全补丁也无法获得性能提升。如博客所述,log4shell漏洞补丁要求搜索系统离线进行维护。在此期间,所有Elasticsearch节点均以更新配置重新启动。

Kubernetes的熟悉度

尽管Discord已在Kubernetes上成功运行无状态服务,但搜索基础设施代表了其首次重大有状态工作负载迁移。该公司发现,Elastic Kubernetes Operator提供了管理大规模复杂Elasticsearch部署的编排能力。

“借助 Elasticsearch Operator,我们能够轻松定义集群拓扑和配置,并将 Elasticsearch 集群部署到我们的 Kubernetes 节点池中,”博客文章中提到。

Kubernetes 带来了立竿见影的运营优势,解决了 Discord 的许多痛点——操作系统升级变得自动化,滚动重启可安全执行,而细粒度的资源分配有助于优化成本。

更重要的是,它使Discord能够实现其多集群“单元”架构,其中较小、更易于管理的Elasticsearch集群可以独立部署和管理。

单元架构与传统的单体集群方法完全不同。Discord不再管理超过 200 个大型节点集群,而是运营 40 个较小的集群,这些集群被组织成逻辑单元。单元内的每个集群运行具有特定角色专用节点类型,确保主节点候选节点拥有足够的资源进行协调。同时,摄入节点可以动态扩展以处理流量峰值。

索引数万亿条消息

从 Redis 迁移到 Pub/Sub 用于消息队列解决了消息丢失问题,同时启用了更复杂的路由策略。Discord 实现了一个消息路由器,该路由器智能地按目标集群和索引批量处理消息,确保批量操作保持隔离并能够抵御单个节点故障。

这种架构灵活性解锁了此前无法实现的新搜索功能。跨消息搜索,这一长期以来被请求的功能,现在变得可行。

对于Discord最大的社区(被称为“Big Freaking Guilds”或BFGs),新架构提供了专用资源和多分片索引来处理数十亿条消息。这些特殊案例拥有自己的Elasticsearch单元和优化配置,确保大型公会不会影响小型社区的性能,同时仍能提供快速搜索能力。

这些变更带来了显著的改进,例如索引吞吐量提升了两倍,查询延迟从中位数500毫秒大幅降至100毫秒以下,且集群升级实现无缝进行,完全不会造成服务中断。

此次转型成果充分展现了精心规划的基础设施演进的强大效能。Discord现已能够处理数万亿条消息,各项性能指标全面提升,同时仍保持处理边际案例和应对未来增长的灵活性。

你也许感兴趣的:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注