Roblox 的缓存如何突破 Redis 限制,实现 13.8 亿 QPS
以可靠性和效率为重,应对流量激增10倍的挑战

在 Roblox 的海量多人在线游戏环境中,用户读写数据的规模和速度之大,足以让标准缓存模式不堪重负。 在缓存静态数据的标准网页上,用户可能不会察觉 200 毫秒的延迟;但在 Roblox 上,若检索交互数据或服务器元数据时出现 200 毫秒的延迟,则可能导致游戏卡顿并破坏模拟的游戏世界。Roblox 运行于一个充满不可预测、高速且瞬息万变的数据生态系统中,为保持沉浸感,这些数据必须在毫秒级内完成检索。
我们的缓存层旨在作为数百万并发用户与持久化存储之间的大型缓冲器。它能够处理每秒高达 13.8 亿次查询(QPS)的峰值负载,单个逻辑集群的查询量甚至超过 1 亿 QPS。 在本文中,我们将揭秘如何构建联邦缓存服务,使其突破 Redis® 节点限制以实现海量吞吐量,同时应对我们最大集群上史无前例的 10 倍流量激增。

突破行业极限,满足不断增长的需求
在 Roblox,我们的缓存服务基于 Redis® 技术构建,一个 Redis® 集群理论上可支持多达 1,000 个节点。然而,经验和业界公认的极限要低得多——大约在 400–500 个节点之间。1 这是因为 Redis® 采用了去中心化的 Gossip 协议,该协议通过节点间通信来共享健康状态、运行状态和分片映射信息。 在节点数超过几百的集群中,Gossip 协议产生的通信流量开始消耗大量的 CPU 和网络资源。每个节点必须处理来自数量不断增长的对等节点的状态更新,这会占用本应用于低延迟数据服务的核心资源。这种控制平面开销可能导致系统不稳定和性能不可预测,这也是托管云服务商强制实施节点限制的原因。这是一个实际的上限,若要突破该限制,就必须牺牲可靠性。
这一单集群的实际限制无法满足 Roblox 级别的平台需求。在 Roblox 平台上,最大的后端服务在高峰期曾要求我们其中一个逻辑 Redis® 集群处理超过 1 亿 QPS,而这一需求在短短三个月内就从 1000 万激增至此。
为突破这一架构限制,我们采用了联邦架构,在多个较小且独立的 Redis® 集群前部署了客户端反向代理。我们为每个集群设定 400 个节点的上限,以确保性能可预测。
对于我们成千上万的应用程序和服务而言,客户端反向代理将这些分散的集群呈现为一个统一且可扩展的缓存服务。这种联合架构使我们能够通过简单地向联合体中添加更多集群来实现几乎无限的水平扩展,从而完全绕过了 Gossip 协议的限制。 目前,我们最大的单个缓存部署包含超过 6,000 个 Redis® 节点,这些节点由 15 个以上的独立 Redis® 集群提供支持——这种规模的实现完全得益于这种联邦模型。

三阶段迁移流程
在管理数百个活跃生产集群的同时,从传统架构迁移至联合架构是一项重大工程。截至2024年底,其中许多集群已接近我们400节点的上限,迫切需要向更高容量的模型过渡。主要挑战在于,标准的Redis®实例是孤立运行的,且无法感知其他集群,这要求我们在迁移过程中采用定制方法来复制数据。
为解决这一问题,我们开发了一条透明的三阶段迁移管道,旨在实现服务迁移,且无需客户参与或进行应用端更改。
迁移工作流
- 双重写入:我们配置了客户端反向代理以执行双重写入,将传入数据同时发送至原始集群和新的联合目标集群。
- 数据一致性与读取切换:当双写入过程将相同数据填充到新集群后,由于所有数据都受生存时间 (TTL) 限制,我们将读取流量从旧集群切换到了新的联合架构。
- 退役:在确认新集群稳定运行后,我们停止了所有对原始集群的写入操作,并将其退役。
我们成功将最关键的服务迁移至支持超过 6,000 个节点的联合架构,这远超单个 Redis® 集群的限制。
应对“Grow a Garden”的爆发式增长
从 2025 年 4 月开始,我们面临着罕见的服务容量挑战。其导火索是《Grow a Garden》的惊人成功。上线仅数周,《Grow a Garden》不仅打破了 Roblox 的纪录,更刷新了游戏行业同时在线用户(CCU)的历史最高纪录。 短短三个月内,该游戏的用户量就突破了我们此前280万玩家的单款游戏CCU纪录,达到超过2100万的峰值。这种爆炸性增长使我们最大的Redis®集群流量增加了10倍,整体缓存流量增加了3倍。
Roblox 在自有数据中心的物理服务器上运行缓存系统,而这种前所未有的增长并未包含在我们的长期容量规划中。为了抵御这股汹涌浪潮并保持平台稳定,我们必须在优先保障可靠性的同时,大幅提升现有服务器集群的效率。
在流量激增期间提升效率
首先,我们需要识别系统中影响最大的瓶颈,以便优先进行优化工作。Roblox Caching 运行在两个不同的硬件池上:一个用于 Redis® 后端节点,另一个用于 Envoy。我们的 Redis® 集群主要受内存限制,而客户端代理则受计算能力限制。
针对受内存限制的 Redis® 集群,我们实施了一项新的调度策略,以更好地平衡各物理机组之间的内存利用率。此外,我们还对容器大小进行了微调,以减少内存碎片。
为提升 CPU 利用率,我们在缓存系统中实施了两项关键优化:
- 客户端代理自动扩展:我们调整了计算密集型客户端代理集群的自动扩展策略。通过降低目标 CPU 值的允许偏差,我们在不改变纵向扩展阈值的情况下,实现了更高的工作负载平均 CPU 利用率。
- 内部集群健康检查:我们优化了内部健康检查机制,消除了不必要的心跳检测,在保持原有检测间隔的同时节省了计算资源。
这些调整使 CPU 利用率提升了近 10%。最后,我们利用 cgroup 容器级隔离技术,将这两种截然不同的工作负载部署在同一机器池中,从而将整体容量需求降低了 25%。
致力于打造坚如磐石的可靠性
即使在全力应对创纪录需求的过程中,可靠性依然是我们首要的优先事项。
端到端可观测性
我们首先致力于理解潜在故障,为此在可观测性架构上投入了大量资源,以实现对缓存系统的全面端到端健康监测。通过追踪整个请求生命周期中的服务器成功情况和客户端故障,我们能够快速检测并诊断问题,往往能在影响用户之前就采取措施。 例如,我们新增了热键检测功能,该功能通过采样实时流量来识别被过度访问并给缓存层带来压力的数据。当系统标记出热键时,我们可以在服务器和客户端两端主动对这些键的流量进行限流,从而防止系统过载。
故障处理
在如此规模的分布式系统中,局部故障时有发生。我们对系统进行了专门设计,以优雅地处理这些故障并将其影响降至最低。
- 批量请求中的局部故障:我们重构了系统架构,以处理批量请求中的局部故障。此前,在分片批量请求中,单个请求失败会导致整个批次失败。现在,即使部分键的检索失败,其余请求仍可成功。
- 缓解队首阻塞:缓存系统理应快速响应。即使是轻微的网络延迟,也可能导致请求堆积并超时,这种现象被称为队首阻塞。我们在客户端和代理层都实现了智能重试机制和连接池策略,以防止单个慢速请求影响其他请求。
- 故障与延迟注入:为测试系统韧性,我们定期利用故障注入框架向生产环境注入受控故障(节点故障、机架故障、网络延迟、API 错误)。通过分析系统在这些条件下的行为,我们能够主动识别并修复薄弱环节,确保系统的持续可靠性。
客户端弹性
为防止缓存系统因流量突增而过载,我们实现了强大的客户端故障恢复机制。该机制在应用层运行,确保任何单一服务都无法独占缓存资源。
- 流量控制限流:客户端对总出站流量设有上限,确保其发送的请求不会超过后端服务可处理的范围。当超过此限额时,请求将被限流,从而防止服务过载。
- 重试与超时机制:我们的客户端库采用经过精细调优的重试机制,包括超时设置和重试配额,以防止“雷霆之群”问题。这能限制故障影响范围,释放资源,并通过防止无限期卡顿和同时重试导致系统过载,从而提升整体系统响应能力。

Roblox 缓存的未来
Roblox 的缓存之旅始于由各应用程序所有者直接管理的裸机 Redis® 集群,随后过渡到由我们的缓存团队管理的 Memcached 集群,最终转变为 Redis® 即服务(Redis®-as-a-service)模式,即以托管服务的形式提供 Redis® 集群。 尽管该模式在当前规模下已证明非常有效,但我们意识到,对于像 Roblox 这样动态的平台而言,它在服务效率和资源隔离方面仍存在局限性。
随着平台的持续发展,我们计划对基于 ValKey 构建的下一代多租户缓存服务进行重大投资。该架构旨在通过多租户模式共享公共资源来大幅降低成本,同时确保每个租户的数据、资源及故障隔离。我们的目标是显著提升缓存基础设施的性能、可扩展性、可靠性和成本效益,以满足 Roblox 上日益庞大的体验需求。
致谢:
这一成就源于团队的通力合作。感谢以下为项目做出重大贡献的团队成员:Utkarsh Singh、Karthick Ramachandran、Vineesha Kasireddy、Weiji Hu 和 Leon Gao。
1AWS 将 ElasticCache 限制为 500 个节点。
*Redis 是 Redis Labs Ltd. 的注册商标。Redis Labs Ltd. 保留其中所有权利。


