Skip to content

Troubleshooting.ru

sikkatu edited this page Nov 2, 2026 · 8 revisions

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

Устранение неполадок

Сначала посмотрите три вещи:

bash scripts/budget-report.sh status        # занято, пространства, диск
tail -n 100 "$KVP_CACHE_ROOT/lmcache-server.log"   # сервис кэша
docker logs --tail 100 mimo-pro-tp4-kvp     # движок (лаунчер kv-persistence)

(KVP_CACHE_ROOT задаётся в configs/generic/cache.env.local.)

Предпроверка жалуется на идентичность

  • KVP_MODEL_REVISION must be a full 40-hex SHA — вставьте SHA коммита, а не имя ветки (см. шаг 3 Быстрого старта).
  • KVP_CHAT_TEMPLATE_DIGEST must be 64 hex — выполните preflight один раз с KVP_MODEL_DIR="$HOME/models/MiMo-V2.6-Pro-MOPD"; скопируйте напечатанное значение.

CLI lmcache отсутствует или несовместим ABI

ERROR: lmcache CLI missing — установите по шагу 4 Быстрого старта. Если import lmcache падает с ошибками неопределённых символов, pip-wheel собран под другой стек PyTorch/CUDA. Запасной путь — сервер прямо из production-образа:

docker run --rm --entrypoint lmcache "$IMAGE" server --help

Если так работает — подправьте строку запуска в scripts/start-cache.sh под docker run с теми же аргументами (порты/пути не меняются).

Сервис кэша запустился, но vLLM не подключается

  1. Порядок старта: start-cache.sh ДО лаунчера vLLM (run-vllm-with-persist.sh иначе отказывается стартовать).
  2. Смотрите строку ошибки в логе сервиса; оба процесса используют одну host-сеть — не переносите порт запросов без правки обеих сторон.
  3. С интеграцией рецепта (KV_PERSIST=1): лаунчер печатает KV_PERSIST=1: attaching LMCache connector … — нет строки = ручка не дошла до лаунчера (проверьте tp4.env и экспортированы ли переменные).

После перезапуска нет попаданий (TTFT не падает)

Проверяйте по порядку:

  1. cached_tokens в ответе > 0.
  2. grep -c Retrieved "$KVP_CACHE_ROOT/lmcache-server.log" растёт во время запроса; строки после перезапуска — это доказательство дискового восстановления.
  3. used_bytes НЕ выросло, пересоздавая те же данные (bash scripts/budget-report.sh status до/после).
  4. Идентичность не менялась — повторите scripts/preflight.sh; смена ревизии/ dtype/шаблона молча переводит в НОВОЕ пространство (по дизайну).
  5. KVP_PERSIST_ENABLED равен true (иначе start-cache.sh предупреждает).

Диск полон / записи отклоняются

free_bytes: 0 в отчёте либо адаптер пишет отказ на жёстком лимите — поднимите KVP_CACHE_BUDGET_GB или явно подчистите старые пространства (purge --namespace=NAME --yes, имена — из status). Жёсткий лимит — это max_capacity_gb в адаптере L2: при его достижении новые записи отклоняются (сервис продолжает работать без новых записей в кэш). Эвикция на мягком пороге (90 %) обычно освобождает место раньше, но это НЕ гарантия от заполнения самого ДИСКА — реальная граница: свободное место на томе с KVP_CACHE_ROOT (на эталонном хосте этот же том держит Docker, модель и ОС). Держите запас свободного места и снижайте бюджет, если диск заканчивается. Не удаляйте отдельные файлы внутри корня кэша, пока сервис работает.

Эвикция слишком резвая (или наоборот)

Поднимите KVP_EVICT_TRIGGER_WATERMARK (начинать позже) или отрегулируйте KVP_EVICT_RATIO (больше возврата за цикл). Проверяйте на маленьком изолированном бюджете, прежде чем ждать эффектов в масштабе 1.5 ТБ. Фактический режим виден по счётчикам evictions/reclaimed_bytes в отчёте.

Кэш мало переиспользуется (всё «холодное»)

Измерьте, какая часть промпта реально стабильна:

python3 "$REPO/implementation/prompt_probe.py" --tokenizer "$MODEL_DIR" \
  --request-file a.json --request-file b.json

с двумя реальными телами запросов, выгруженными из клиента. Мало stable_prefix_tokens — динамические значения (временные метки, id tool-вызовов) ломают префикс: лечите сериализацию на источнике либо принимайте ограничение. Обрезать историю ради кэша запрещено.

Восстановление после повреждения файла

Повреждения терпимы: промах просто пересчитывает. Для очистки вручную: остановите сервис кэша, bash scripts/budget-report.sh purge --all --yes, запустите снова. Автоматически никогда. Фреймы lossless-кодека дополнительно несут CRC32: битый или усечённый фрейм обнаруживается при чтении и трактуется как промах кэша — никогда не возвращается как неверный KV.

Проблемы lossless-кодека

  • CodecError: zstandard/lz4 python bindings not installed — ВЫБРАННОМУ кодеку нужен Python-пакет (zstd → zstandard, lz4 → lz4). Установите его в venv lmcache или откатитесь на LMCACHE_L2_SERDE=none (байт-точный сырой режим, без зависимостей вообще). Проверка идёт до старта сервера и никогда не требует неиспользуемый кодек: кэшу none пакеты сжатия не нужны.
  • LMCACHE_L2_SERDE=... is LOSSY and is not supported — ожидаемо: проект lossless-only. Используйте none, zstd или lz4.
  • Сменили кодек и исчезли cache hit — ожидаемо и безопасно: кодек входит в namespace идентичности, старые чанки становятся промахом. Пересохраните их (или верните кодек) — никогда не неверное чтение.
  • Сжатые чанки не меньше на диске — кодек сжимает только сжимаемое; несжимаемые блоки хранятся сырыми с паддингом до 4 КиБ. На крошечных чанках доминирует заголовок (28 Б).

Расход диска выше ожидаемого, но кэш-файлов не видно

После жёсткого убийства (SIGKILL, OOM, отключение питания) адаптер может оставить <final>.bin.tmp.<uuid> — файлы, не успевшие атомарно переименоваться. Upstream вычищает их только при ЧИСТОЙ остановке. Проверьте bash scripts/budget-report.sh status (поля tmp_files / tmp_files_bytes), удалите через purge --tmp --yes (только мусор) или purge --all --yes. Обе команды защищают идущие записи реестром активных записей (kvpersist.tmp_guard): каждая запись регистрирует маркер до создания tmp-файла и снимает его после атомарного rename. Живость работает в ОБОИХ режимах запуска (раунд 18):

  • host-режим — маркер хранит (pid, время старта процесса), писатель жив, пока существует именно этот процесс (/proc/<pid> + время старта защищает от повторного использования PID);
  • docker-режим (KVP_LAUNCH_MODE=docker, без --pid=host) — маркер хранит ID PID-неймспейса писателя; если маркер принадлежит чужому неймспейсу, CLI на хосте не может проверить его PID, поэтому живость определяется по HEARTBEAT самого маркера (работающая запись освежает его каждые 30 с): маркер, тронутый за последние 2 минуты — живой, старше — остаток краша. Если живость определить вообще нельзя (нет /proc, нечитаемый маркер) — маркер сохраняется: лучше держать лишний tmp-файл, чем удалить файл живой записи. Маркеры, чей писатель доказанно завершился, вычищаются через час. Второй механизм — страховка для писателей без реестра (например, голый lmcache server): файлы *.tmp.*, изменённые за последние 15 минут, пропускаются — это окно ЭВРИСТИКА, а не абсолютная защита.

Grafana не показывает данные

Стек пассивен до пуша телеметрии. Запустите кэш с USE_OBSERVABILITY=1 (или KVP_OTLP_ENDPOINT=http://localhost:4320) и проверьте лог на баннер [kvp]. В docker-режиме start-cache.sh сам переписывает localhost на host.docker.internal. Все порты стека — только 127.0.0.1 (loopback-контракт).

Матрица промахов кэша (почему кэш "перестал работать"?)

Изменение ЛЮБОГО поля идентичности меняет пространство имён: старые записи кэша не удаляются, но становятся недостижимыми — это выглядит как "кэш сломан", хотя работает механизм изоляции. Каждая строка ниже инвалидирует ВСЕ ранее закэшированные KV-блоки этого деплоя:

Вы изменили... Влияние на namespace Переиспользование старого кэша?
веса модели (подмена содержимого, даже при тех же именах) SHA-256 байт шарда меняется НЕТ
ревизию модели (HF SHA) меняется НЕТ
токенизатор (tokenizer.json / tokenizer_config.json) меняется НЕТ
chat_template / chat_template.jinja digest меняется НЕТ
--kv-cache-dtype (bfloat16 -> float16 и т.п.) меняется НЕТ
--max-model-len меняется НЕТ
--tensor-parallel-size меняется НЕТ
конфигурацию KV-геометрии в config.json меняется НЕТ
сборку vLLM / версию LMCache-коннектора (KVP_CONNECTOR_VERSION) меняется НЕТ
--enforce-eager / прочие флаги движка, меняющие порядок KV-вычислений может менять раскладку блоков → меняется НЕТ
дайджест Docker-образа (другая сборка vLLM) меняется НЕТ

Практически: фиксируйте KVP_MODEL_REVISION выводом setup-identity.sh и сохраняйте identity.env.local рядом с каждым деплоем; ожидайте смену namespace при любом изменении аргументов движка и воспринимайте "кэш холодный после правки" как корректное ожидаемое поведение, а не ошибку.

Clone this wiki locally