P2P KV 缓存共享#

概述#

在多节点部署中,每个节点运行自己的 LMCache 服务器进程,每个节点在其本地内存中缓存它所服务请求的 KV。没有共享时,当相同的前缀到达不同节点时,必须从头开始重计算在一个节点上计算的前缀。

点对点 (P2P) KV 缓存共享将每个节点的缓存转变为一个逻辑缓存。 当一个节点查找不在其本地内存中的前缀时,它可以通过数据中心网络使用 RDMA 直接从持有该前缀的对等节点的内存中读取该前缀的 KV。结果是整个系统的有效缓存命中率大大提高,而无需在热路径中使用中央存储层。

传输是从请求节点到其自身 L1 缓冲区的单向 RDMA 读取;拥有数据的节点不会被打断来提供数据。在支持 RDMA 的网络(如 InfiniBand / RoCE)上,这比重新计算前缀或通过共享对象存储进行往返要快得多。

它是如何工作的#

P2P 涉及三个部分:

  • 协调器 — 一个小型 HTTP 服务(每个部署一个),用于跟踪哪些 LMCache 服务器处于活动状态。每个服务器向其注册并发送心跳;协调器回答“我的活动对等体是谁?”的查询。它仅管理成员资格——它从不查看 KV 数据或参与查找。请参见 多服务器协调

  • LMCache 服务器 — 每个服务器运行一个 P2P 控制器,定期向协调器请求当前的对等体列表,并为每个活跃的对等体打开一个连接,用于查找和读取该对等体的 KV。

  • 传输通道 — 执行实际远程内存读取的 RDMA 层。每个服务器在启动时注册其 L1 缓冲区,以便对等体可以从中读取。

在缓存未命中时,一个节点请求拥有前缀的对等节点锁定并定位它,接收远程地址,将 KV 读取到自己的 L1 中,并从那里提供请求。对等节点在加入时会自动发现和连接,在离开时会自动断开 — 无需静态对等节点列表。

要求#

  • 一个协调者。 P2P 需要协调者进行对等发现。使用 --p2p-advertise-url 启动的服务器如果没有 --coordinator-url 则拒绝启动。

  • 强烈推荐使用支持 RDMA 的网络(InfiniBand / RoCE)以获得生产性能。默认情况下,P2P 使用与 LMCache 一起提供的 nixl 传输引擎,因此无需额外安装任何东西。

  • 一个单一的、连续的 L1 区域。 传输通道为 RDMA 注册整个 L1 缓冲区,因此 P2P 与 GDS L1 层(--gds-l1-path)和 Device-DAX L1 层(--l1-devdax-path)不兼容;在这些配置下,服务器拒绝启动。

配置#

P2P 通过 --p2p-advertise-url 标志在每个服务器上启用。相关的 lmcache server 标志包括:

标志

描述

--p2p-advertise-url HOST:PORT

此服务器向对等节点广告的传输通道端点。设置它可以启用 P2P。必须是其他节点可以访问的地址。

--p2p-listen-url HOST:PORT

传输通道服务器绑定的地址。默认为 --p2p-advertise-url;在广告可路由 IP 时,将其设置为绑定 0.0.0.0

--p2p-lookup-timeout SECONDS

对等查找的截止时间,超过该时间将视为未命中(默认 30)。

--p2p-load-timeout SECONDS

对等 KV 读取的截止时间,超过该时间将视为失败(默认 30)。

--p2p-transfer-engine ENGINE

传输通道实现(默认 nixl)。

P2P 还重用协调器连接标志 (--coordinator-url, --coordinator-advertise-ip, --coordinator-heartbeat-interval);心跳间隔同时作为对等发现轮询间隔。有关完整的标志列表,请参见 lmcache serverlmcache coordinator

小技巧

在参与 P2P 的服务器上,将 L1 缓冲区对齐增加到至少 64 KB (--l1-align-bytes 65536)。更大的对齐可以让传输通道发出更大、更好对齐的 RDMA 读取,并显著提高传输性能。默认值(4 KB)对于非 P2P 部署是可以的。

传输引擎后端#

传输引擎是执行远程内存读取的组件,按服务器选择,使用 --p2p-transfer-engine

引擎

描述

nixl (默认)

基于 RDMA 的传输,随 LMCache 一起提供。运行在 InfiniBand / RoCE 网络上。

nixl 是目前唯一可用的后端。传输引擎是一个可插拔的抽象,因此可以在未来添加其他后端,而无需更改 P2P 堆栈的其余部分。

运行多节点部署#

下面的示例启动了一个两节点的集群。添加更多节点只需复制每个节点的步骤,所有节点都指向相同的协调器。

步骤 1 — 启动协调器(在所有节点都能访问的主机上,这里是 10.0.0.1):

lmcache coordinator --host 0.0.0.0 --port 9300

步骤 2 — 在每个节点上启动启用 P2P 的 LMCache 服务器。<NODE_IP> 替换为该节点的可路由地址(例如 10.0.0.210.0.0.3 等):

lmcache server \
    --host 0.0.0.0 --port 5555 \
    --http-port 8080 \
    --l1-size-gb 100 --eviction-policy LRU \
    --l1-align-bytes 65536 \
    --coordinator-url http://10.0.0.1:9300 \
    --coordinator-advertise-ip <NODE_IP> \
    --p2p-advertise-url <NODE_IP>:8500

--coordinator-advertise-ip 是对等节点用来访问该节点控制平面的地址,而 --p2p-advertise-url 是 RDMA 传输端点。这里服务器绑定 0.0.0.0(所有接口)并广播 <NODE_IP>

步骤 3 — 在每个节点上,通过连接器启动指向本地 LMCache 服务器的 vLLM。vLLM 从不直接与对等节点通信 — 它连接的 LMCache 服务器代表它进行 P2P:

vllm serve <model> \
    --port 8000 \
    --kv-transfer-config '{"kv_connector":"LMCacheMPConnector","kv_role":"kv_both","kv_load_failure_policy":"recompute","kv_connector_extra_config":{"lmcache.mp.port":5555}}'

一旦两个节点都已注册,当相同的前缀稍后到达节点 3 时,首先在节点 2 上提供的前缀将从节点 2 的缓存中提供——通过 RDMA 读取,而不是重计算。

在单个节点上运行(测试和调试)#

您可以通过在 localhost 上运行两个 LMCache 服务器和两个 vLLM 服务器,以及一个协调器,在单个多 GPU 机器上执行整个 P2P 路径。这是开发和调试 P2P 的推荐方式。

# Terminal 1 — coordinator
lmcache coordinator --host 0.0.0.0 --port 9300

# Terminal 2 — node "A": LMCache server
lmcache server \
    --host 127.0.0.1 --port 6555 --http-port 7555 \
    --l1-size-gb 50 --eviction-policy LRU \
    --l1-align-bytes 65536 \
    --instance-id node-a \
    --coordinator-url http://127.0.0.1:9300 \
    --coordinator-advertise-ip 127.0.0.1 \
    --p2p-advertise-url 127.0.0.1:8555

# Terminal 3 — node "A": vLLM on GPU 0
CUDA_VISIBLE_DEVICES=0 vllm serve <model> --port 8000 \
    --kv-transfer-config '{"kv_connector":"LMCacheMPConnector","kv_role":"kv_both","kv_load_failure_policy":"recompute","kv_connector_extra_config":{"lmcache.mp.port":6555}}'

# Terminal 4 — node "B": LMCache server
lmcache server \
    --host 127.0.0.1 --port 6556 --http-port 7556 \
    --l1-size-gb 50 --eviction-policy LRU \
    --l1-align-bytes 65536 \
    --instance-id node-b \
    --coordinator-url http://127.0.0.1:9300 \
    --coordinator-advertise-ip 127.0.0.1 \
    --p2p-advertise-url 127.0.0.1:8556

# Terminal 5 — node "B": vLLM on GPU 1
CUDA_VISIBLE_DEVICES=1 vllm serve <model> --port 8001 \
    --kv-transfer-config '{"kv_connector":"LMCacheMPConnector","kv_role":"kv_both","kv_load_failure_policy":"recompute","kv_connector_extra_config":{"lmcache.mp.port":6556}}'

这两个服务器必须在 每个 端口上有所不同:ZMQ (--port)、HTTP (--http-port) 和 P2P 传输端点 (--p2p-advertise-url)。为每个服务器指定一个独特的 --instance-id,以便于区分。

要测试路径,向 vLLM A(端口 8000)发送一个长提示,然后向 vLLM B(端口 8001)发送相同的提示。B 从未见过该提示,并且它自己的缓存是空的,因此 B 上的任何 LMCache 命中必须是通过 P2P 从 A 读取的。

备注

在单个主机上,localhost 流量通常使用回环/TCP 路径而不是 RDMA,因此延迟并不能代表真实的 RDMA 结构。单节点模式用于 功能 测试和调试;在真实的多节点 RDMA 部署上进行基准性能测试。

验证 P2P 是否正常工作#

查询服务器的状态端点以查看其 P2P 状态和发现的对等节点:

curl -s http://127.0.0.1:7555/status | python3 -m json.tool

查找 p2p_state (一旦加入协调器则为 registered)和 p2p_peer_count (连接的对等节点数量;在两个节点的示例中为 1)。您还可以从协调器列出整个集群:

curl -s http://127.0.0.1:9300/instances | python3 -m json.tool

LMCACHE_LOG_LEVEL=DEBUG 下,每个服务器在连接到对等体时记录 Added P2P adapter ... for peer <instance-id>,在对等体离开时记录 Removed P2P adapter ...

限制#

  • 只读。 节点从其对等节点读取 KV;它永远不会写入对等节点的内存。这使得每个节点都是其 L1 的唯一拥有者。

  • 单跳。 节点直接从持有前缀的对等节点读取;读取不会跨多个对等节点链式进行。