跳到主要内容

多区域 LLM 服务:没人警告过你的缓存局部性问题

· 阅读需 12 分钟
Tian Pan
Software Engineer

当你在多个区域运行无状态 HTTP API 时,路由问题基本上已经解决了。在前面放一个全球负载均衡器,按地理位置分配请求,最糟糕的情况也不过是缓存项稍微过时。任何副本都可以处理任何请求,并获得相同的结果。

LLM 推理打破了每一个假设。一旦你添加了提示词缓存(Prompt Caching)——你肯定会加,因为缓存命中和未命中的成本差异大约是 10 倍——你的服务就会以大多数基础设施团队预料不到的方式变得有状态,直到他们在第二个区域看到延迟数据退化。

根本原因在于 KV 缓存局部性(KV cache locality)。当语言模型处理提示词时,它会为该提示词中的每个 token 计算键值张量(key-value tensors)并将其存储在 GPU 显存中。下一个与缓存提示词共享前缀的请求可以跳过重新计算这些张量——但前提是该请求落在了持有该缓存的同一个 GPU 节点上。跨区域路由不仅仅是导致缓存未命中,它会让缓存变得像从未存在过一样。

为什么多区域 LLM 服务不同于多区域 API

考虑一下当你给一个调优良好的单区域 LLM 部署添加第二个区域时会发生什么。在区域 A,你通过重复的系统提示词、共享的对话前缀以及附加在大多数请求前的 RAG 上下文分块,建立起了温缓存(warm caches)。你的缓存命中率维持在 60–70%。区域 A 的用户看到的延迟始终保持在低水平。

区域 B 启动时是冷启动。每个请求都是全上下文重新计算。延迟飙升。你增加了更多的 GPU。成本上升。你告诉自己过几天就会变暖,确实如此——但现在你遇到了新问题。你的全球负载均衡器在执行感性操作时,偶尔会因为区域 A 负载过重而将区域 A 用户的请求路由到区域 B。该请求命中了冷缓存,你会在 P95 指标中看到延迟飙升。你根据用户 ID 添加了粘性会话(sticky sessions)。延迟恢复正常。一周后,你意识到按用户 ID 建立粘性会话意味着你的负载分布不均,因为某些用户产生的流量是其他人的 10 倍。

这就是模式。每一次修复都会揭示下一个问题,而且它们都不是代码中的 bug——它们是无状态基础设施假设与有状态推理需求之间的架构不匹配。

KV 缓存是你真正的状态单元

在传统的分布式系统中,状态存在于数据库中。你在无状态计算和有状态存储之间有明确的分离。扩缩容是可预测的。

在 LLM 服务中,KV 缓存驻留在运行预填充(prefill)阶段的 GPU 上。它与产生它的计算任务位于同一位置,在内存压力下会被逐出且没有持久记录,并且没有用于外部检查的 API。发送到两个不同节点的两个相同请求会导致两次缓存未命中,尽管从系统设计的角度来看,“正确”的行为应该是共享该计算结果。

这与在其他地方都行之有效的扩缩容策略产生了根本性的冲突。轮询(Round-robin)负载均衡对无状态服务是正确的,但对带缓存的 LLM 推理却是有害的。每一个没有落在具有匹配前缀节点上的请求都要支付完整的预填充成本。在大规模场景下,长系统提示词的预填充可能需要数百毫秒,这不仅仅是一个小小的效率问题——它是 P50 延迟 80ms 与 800ms 之间的区别。

实际后果是:你的负载均衡器需要了解 KV 缓存状态,而不仅仅是节点健康状况和队列深度。通用的 HTTP 负载均衡器没有这些信息。这就是为什么会出现像 vLLM Router 这种专用路由器的原因——它用 Rust 编写以最小化开销,并专门设计用于消费来自推理引擎的 KV 缓存事件。它们基于前缀哈希匹配进行路由,而不仅仅是轮询或最小连接数。

基于前缀的一致性哈希是单区域部署的正确默认选择。你对提示词的前 N 个 token 进行哈希处理,将该哈希映射到一个节点,并进行相应路由。添加有界负载约束,使单个节点不会过载,这样你就拥有了一个合理的稳定状态。经过研究支持的实现方案是有界负载一致性哈希(CHWBL),它是专门为这个问题设计的。

数据驻留要求打破了你的缓存优化

如果你为欧盟用户提供服务,你最终会遇到数据驻留(Data Residency)要求。最简单的版本是:用户数据不得在欧盟以外处理。更严格的版本——随着组织对云服务商管辖权变得更加谨慎而变得越来越普遍——是数据甚至不能经过总部位于美国的提供商基础设施,因为可能存在《云法案》(CLOUD Act)的风险。

此时,架构上的张力变成了真正的冲突。当缓存预热的请求留在同一个节点或同一个区域集群时,提示词缓存最为有效。但数据驻留要求欧盟用户的数据永远不能离开欧盟区域。这两个约束单独来看都是可以满足的。但结合在一起,这意味着你不能根据缓存可用性来路由欧盟流量——你只能在欧盟部署内路由它。

结果是:你的欧盟区域拥有的缓存池比你的全球区域小,仅此而已。如果你的欧盟用户群较小,缓存预热速度就会较慢。如果欧盟用户具有多样化的查询模式和冗长的、独特的系统提示词,命中率可能会永久保持在低水平。你在欧盟支付的单 token 成本将高于你的主要区域,这不是因为基础设施定价差异,而是因为你的缓存架构受到了合规性的限制。

摆脱这一困境的唯一方法是对欧盟数据停止依赖云托管的 LLM 推理。可以在单个本地服务器上运行的小型模型完全避免了多区域问题——如果只有一个区域,就不存在跨区域路由。这是一个现实的权衡,那些做出“进军欧盟”决策的团队往往只有在围绕云 API 构建了缓存策略之后才会发现这一点。

模型权重同步与版本偏差

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates