Prhub

#39837 [KVConnector][LMCache] Propagate cache_salt through MP connector for per-user cache isolation

vllm-project/vllm · 作者 royyhuang · 合并时间 2026-04-16 00:10

分析状态 已生成
文件变更 1提交数 7 · 评论 5
代码增减 +17 / -2
kv-connector v1 feature

执行摘要

为 LMCache MP 连接器传播 cache_salt,支持按用户缓存隔离。

根据PR body和关联Issue LMCache/LMCache#3029,动机是支持LMCache的按用户缓存隔离功能。cache_salt是vLLM OpenAI API中已有的每请求字段(用于前缀缓存隔离),需要将其传播到LMCache MP连接器,以便LMCache可以将其用于按用户存储配额。这是vLLM侧的对等变更,与LMCache仓库的接口扩展配合。

该PR值得精读,因为它展示了如何在分布式缓存系统中传播上下文信息以支持新功能(如按用户隔离)。关注点包括:数据流设计(从请求到跟踪器、元数据、适配器)、默认值处理(or ""确保向后兼容)、以及与外部系统的接口协调。

讨论亮点

review中主要讨论了代码一致性和潜在运行时错误:

  • gemini-code-assist[bot]指出cache_salt应在LMCacheMPRequestTracker数据类中显式声明为字段以保持一致性(已通过后续提交修复)。
  • gemini-code-assist[bot]警告:内部回退适配器方法(如batched_submit_retrieve_requests)尚未更新以接受cache_salts参数,如果lmcache包未安装且使用回退,可能导致TypeError。但此问题可能属于LMCache仓库的范畴,因为PR body提到适配器方法已接受cache_salt=""默认值(LMCache/LMCache#3029)。
  • ApostaC批准:简单表示“LGTM!”,表明变更整体被接受。

实现拆解

  1. 在请求跟踪器中添加cache_salt字段:在LMCacheMPRequestTracker类中添加cache_salt: str = ""字段,并在__init__方法中从request.cache_salt初始化(若为None则默认为空字符串)。
  2. 在元数据中添加cache_salt字段:在LMCacheMPRequestMetadata数据类中添加cache_salt: str = ""字段,并在GetStoreMetadataGetRetrieveMetadata静态方法中从跟踪器复制该值。
  3. 传播到调度器适配器:在get_num_new_matched_tokens方法中,调用scheduler_adapter.maybe_submit_lookup_request时传递cache_salt参数。
  4. 传播到工作者适配器:在start_load_kvwait_for_save方法中,收集cache_salts列表,并传递给worker_adapter.batched_submit_retrieve_requestsbatched_submit_store_requests方法。
  5. 测试与兼容性:PR body提到测试计划包括确保未设置cache_salt时行为不变(默认为空字符串),但未包含测试文件变更;集成测试将作为后续工作。
文件 模块 状态 重要度
vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py KV 连接器 modified 5.95
vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py core-logic

这是唯一变更的文件,包含了 LMCache MP 连接器的核心逻辑,负责传播 cache_salt 以支持按用户缓存隔离。

@dataclass
class LMCacheMPRequestTracker:
    # ... 其他字段 ...
    cache_salt: str = "" # 新增字段,用于存储缓存盐值,默认为空字符串
​
    def __init__(self, request: "Request"):
        self.request_id = request.request_id
        self.cache_salt: str = request.cache_salt or "" # 从请求中提取cache_salt,若为None则默认为空字符串
        self.all_token_ids = request.all_token_ids
        # ... 其他初始化 ...@dataclass
class LMCacheMPRequestMetadata:
    request_id: str
    direction: Literal["STORE", "RETRIEVE"]
    op: LoadStoreOp
    cache_salt: str = "" # 新增字段,用于在元数据中传递缓存盐值
​
    @staticmethod
    def GetStoreMetadata(
        tracker: LMCacheMPRequestTracker,
        blocks_in_chunk: int,
        vllm_block_size: int,
    ) -> "LMCacheMPRequestMetadata | None":
        # ... 计算存储元数据的逻辑 ...
        if num_chunks >= 1:
            # ... 构建操作 ...
            ret = LMCacheMPRequestMetadata(
                request_id=tracker.request_id,
                direction="STORE",
                op=op,
                cache_salt=tracker.cache_salt, # 从跟踪器复制cache_salt到元数据
            )
            # ... 更新跟踪器 ...
            return ret
        return None
​
    # GetRetrieveMetadata 方法类似,也包含 cache_salt=tracker.cache_salt

关键符号

LMCacheMPRequestTracker.__init__ LMCacheMPRequestMetadata.GetStoreMetadata LMCacheMPRequestMetadata.GetRetrieveMetadata start_load_kv wait_for_save get_num_new_matched_tokens

评论区精华

cache_salt 字段在数据类中的声明 正确性

gemini-code-assist[bot] 指出 cache_salt 应在 LMCacheMPRequestTracker 数据类中显式声明为字段,而不仅仅在 __init__ 中初始化,以确保类型提示和一致性。

结论:通过后续提交添加了 cache_salt: str = "" 字段声明,问题已解决。 · 已解决

内部回退适配器方法参数不匹配 正确性

gemini-code-assist[bot] 警告内部回退适配器方法(如 batched_submit_retrieve_requests)可能未更新以接受 cache_salts 参数,导致 TypeError。

结论:根据关联 Issue,LMCache 侧已添加默认参数,因此风险较低,但需确保部署协调。 · partially_resolved

风险与影响

技术风险较低,但需注意:

  1. 兼容性风险:如果内部回退适配器未同步更新,当lmcache未安装时可能引发TypeError。但根据关联Issue,LMCache侧已添加默认参数,因此风险可控。
  2. 回归风险:变更核心是添加可选字段和参数,默认值为空字符串,因此当cache_salt未设置时行为应与之前一致,降低了回归可能性。
  3. 集成风险:需要与LMCache仓库的变更(Issue #3029)协同部署,否则可能导致接口不匹配。

影响范围有限:

  • 用户影响:对最终用户透明,除非通过API设置cache_salt,否则无行为变化。为未来按用户缓存隔离功能奠定基础。
  • 系统影响:仅影响使用LMCache MP连接器的场景,涉及KV卸载和外部缓存路径。
  • 团队影响:需要与LMCache团队协调,确保接口变更同步。
依赖外部系统协调 潜在接口不匹配

关联 Issue

#3029 [Feat] Add cache_salt parameter to MP adapter interfaces

完整报告

执行摘要

  • 一句话:为LMCache MP连接器传播cache_salt,支持按用户缓存隔离。
  • 推荐动作:该PR值得精读,因为它展示了如何在分布式缓存系统中传播上下文信息以支持新功能(如按用户隔离)。关注点包括:数据流设计(从请求到跟踪器、元数据、适配器)、默认值处理(or ""确保向后兼容)、以及与外部系统的接口协调。

功能与动机

根据PR body和关联Issue LMCache/LMCache#3029,动机是支持LMCache的按用户缓存隔离功能。cache_salt是vLLM OpenAI API中已有的每请求字段(用于前缀缓存隔离),需要将其传播到LMCache MP连接器,以便LMCache可以将其用于按用户存储配额。这是vLLM侧的对等变更,与LMCache仓库的接口扩展配合。

实现拆解

  1. 在请求跟踪器中添加cache_salt字段:在LMCacheMPRequestTracker类中添加cache_salt: str = ""字段,并在__init__方法中从request.cache_salt初始化(若为None则默认为空字符串)。
  2. 在元数据中添加cache_salt字段:在LMCacheMPRequestMetadata数据类中添加cache_salt: str = ""字段,并在GetStoreMetadataGetRetrieveMetadata静态方法中从跟踪器复制该值。
  3. 传播到调度器适配器:在get_num_new_matched_tokens方法中,调用scheduler_adapter.maybe_submit_lookup_request时传递cache_salt参数。
  4. 传播到工作者适配器:在start_load_kvwait_for_save方法中,收集cache_salts列表,并传递给worker_adapter.batched_submit_retrieve_requestsbatched_submit_store_requests方法。
  5. 测试与兼容性:PR body提到测试计划包括确保未设置cache_salt时行为不变(默认为空字符串),但未包含测试文件变更;集成测试将作为后续工作。

关键文件:

  • vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py(模块 KV连接器;类别 source;类型 core-logic;符号 LMCacheMPRequestTracker, LMCacheMPRequestMetadata, GetStoreMetadata, GetRetrieveMetadata): 这是唯一变更的文件,包含了LMCache MP连接器的核心逻辑,负责传播cache_salt以支持按用户缓存隔离。

关键符号:LMCacheMPRequestTracker.init, LMCacheMPRequestMetadata.GetStoreMetadata, LMCacheMPRequestMetadata.GetRetrieveMetadata, start_load_kv, wait_for_save, get_num_new_matched_tokens

关键源码片段

vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py

这是唯一变更的文件,包含了LMCache MP连接器的核心逻辑,负责传播cache_salt以支持按用户缓存隔离。

@dataclass
class LMCacheMPRequestTracker:
    # ... 其他字段 ...
    cache_salt: str = "" # 新增字段,用于存储缓存盐值,默认为空字符串
​
    def __init__(self, request: "Request"):
        self.request_id = request.request_id
        self.cache_salt: str = request.cache_salt or "" # 从请求中提取cache_salt,若为None则默认为空字符串
        self.all_token_ids = request.all_token_ids
        # ... 其他初始化 ...@dataclass
class LMCacheMPRequestMetadata:
    request_id: str
    direction: Literal["STORE", "RETRIEVE"]
    op: LoadStoreOp
    cache_salt: str = "" # 新增字段,用于在元数据中传递缓存盐值
​
    @staticmethod
    def GetStoreMetadata(
        tracker: LMCacheMPRequestTracker,
        blocks_in_chunk: int,
        vllm_block_size: int,
    ) -> "LMCacheMPRequestMetadata | None":
        # ... 计算存储元数据的逻辑 ...
        if num_chunks >= 1:
            # ... 构建操作 ...
            ret = LMCacheMPRequestMetadata(
                request_id=tracker.request_id,
                direction="STORE",
                op=op,
                cache_salt=tracker.cache_salt, # 从跟踪器复制cache_salt到元数据
            )
            # ... 更新跟踪器 ...
            return ret
        return None
​
    # GetRetrieveMetadata 方法类似,也包含 cache_salt=tracker.cache_salt

评论区精华

review中主要讨论了代码一致性和潜在运行时错误:

  • gemini-code-assist[bot]指出cache_salt应在LMCacheMPRequestTracker数据类中显式声明为字段以保持一致性(已通过后续提交修复)。
  • gemini-code-assist[bot]警告:内部回退适配器方法(如batched_submit_retrieve_requests)尚未更新以接受cache_salts参数,如果lmcache包未安装且使用回退,可能导致TypeError。但此问题可能属于LMCache仓库的范畴,因为PR body提到适配器方法已接受cache_salt=""默认值(LMCache/LMCache#3029)。
  • ApostaC批准:简单表示“LGTM!”,表明变更整体被接受。

    • cache_salt字段在数据类中的声明 (correctness): 通过后续提交添加了cache_salt: str = ""字段声明,问题已解决。
    • 内部回退适配器方法参数不匹配 (correctness): 根据关联Issue,LMCache侧已添加默认参数,因此风险较低,但需确保部署协调。

风险与影响

  • 风险:技术风险较低,但需注意:
    1. 兼容性风险:如果内部回退适配器未同步更新,当lmcache未安装时可能引发TypeError。但根据关联Issue,LMCache侧已添加默认参数,因此风险可控。
    2. 回归风险:变更核心是添加可选字段和参数,默认值为空字符串,因此当cache_salt未设置时行为应与之前一致,降低了回归可能性。
    3. 集成风险:需要与LMCache仓库的变更(Issue #3029)协同部署,否则可能导致接口不匹配。
  • 影响:影响范围有限:
  • 用户影响:对最终用户透明,除非通过API设置cache_salt,否则无行为变化。为未来按用户缓存隔离功能奠定基础。
  • 系统影响:仅影响使用LMCache MP连接器的场景,涉及KV卸载和外部缓存路径。
  • 团队影响:需要与LMCache团队协调,确保接口变更同步。
  • 风险标记:依赖外部系统协调, 潜在接口不匹配

关联脉络

  • PR #36644 [kv_offload+HMA][3/N]: Remove block_size from KVEvents: 同属kv-connector模块的PR,涉及KV卸载事件系统的重构,与本PR的LMCache MP连接器变更相关。
  • PR #39548 [Bugfix][Mooncake] Fix thread-local CUDA context for NVLink transfers in _send_blocks: 同属kv-connector模块的PR,涉及KV传输的修复,展示了该模块的持续演进。

参与讨论