Skip to content

Architecture.ru

sikkatu edited this page Nov 1, 2026 · 5 revisions

English | Русский | 中文

Архитектура

Топология

Чат-клиент (OpenAI-совместимый, длинная история сообщений)
   │  /v1/chat/completions
   ▼
vLLM  (TP4 или другая параллельность, любая модель; production-рецепт не изменяется)
   │  --kv-transfer-config: LMCacheMPConnector
   │  (kv_connector_module_path фиксирует коннектор из LMCache)
   ▼
lmcache-сервер  (отдельный процесс; ZMQ-порт запросов 5555, HTTP-админ 8080)
   │  L1: буфер в RAM хоста (KVP_L1_SIZE_GB, по умолчанию 64 ГБ)
   ▼
Постоянный уровень L2: nixl_store_dynamic / POSIX  →  NVMe (KVP_CACHE_ROOT)
   контроллер эвикции: LRU, trigger_watermark 0.9, eviction_ratio 0.1

Поток данных

  1. vLLM считает KV-чанки и сохраняет их через коннектор в L1 (RAM хоста).
  2. Контроллер записи асинхронно пишет каждый объект в L2 — по одному файлу на ключ чанка (временный файл + атомарный rename — сбой никогда не оставит «полуфайл»).
  3. При поиске сначала проверяется L1; промах уходит в L2 на диске. Дисковое попадание подтягивается в L1 и возвращается vLLM. Индекс в памяти стартует пустым и наполняется лениво из детерминированных имён файлов — это и обеспечивает восстановление после рестарта обоих сервисов.
  4. При выключении persist_enabled=true сохраняет файлы L2 (значение по умолчанию; false удаляет их и ломает главное требование).

Почему nixl_store_dynamic

Именно семейство этого L2-адаптера LMCache документировано с семантикой persist/recover: файлы открываются на каждую операцию (нет предварительно выделенного реестра, умирающего с процессом, нет ограничения по числу дескрипторов в масштабе 1.5 ТБ), а промах поиска уходит к детерминированному файлу на диске. nixl_store (предварительно выделенный вариант) не документирует восстановление после рестарта. POSIX-бэкенд выбран сознательно — самый простой надёжный путь к NVMe — до всяких GDS.

Независимость компонентов

Кэш-сервис — отдельный процесс. Рестарт vLLM не может стереть постоянные KV-данные; рестарт кэш-сервиса сохраняет их на диске. Режим, где кэш живёт только в памяти процесса, НЕ удовлетворяет требованию персистентности и не используется.

Пространства совместимости

В ключ кэша входят:

  • id модели + ревизия модели (полный 40-символьный SHA коммита)
  • имя и ревизия токенизатора
  • эффективный KV-cache dtype (разрешённый — auto не принимается)
  • геометрия KV: размер блока, число KV-голов, размер головы
  • размер тензорного параллелизма (TP)
  • имя коннектора + фиксированная идентичность сборки коннектора/vLLM
  • максимальная длина модели
  • digest чат-шаблона (sha256 отрендеренного шаблона)

Пространство — kvp-<первые 32 hex от sha256(канонического JSON полей)>. Это логический идентификатор. На уровне хранилища LMCache он преобразуется в model_name (CacheIdentity.lmcache_model_name()), и именно он разделяет файлы на диске: адаптер nixl_store_dynamic именует файлы <safe_model_name>_<kv_rank>_<group>_<chunkhash>.bin прямо в KVP_CACHE_ROOT (плоская раскладка — каталогов kvp-<hash> НЕТ; префикс каждого имени файла — санитизированное имя модели с этим пространством). Любое пустое/неопределённое поле ⇒ промах кэша (пересчёт), никогда — неверное попадание. Изменение любого поля переводит в НОВОЕ пространство; старые данные становятся недостижимыми, но никогда не удаляются автоматически (см. Хранилище и эвикция).

Модельно-агностичная граница

Слой Где Модель-зависимый?
Идентичность / пространства implementation/kvpersist/identity.py только входные данные
Бюджет и квоты implementation/kvpersist/budget.py нет
Ранжирование удержания implementation/kvpersist/retention.py нет
lmcache-сервер + L2-адаптер configs/generic/* нет
Пины идентичности и геометрия configs/<model>/identity.env да
Лаунчер vLLM scripts/run-vllm-with-persist.sh да

«Модельно-агностичный» означает, что механизм поддерживает несколько конфигураций — НЕ то, что их KV-данные взаимозаменяемы. Разные модели никогда не делят KV-блоки.

Модель отказов

Отказ Поведение
промах / частичное попадание пересчитывается только недостающая часть
несовместимая запись недостижима по пространству ⇒ промах
битый / недописанный файл поиск уходит мимо ⇒ пересчёт; вывод никогда не неверный
прерванная запись атомарный rename ⇒ читатель видит старый или новый файл
прерванная эвикция та же атомарность; отсутствие файла — обычный промах
диск полон / бюджет исчерпан записи отклоняются; обслуживание продолжается без кэша
кэш-сервис недоступен vLLM работает без кэша; корректность не меняется
падение любого процесса рестарт ⇒ ленивое восстановление индекса с диска

Сбой кэша никогда не может испортить вывод: худший случай — пересчёт.

Раскладка процессов

  • lmcache-сервер — в фоне, pid-файл KVP_CACHE_ROOT/lmcache-server.pid.
  • Контейнер vLLM — имя mimo-pro-tp4-kvp (лаунчер kv-persistence) или собственный контейнер рецепта при интеграции KV_PERSIST=1.
  • kvp-admin (консольная команда / python3 -m kvpersist.cli) — отчёты и явная очистка; никогда не запускается автоматически.

Clone this wiki locally