中文翻译暂不可用,显示俄语原文。

Как вы проектируете RAG для 10k RPS с P99 latency <200ms? Архитектура.

Краткий тезис

Проектирование RAG-системы на 10k RPS с P99 latency <200ms требует распределённой архитектуры с горизонтальным масштабированием, кэшированием горячих запросов, оптимизированным инференсом LLM и балансировкой нагрузки. Ключевые компоненты: multi-region deployment (мультирегиональное развёртывание), Redis cache для горячих запросов, read replicas векторной БД, vLLM с continuous batching (непрерывная пакетная обработка), load balancer с consistent hashing (консистентное хеширование). Такая архитектура позволяет выдерживать пиковую нагрузку, минимизировать задержки и обеспечить отказоустойчивость.


1. Термины и требования

  • RPS (Requests Per Second) — количество запросов в секунду. 10k RPS — высокая нагрузка, характерная для крупных продуктов (поиск, чат-боты с миллионами пользователей).
  • P99 latency — 99-й перцентиль задержки: 99% запросов должны обрабатываться быстрее 200 мс. Это жёсткое SLA (Service Level Agreement).
  • P99 latency <200ms означает, что даже в худших условиях (перегрузка, сбои) система должна укладываться в 200 мс для 99% запросов.

Для достижения таких показателей необходима горизонтальная масштабируемость (добавление узлов), кэширование, геораспределение и оптимизация каждого этапа RAG-пайплайна.


2. Общая архитектура

Система состоит из нескольких слоёв:

  1. Входной слой: глобальный load balancer (например, AWS Global Accelerator или Cloudflare) с consistent hashing для привязки пользователя к региону.
  2. API Gateway: аутентификация, rate limiting, маршрутизация.
  3. Слой кэша: Redis (или Memcached) для горячих запросов и результатов retrieval.
  4. Слой retrieval: векторная БД (например, Qdrant, Pinecone, Weaviate) с read replicas в каждом регионе.
  5. Слой генерации: vLLM с continuous batching, развёрнутый на GPU-инстансах.
  6. Слой хранения: PostgreSQL для метаданных, S3 для сырых документов.

Каждый слой масштабируется независимо.


3. Multi-region deployment

Multi-region deployment — развёртывание идентичных копий системы в нескольких географических регионах (например, us-east, eu-west, ap-southeast).

Зачем

  • Снижение latency для пользователей (запрос идёт в ближайший регион).
  • Отказоустойчивость (при падении одного региона трафик перенаправляется в другой).
  • Балансировка нагрузки между регионами.

Реализация

  • Глобальный DNS-балансировщик (например, AWS Route53 с политикой latency-based routing).
  • Внутри региона — Kubernetes с Horizontal Pod Autoscaler (HPA) для автоматического масштабирования подов.
  • Consistent hashing на уровне load balancer гарантирует, что запросы одного пользователя попадают в один регион (для кэша и сессий).

Компромисс репликация данных между регионами увеличивает сложность и стоимость. Для RAG обычно достаточно реплицировать только векторную БД и кэш (асинхронно).


4. Кэширование (Redis)

Redisin-memory key-value store, используется для кэширования:

  • Горячих запросов (частые вопросы, популярные темы).
  • Результатов retrieval (эмбеддинги запросов и найденные документы).
  • Ответов LLM (для идентичных запросов).

Стратегия кэширования

  • Write-through при добавлении новых документов (обновление кэша).
  • TTL (Time To Live) — время жизни кэша (например, 5 минут для горячих запросов, 1 час для статичных документов).
  • LRU (Least Recently Used) — вытеснение старых записей при переполнении памяти.

Пример конфигурации Redis Cluster

# redis-cluster.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-config
data:
  redis.conf: |
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes
    maxmemory 10gb
    maxmemory-policy allkeys-lru

Ожидаемый эффект hit rate кэша >80% для популярных запросов, снижение нагрузки на retrieval и LLM в 5–10 раз.


5. Векторная БД: read replicas и шардирование

Для 10k RPS одна инстанция векторной БД не справится. Необходимы read replicas (реплики для чтения) и шардирование (распределение данных по шардам).

Архитектура

  • Primary (мастер) — принимает записи (индексация новых документов).
  • Read replicas (несколько в каждом регионе) — обслуживают запросы на поиск.
  • Шардирование по consistent hashing (например, по id документа) для равномерного распределения данных.

Пример настройки Qdrant

# qdrant-cluster.yaml
replicas: 3
shards: 8
replicationFactor: 2

Оптимизация retrieval

  • Использование бинарных эмбеддингов (binary embeddings) вместо float32 — снижение размера в 32 раза, ускорение поиска.
  • Настройка HNSW (Hierarchical Navigable Small World) параметров: ef_construct=200, M=16 для баланса скорости и точности.
  • Pre-filtering по метаданным (фильтр по дате, категории) перед векторным поиском.

Ожидаемая latency retrieval <10 мс на реплику при правильной настройке.


6. Инференс LLM: vLLM с continuous batching

vLLM — библиотека для эффективного инференса LLM, поддерживающая continuous batching (непрерывная пакетная обработка). В отличие от статического батчинга, vLLM динамически добавляет запросы в батч по мере их поступления, что увеличивает пропускную способность GPU.

Почему vLLM

  • PagedAttention — эффективное управление памятью KV-cache.
  • Continuous batching — утилизация GPU до 95%.
  • Поддержка quantization (квантизация) — FP16, INT8, AWQ для снижения latency.

Конфигурация для 10k RPS

  • Несколько GPU-инстансов (например, NVIDIA A100 или H100).
  • vLLM разворачивается как REST API (совместим с OpenAI API).
  • Autoscaling на основе длины очереди запросов.

Пример запуска vLLM

python -m vllm.entrypoints.openai.api_server \
    --model mistralai/Mistral-7B-Instruct-v0.3 \
    --tensor-parallel-size 4 \
    --max-num-batched-tokens 8192 \
    --max-num-seqs 256 \
    --gpu-memory-utilization 0.95 \
    --quantization awq \
    --port 8000

Ожидаемая latency генерации для коротких ответов (50–100 токенов) — 30–50 мс на один запрос при батчинге.


7. Балансировка нагрузки и consistent hashing

Load balancer распределяет запросы между регионами и инстансами. Consistent hashing (консистентное хеширование) минимизирует перераспределение запросов при добавлении/удалении узлов.

Реализация

  • Nginx с модулем ngx_http_upstream_consistent_hash или Envoy с ring_hash политикой.
  • Ключ хеширования — user_id или session_id для попадания в один кэш.

Пример конфигурации Nginx

upstream rag_backend {
    consistent_hash $arg_user_id;
    server region1:8000 weight=10;
    server region2:8000 weight=10;
}

Rate limiting на уровне API Gateway (например, Kong или AWS API Gateway) защищает от DDoS и превышения квот.


8. Мониторинг и алертинг

Для контроля P99 latency <200ms необходим мониторинг в реальном времени.

Метрики:

Инструменты

  • Prometheus + Grafana для сбора и визуализации.
  • Alertmanager для оповещений при превышении порогов (например, P99 >180 мс).

Пример дашборда Grafana

  • Панель "Latency heatmap" по регионам.
  • График "RPS vs P99" для выявления корреляции.

9. Оптимизация retrieval (бинарные эмбеддинги, ANN параметры)

Бинарные эмбеддинги — квантование float32 векторов до 1 бита (0/1). Размер уменьшается в 32 раза, скорость поиска возрастает в 10–20 раз за счёт использования XOR и popcount инструкций CPU.

Пример использования в Qdrant

from qdrant_client import QdrantClient
client = QdrantClient(host="localhost", port=6333)
client.create_collection(
    collection_name="docs",
    vectors_config={
        "size": 768,
        "distance": "Dot",
        "quantization_config": {
            "binary": True
        }
    }
)

ANN (Approximate Nearest Neighbor) параметры:

  • HNSW: ef_construct=200, M=16 для индексации; ef=128 для поиска.
  • IVF (Inverted File Index): nlist=4096, nprobe=10 для ускорения.

Trade-off бинарные эмбеддинги снижают recall на 1–3%, но дают 10x ускорение. Для 10k RPS это оправдано.


10. Обработка отказов и деградация

Circuit breaker (автоматическое отключение проблемного компонента) и fallback (запасной вариант) критичны для SLA.

Сценарии

  • Отказ векторной БД → fallback на кэш (если есть) или на BM25 (keyword search) из Elasticsearch.
  • Отказ LLM → возврат кэшированного ответа или сообщение "временно недоступно".
  • Превышение latencytimeout (например, 150 мс на retrieval, 50 мс на генерацию) и возврат частичного ответа.

Реализация circuit breaker

import pybreaker
breaker = pybreaker.CircuitBreaker(fail_max=5, reset_timeout=30)

@breaker
def call_llm(prompt):
    # вызов vLLM
    pass

11. Стоимость и компромиссы

КомпонентСтоимость (приблизительно)Комментарий
GPU (vLLM)$10–30/час за A100Основной расход
Redis Cluster$500–2000/месЗависит от памяти
Векторная БД$1000–5000/месЗависит от размера данных
Load balancer + сеть$200–1000/месВключая межрегиональный трафик

Компромиссы

  • Multi-region увеличивает стоимость в 2–3 раза, но даёт низкую latency и отказоустойчивость.
  • Кэширование снижает нагрузку на GPU, но требует памяти.
  • Бинарные эмбеддинги жертвуют точностью ради скорости.

Пет-проект для закрепления

Задача Развернуть прототип RAG-системы, способной выдержать 1000 RPS (масштабируемый до 10k) с P99 latency <500 мс на локальной машине или облаке.

Инструменты

Шаги:

  1. Развернуть Qdrant с read replicas (2 реплики) и загрузить 100k документов.
  2. Настроить Redis для кэширования результатов retrieval (TTL=60 сек).
  3. Запустить vLLM с моделью Mistral-7B (quantized AWQ) на одном GPU.
  4. Написать API-сервер на FastAPI, который принимает запрос, проверяет кэш, ищет в Qdrant, генерирует ответ.
  5. Настроить Nginx с consistent hashing по user_id.
  6. Запустить Locust с 1000 concurrent users и измерить P99 latency.

Ожидаемый результат P99 latency <500 мс при 1000 RPS. Анализ узких мест (GPU utilization, cache hit ratio) и оптимизация (увеличение replicas, настройка HNSW).


Связь с другими вопросами

ВопросТема
235Оптимизация latency RAG-системы
237Выбор векторной БД для high-load
238Деплой LLM в production
239Нагрузочное тестирование RAG
240Отказоустойчивость RAG-системы

Навигация