NIXL#

基于 NIXL 的持久存储 — 主要的生产 L2 后端,使用 NIXL(NVIDIA 互连库)进行高性能存储 I/O。两种适配器类型共享此后端:

  • nixl_store — 在初始化时预分配的固定存储描述符池。

  • nixl_store_dynamic — 每次操作时动态打开并注册文件,支持跨重启的持久化/恢复,并消除打开文件描述符数量的限制。

备注

Both adapters require the NIXL runtime, which ships as the optional lmcache[nixl] extra:

uv pip install lmcache[nixl]

静态池 — nixl_store#

主要的生产适配器。在初始化时预分配一组存储描述符池。

必填字段:

  • backend: 存储后端 -- 以下之一:POSIXGDSGDS_MTHF3FSOBJAZURE_BLOB

  • pool_size: 预分配的存储描述符数量(必须大于 0)。

后端特定参数 (``backend_params``):

基于文件的后端(GDS, GDS_MT, POSIX, HF3FS)需要:

  • file_path: 存储 L2 数据的目录路径。

  • use_direct_io: "true""false" -- 是否使用直接 I/O。

OBJAZURE_BLOB 后端(对象存储)不需要 file_path

后端描述:

后端

描述

POSIX

标准 POSIX 文件 I/O。适用于任何文件系统。无直接 I/O。

GDS

NVIDIA GPU 直接存储。启用直接的 GPU 到存储传输,绕过 CPU。需要支持 GDS 的 NVMe SSD。

GDS_MT

GDS 的多线程变体,以提高吞吐量。

HF3FS

共享文件系统后端(例如,用于分布式/网络存储)。

OBJ

对象存储后端。无需本地文件路径。

AZURE_BLOB

Azure Blob Storage 的对象存储后端。无需本地文件路径。

配置示例:

# POSIX backend
--l2-adapter '{"type": "nixl_store", "backend": "POSIX", "backend_params": {"file_path": "/data/lmcache/l2", "use_direct_io": "false"}, "pool_size": 64}'

# GDS backend
--l2-adapter '{"type": "nixl_store", "backend": "GDS", "backend_params": {"file_path": "/data/nvme/lmcache", "use_direct_io": "true"}, "pool_size": 128}'

# GDS_MT backend
--l2-adapter '{"type": "nixl_store", "backend": "GDS_MT", "backend_params": {"file_path": "/data/nvme/lmcache", "use_direct_io": "true"}, "pool_size": 128}'

# HF3FS backend
--l2-adapter '{"type": "nixl_store", "backend": "HF3FS", "backend_params": {"file_path": "/mnt/hf3fs/lmcache", "use_direct_io": "false"}, "pool_size": 64}'

# OBJ backend
--l2-adapter '{"type": "nixl_store", "backend": "OBJ", "backend_params": {}, "pool_size": 32}'

# AZURE_BLOB backend
--l2-adapter '{"type": "nixl_store", "backend": "AZURE_BLOB", "backend_params": {"account_url": "https://<account_name>.blob.core.windows.net", "container_name": "<container_name>"}, "pool_size": 32}'

动态(持久/恢复) — nixl_store_dynamic#

NIXL 适配器的动态变体,按操作打开和注册文件,而不是在初始化时预分配。该变体支持以下功能:

  • 持久化/恢复 -- 缓存的 KV 元数据在重启后仍然存在。

  • 无文件描述符限制 -- 文件在每次传输时打开和关闭,因此缓存可以超出操作系统的打开文件描述符限制。

备注

仅支持基于文件的后端(POSIX, GDS, GDS_MT, HF3FS)。OBJAZURE_BLOB 后端尚不支持。

必填字段:

  • backend: 存储后端 -- 以下之一:POSIXGDSGDS_MTHF3FS

后端特定参数 (``backend_params``):

  • file_path: 存储 L2 数据文件的目录路径。

  • use_direct_io: "true""false"

  • max_capacity_gb: 最大存储容量(以 GB 为单位)。当达到此限制时,适配器会拒绝存储。此项是逐出控制器计算使用情况所必需的。

  • shard_dirs: "true" or "false" (default "false"). When "true", data files are spread across a two-level subdirectory tree under file_path instead of all living in one flat directory. The two levels use the first four hex characters of the chunk hash for both salted and unsalted keys, providing up to 256 × 256 subdirectories. Leaving shard_dirs unset preserves the flat layout.

    Large flat directories slow down metadata operations on many filesystems, so sharding helps once a single cache directory holds a large number of files. Subdirectories are created lazily on first use and cached in memory, so the store hot path issues at most one makedirs per bucket.

    备注

    shard_dirs changes where files are located, and lookup does not fall back to the other layout. Toggling it against an existing cache directory makes previously written files unreachable (they are not deleted, just no longer found). Choose the layout when the cache directory is first created, or clear it when changing the setting.

    Releases that predate salted dynamic-NIXL filenames wrote salted traffic to salt-blind legacy paths. Those files cannot be safely attributed to a salt and are not used as a fallback. Clear or quarantine that cache directory when upgrading a deployment that used non-empty salts.

For both flat and sharded layouts, a non-empty cache_salt is appended to the filename as @<cache_salt> before .bin. An empty salt retains the legacy filename.

可选字段(用于持久化):

  • persist_enabled (bool, 默认 true): 若为 true,关闭时数据文件将保留在磁盘上。若为 false,关闭时所有数据文件将被删除。

查找时,若未命中则始终回退到二级存储(磁盘)进行检查;找到文件后,惰性填充内存索引。

配置示例:

# Basic dynamic POSIX backend (persist enabled by default)
--l2-adapter '{"type": "nixl_store_dynamic", "backend": "POSIX", "backend_params": {"file_path": "/data/lmcache/l2", "use_direct_io": "false", "max_capacity_gb": "10"}}'

# Explicitly disable persist
--l2-adapter '{"type": "nixl_store_dynamic", "backend": "POSIX", "backend_params": {"file_path": "/data/lmcache/l2", "use_direct_io": "false", "max_capacity_gb": "10"}, "persist_enabled": false}'

# With eviction
--l2-adapter '{"type": "nixl_store_dynamic", "backend": "GDS", "backend_params": {"file_path": "/data/nvme/l2", "use_direct_io": "true", "max_capacity_gb": "50"}, "eviction": {"eviction_policy": "LRU", "trigger_watermark": 0.9, "eviction_ratio": 0.1}}'

# Shard data files across a two-level subdirectory tree
--l2-adapter '{"type": "nixl_store_dynamic", "backend": "POSIX", "backend_params": {"file_path": "/data/lmcache/l2", "use_direct_io": "false", "max_capacity_gb": "10", "shard_dirs": "true"}}'

持久化 / 二级查找行为:

  • 关闭 时,适配器默认将数据文件保留在磁盘上(persist_enabled 默认为 true)。如果明确设置为 false,则所有数据文件将被删除,以避免孤立存储。

  • 启动 时,内存索引为空。每次查找未命中都会回退到磁盘上的二级查找:若对应的确定性文件存在,则视为命中,并根据文件大小惰性填充内存索引。