AIBrix Cache 缓存包深入解析:Pod 元数据、模型路由与 KV 事件同步
【免费下载链接】aibrixCost-efficient and pluggable Infrastructure components for GenAI inference项目地址: https://gitcode.com/GitHub_Trending/ai/aibrix
导读
AIBrix 的pkg/cache包是整个 LLM 推理系统的"中枢神经",它以内存缓存为核心,向上为 Envoy Gateway 插件与各类路由算法提供 Pod 可用性、负载、前缀缓存命中率等实时决策数据,向下通过 Kubernetes Informer 与 ZMQ 事件流打通 vLLM Pod 的 KV Cache 变更。本文以 pkg/cache/README.md 为骨架,结合源码逐层剖析其缓存存储、请求追踪、输出预测、GPU Profile 与 KV 事件同步的实现原理,并给出完整的配置项与可运行示例,帮助你掌握 AIBrix 路由决策的数据基础。
一、Cache 包定位:路由决策的数据中枢
AIBrix 的网关插件在每次请求路由前,都需要回答几个关键问题:某个模型当前有哪些可用 Pod?哪个 Pod 负载最低?哪些 Pod 的前缀缓存命中率最高?目标 Pod 的 GPU 利用率如何?pkg/cache正是为回答这些问题而设计的集中式缓存与路由支撑组件。
从 cache_api.go 可以看到,Cache是一个聚合接口,它嵌入了 8 个子接口:
type Cache interface { PodCache ModelCache MetricCache RequestTracker RequestTrackerRegistry ProfileCache types.OutputPredictorProvider types.RouterProvider }这从结构上决定了缓存包的五大核心职责:
| 能力 | 接口 | 说明 |
|---|---|---|
| Pod 与模型元数据缓存 | PodCache/ModelCache | 按 Pod 查模型、按模型查 Pod,以及 LoRA 适配器与基础模型的映射 |
| 请求路由与负载追踪 | MetricCache/RequestTracker | Pod 指标查询、跨网关运行中请求数统计、请求生命周期追踪 |
| KV 缓存事件同步 | 事件管道 + 前缀索引器 | vLLM Pod 的 KV 块事件经 ZMQ 同步进前缀缓存索引器 |
| GPU Profile 管理 | ProfileCache | 按 Pod / 按 Deployment 查询模型 GPU 画像 |
| 输出预测 | OutputPredictorProvider | 基于历史滑窗预测请求的输出 token 数 |
二、核心组件:Store 与它的存储结构
2.1 Store:全局单例缓存仓库
Store是缓存包的中心数据结构,定义于 cache_init.go。它采用全局单例 +sync.Once初始化的模式(cache_init.go):
var ( store = &Store{} // Global cache store instance once sync.Once // Singleton pattern control lock )Store内部的核心字段包括:
- Pod 存储:
metaPods(SyncMap[string, *Pod]),以namespace/name为键,存放所有被发现的 Pod;recentlyDeletedPods保存刚删除 Pod 的实时计数器快照,支持 Pod 快速重建后恢复请求追踪计数而不是从零开始。 - 模型存储:
metaModels(模型名 →*Model);modelClaims单独存放不可路由(端口为 0)的 ModelClaim 广播状态,避免污染正常路由。 - Deployment 画像:
deploymentProfiles,键为aibrix:profile_[model_name]_[deployment_name]。 - KV 同步:
syncPrefixIndexer(仅在启用 KV 同步时创建)与kvEventManager。 - 运行时统计:
enableTracing(是否开启 GPU Optimizer 追踪)、podMetricsWorkerCount与podMetricsJobs组成的 Pod 指标更新 worker 池、requestTrackers注册的请求追踪器列表。
2.2 初始化流程与三类服务身份
InitWithOptions 是生产环境的统一入口,它通过InitOptions判断当前调用方身份,从而决定启用哪些能力:
type InitOptions struct { IsGateway bool // 标记调用方为 gateway-plugins 服务 EnableKVSync bool // 是否启动 ZMQ KV 事件同步 RedisClient *redis.Client // KV 同步等特性必需 ModelRouterProvider ModelRouterProviderFunc // 仅网关需要 DiscoveryProvider discovery.Provider // 服务发现 Provider,默认为 Kubernetes Informer }根据serviceIdentity(cache_init.go)的判断逻辑:
- gateway:
IsGateway=true,启用追踪与 GPU Profile 缓存,支撑路由; - metadata:有 RedisClient 但非网关,关闭 GPU Optimizer 追踪与 Profile 缓存;
- controllers:其余场景,同样关闭追踪与 Profile 缓存。
初始化时若EnableKVSync=true但RedisClient为 nil,会直接klog.Fatalf退出——这是硬性依赖校验。此外,初始化还会视 Redis 可用性启动网关快照同步(initGatewaySnapshotSync)与运行中请求活性心跳(initRunningRequestsLiveness),后者用于跨网关精确统计每个 Pod 当前在途请求数。
2.3 服务发现:Kubernetes Informer 与可插拔 Provider
缓存数据从何而来?答案是服务发现层。所有 Pod / ModelAdapter 的增删改事件都通过统一的discovery.Provider接口进入缓存(cache_init.go):
provider := opts.DiscoveryProvider if provider == nil { // Default: Kubernetes informer-based discovery provider = discovery.NewKubernetesProvider(config) }discovery子包(pkg/cache/discovery)提供了两种开箱即用的 Provider:
- Kubernetes Provider:基于 Informer 监听 Pod 生命周期与 ModelAdapter 资源,对应 kubernetes.go;
- Static Provider:用于独立/开发模式,无需 Kubernetes,对应 static.go,另有 static_test.go 验证其行为。
事件进入handleDiscoveryObject后被分派到addPod/updatePod/deletePod/addModelAdapter等内部方法,完成内存索引的维护。informers.go中注册的 Informer 则负责监听 Pod 生命周期事件、ModelAdapter 资源与配置更新。
三、KV 缓存事件同步:从 vLLM Pod 到前缀索引器
KV 事件同步是pkg/cache最具特色的能力:它让网关能实时感知每个 vLLM Pod 中 KV Cache 块的存储与移除,从而在路由时优先选择前缀缓存命中率高的 Pod,显著降低 TTFT(首 token 延迟)。
3.1 事件链路全景
README 中给出了完整的五步事件流:
- Pod Discovery:缓存监听带有 KV 事件标签的 Pod;
- Subscription:事件管理器为符合条件的 Pod 创建 ZMQ 客户端;
- Event Processing:进入的事件更新前缀缓存索引器;
- Query Routing:路由器向索引器查询前缀匹配;
- Request Dispatch:请求被路由到具有匹配前缀的 Pod。
3.2 KVEventManager:带构建标签的双实现
KVEventManager是同步的入口,它通过Go build tags区分两种实现:
- 非 ZMQ 构建(默认):kv_event_manager.go 中是一个 stub,
validateConfiguration()直接返回"需要-tags=zmq构建"的错误,所有OnPodAdd/Update/Delete均为空操作; - ZMQ 构建(
-tags=zmq):kv_event_manager_zmq.go 中它内嵌了*kvevent.Manager,通过NewStoreProviderAdapter(store)将 Store 适配为 Pod Provider 与同步 Provider,复用 pkg/kvevent 的完整事件管理器实现。
其配置校验(validateKVEventConfiguration,见 kv_event_manager_zmq.go)揭示了启用 KV 同步的四项硬性前提:
| 环境变量 | 要求 | 说明 |
|---|---|---|
AIBRIX_PREFIX_CACHE_KV_EVENT_SYNC_ENABLED | true | 总开关 |
AIBRIX_PREFIX_CACHE_USE_REMOTE_TOKENIZER | true | 必须启用远程 tokenizer |
AIBRIX_PREFIX_CACHE_TOKENIZER_TYPE | remote | tokenizer 类型必须为 remote |
AIBRIX_PREFIX_CACHE_REMOTE_TOKENIZER_ENDPOINT | 非空 | 远程 tokenizer 服务地址 |
在 initKVEventSync 中,Store 依次执行:读取开关 → 校验配置 → 创建事件管理器 → 创建共享的单例SyncPrefixHashTable(syncindexer.GetSharedSyncPrefixHashTable)→ 启动管理器。注意:清理时(cleanupKVEventSync)不会关闭共享索引器单例,因为它可能仍被网关路由器等其他组件使用,其生命周期由全局统一管理。
3.3 底层传输:ZMQ 客户端与 MessagePack 编解码
KV 事件的实际收发由 pkg/cache/kvcache 子包承担,其 README(kvcache/README.md)描述了三个关键组件:
ZMQ 客户端(zmq_client.go)——连接 vLLM Pod 并订阅 KV 事件流,具备指数退避自动重连、事件回放(Replay)、序号追踪检测漏事件、可配置超时与缓冲区等可靠性特性:
config := &ZMQClientConfig{ PodName: "vllm-pod-1", PodIP: "10.0.0.1", PubPort: 5557, RouterPort: 5558, PollTimeout: 100 * time.Millisecond, } client := NewZMQClient(config, handler) go client.Start(ctx)事件类型(event_types.go):BlockStoredEvent(新 KV 块存储)、BlockRemovedEvent(块被移除)、AllBlocksClearedEvent(全部块清空),对应事件处理器中"block stored/removed"的分发逻辑。
MessagePack 编解码器(msgpack_encoder.go 与 msgpack_decoder.go):对事件批量序列化,降低网络传输开销:
data, err := EncodeEventBatch(eventBatch) // 编码 events, err := DecodeEventBatch(data, modelName, podName) // 解码依赖github.com/pebbe/zmq4(ZMQ Go 绑定)、github.com/vmihailenco/msgpack/v5,系统需安装 libzmq3 或更高版本。
3.4 事件处理器与多模型部署
事件处理器将收到的 KV 事件路由到合适的索引器,处理块存储/移除事件,并维护 Pod 重启后的一致性。事件管理器支持自动 Pod 发现与订阅、生命周期管理(增/改/删)以及多模型部署——同一 Pod 可为多个模型服务,其 KV 事件按模型维度落入对应索引。
四、请求追踪与输出预测
4.1 RequestTrace:单请求全链路数据
RequestTrace 记录单个请求在系统中的完整轨迹:请求耗时与延迟、token 数与模型信息、GPU 利用率指标。Store 以model_name -> *RequestTrace的映射保存(requestTrace字段),并通过RequestTracker接口对外暴露。
RequestTracker接口(cache_api.go)定义了三阶段契约:
AddRequestCount(ctx, requestID, modelName):路由后记录请求开始,返回traceTerm(追踪期标识);可被多次调用,实现必须保证线程安全与幂等;DoneRequestCount(...):记录无 usage 信息的请求完成;DoneRequestTrace(...):记录带 inputTokens / outputTokens 的请求完成。
由于AddRequestCount的 ctx 可能为 nil(如请求在路由完成前被取消),所有实现都必须对 nil ctx 做防护。RequestTrackerRegistry允许多个 tracker 按注册顺序依次被调用,便于扩展自定义追踪器。追踪数据启用后,initTraceCache(cache_init.go)会按固定周期(RequestTraceWriteInterval)将窗口内轨迹批量写入 Redis 存储。
4.2 OutputPredictor:加权随机输出预测
输出预测器(output_predictor.go)用于容量规划:在请求到达前预测其输出 token 数,帮助调度器预估 GPU 负载。其核心是SimpleOutputPredictor:
- 滑窗直方图:维护最近
movingWindow(默认 240s,与 GPU Optimizer 窗口一致,见 cache_init.go)内的历史分布,按MovingInterval = 10s滚动; - 对数分桶:输入/输出 token 分别按
round(log2(tokens))分桶,桶数量由maxInputTokens = 1M、maxOutputTokens = 1M计算(cache_init.go); - 加权随机预测:
Predict(inputTokens)在对应输入桶内做加权随机采样,命中概率与该输出桶的历史频次成正比; - 冷启动策略:无历史数据时,
ColdPredictionStrategy提供四种回退——Optimistic(默认,预测为 1,对 Profile 最友好)、Random(0 到MaxOutputLen=4096随机)、Input(输出等于输入)、Pessimistic(直接取MaxOutputLen)。
五、Pod 实时负载与 GPU Profile
5.1 Pod 元数据与运行中请求计数
Pod结构(pod.go)在原生*v1.Pod之上叠加了三层缓存数据:
Models:该 Pod 承载的模型/适配器名集合(utils.Registry[string]);Metrics/ModelMetrics:Pod 级与 Pod-模型级指标(Prometheus 抓取的引擎 gauge、PromQL 结果、网关派生值等);- 实时统计:
runningRequests(运行中请求原子计数)、completedRequests(已完成请求单调计数)、pendingLoadUtilization(挂起负载利用率)。
特别值得关注的是跨网关运行中请求计数:GetPodsRunningRequests(cache_api.go)通过一次 Redis pipeline 批量获取多个 Pod 的实时在途请求数(本地原子计数作为回退),供 least-request、load-balance、prefix-cache 等路由器和 in-flight 饱和过滤器使用。AdmitPodRunningRequest则提供"检查并计入"的原子操作,避免并发调用方都读到增量前的计数而被同时放行超限。
5.2 GPU Profile 缓存
ProfileCache接口(cache_api.go)提供按 Pod 或按 Deployment 查询ModelGPUProfile的能力,实现位于 model_gpu_profile.go。当启用 Profile 缓存后,initProfileCache会创建pendingLoadProvider(按挂起请求数定义负载的提供者),并启动定时器周期刷新各 Deployment 的画像(cache_init.go)。
六、配置总览:环境变量与默认值
结合 README 与源码,缓存包的全部环境变量整理如下:
核心缓存
| 环境变量 | 默认值 | 说明 |
|---|---|---|
AIBRIX_POD_DEPLOYMENT_LABEL | app.kubernetes.io/name | Deployment 识别标签(见 pkg/utils/pod.go) |
AIBRIX_POD_RAYCLUSTERFLEET_LABEL | orchestration.aibrix.ai/raycluster-fleet-name | RayClusterFleet 识别标签(见 pkg/utils/raycluster.go) |
KV 事件同步(常量定义见 pkg/constants/kv_event_sync.go)
| 环境变量 | 说明 |
|---|---|
AIBRIX_PREFIX_CACHE_KV_EVENT_SYNC_ENABLED | 启用 KV 事件同步总开关 |
AIBRIX_PREFIX_CACHE_USE_REMOTE_TOKENIZER | 启用远程 tokenizer(KV 同步必需) |
AIBRIX_PREFIX_CACHE_TOKENIZER_TYPE | tokenizer 类型,KV 同步要求remote |
AIBRIX_PREFIX_CACHE_REMOTE_TOKENIZER_ENDPOINT | 远程 tokenizer 服务端点 |
AIBRIX_PREFIX_CACHE_KV_EVENT_PUBLISH_ADDR | ZMQ 发布地址 |
AIBRIX_PREFIX_CACHE_KV_EVENT_SUBSCRIBE_ADDRS | ZMQ 订阅地址 |
性能与监控
| 环境变量 | 默认值 | 说明 |
|---|---|---|
AIBRIX_POD_METRIC_REFRESH_INTERVAL_MS | 见 cache_metrics.go | Pod 指标刷新间隔(毫秒),gateway-plugin 部署中显式配置示例见 config/gateway/gateway-plugin/gateway-plugin.yaml |
AIBRIX_MODEL_GPU_PROFILE_CACHING_FLAG | true(见 model_gpu_profile.go) | 启用 GPU Profile 缓存 |
AIBRIX_ZMQ_POLL_TIMEOUT | 100ms | ZMQ 轮询超时 |
AIBRIX_ZMQ_REPLAY_TIMEOUT | 5s | 事件回放请求超时 |
AIBRIX_ZMQ_RECONNECT_INTERVAL | 1s | ZMQ 初始重连间隔 |
生产环境可用kubectl set env动态调整,例如:
kubectl set env deployment/aibrix-gateway-plugins -n aibrix-system AIBRIX_POD_METRIC_REFRESH_INTERVAL_MS=10000七、Usage Example:程序化使用缓存
README 给出了完整的程序化示例——启用 KV 同步、添加 Pod、查询模型 Pod 列表并追踪请求:
// Create cache with KV event sync enabled os.Setenv(constants.EnvPrefixCacheKVEventSyncEnabled, "true") os.Setenv(constants.EnvPrefixCacheUseRemoteTokenizer, "true") store := cache.NewStore() // Add a pod - KV sync will start automatically if eligible store.AddPod(pod) // Query pods for a model pods := store.GetPodsForModel("llama-2-7b") // Track a request store.AddRequest(pod.Name, model, inputTokens) defer store.DoneRequest(pod.Name, model, outputTokens)需要说明的是:生产环境通常不直接调用NewStore(),而是通过cache.InitWithOptions(config, stopCh, opts)完成全局单例的初始化,之后通过cache.Get()获取Cache接口(未初始化时会返回"cache is not initialized"错误,见 cache_init.go)。测试环境则可用NewForTest()/InitForTest()反复重建 Store,或用InitWithPods系列函数注入 Pod 与指标数据(cache_init.go)。
八、集成点:路由算法与网关插件
缓存的数据最终服务于两类消费方:
路由算法:缓存提供 Pod 可用性与负载、前缀缓存命中率、GPU 利用率指标,支撑 least-request(最少请求)、load-balance(负载均衡)、prefix-cache(前缀缓存优先)等路由策略。KV 同步启用时,路由器通过GetSyncPrefixIndexer()(cache_init.go)拿到同步前缀索引器做前缀匹配,若返回 nil 则回退到普通索引器。
网关插件:gateway-plugins 服务查询缓存获取每模型的可用 Pod 列表、当前请求计数与性能预测。Store还通过MetricSubscriber注册机制向外部推送指标更新(AddSubscriber,见 cache_api.go)。
九、监控与线程安全
9.1 Prometheus 指标
缓存包暴露的 Prometheus 指标覆盖:缓存命中/未命中率、请求队列深度、KV 事件处理速率、Pod 同步状态。kvcache子包另有事件接收/处理计数、连接状态、错误计数与处理延迟等指标(见 metrics.go)。
9.2 线程安全设计
Store 的所有操作均线程安全,采用三层保障机制:
- 读写互斥锁:
Store.mu(sync.RWMutex)保护整体数据结构;podStatsMu采用固定条带锁(stripe lock)同步 Pod 删除/重建周期中的计数变更,避免随 Pod 键无限增长锁数量(cache_init.go); - 原子操作:
runningRequests、completedRequests、numRequestsTraces等计数器使用sync/atomic;gatewaySnapshotCache使用atomic.Value实现快照的无锁原子交换; - 通道驱动的事件处理:
podMetricsJobs/promqlJobs通道 + worker 池模型解耦指标采集与主路径;PromQL worker 还内置按 Pod 键去重、FIFO 顺序处理与失败回队重试的机制(cache_init.go)。
十、测试指南
缓存包拥有完善的测试体系,覆盖 Store 初始化、指标刷新、运行中请求追踪、GPU Profile、KV 事件管理器校验等场景:
# All cache tests go test ./pkg/cache/ # KV event specific tests go test -v ./pkg/cache/ -run ".*KV.*" # With ZMQ support go test -tags="zmq" ./pkg/cache/ # kvcache subpackage tests (requires libzmq) go test -tags="zmq" ./pkg/cache/kvcache/相关测试用例包括 cache_test.go、cache_init_test.go、output_predictor_test.go、kv_event_manager_validation_test.go 以及 kvcache 子包的 zmq_client_test.go(内含 mock publisher 的综合示例)。
结语
pkg/cache是理解 AIBrix 路由决策机制的钥匙:从 Kubernetes Informer 驱动的 Pod/模型索引,到 Redis 支撑的跨网关实时计数与网关快照,再到 ZMQ + MessagePack 驱动的 KV 前缀缓存同步,它以线程安全的单例 Store 为底座,把"元数据缓存、负载感知、前缀缓存路由、容量预测"四件事高效地串联在一起。无论你是要扩展新的路由算法、接入自定义服务发现,还是调优 KV 事件同步链路,本包的接口设计(Cache聚合接口、可插拔discovery.Provider、可注册的RequestTracker)都预留了清晰的扩展点,值得深入研读。
【免费下载链接】aibrixCost-efficient and pluggable Infrastructure components for GenAI inference项目地址: https://gitcode.com/GitHub_Trending/ai/aibrix
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考