English translation is not available yet. Showing Russian content.
Как вы проектируете 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. Общая архитектура
Система состоит из нескольких слоёв:
- Входной слой: глобальный load balancer (например, AWS Global Accelerator или Cloudflare) с consistent hashing для привязки пользователя к региону.
- API Gateway: аутентификация, rate limiting, маршрутизация.
- Слой кэша: Redis (или Memcached) для горячих запросов и результатов retrieval.
- Слой retrieval: векторная БД (например, Qdrant, Pinecone, Weaviate) с read replicas в каждом регионе.
- Слой генерации: vLLM с continuous batching, развёрнутый на GPU-инстансах.
- Слой хранения: 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)
Redis — in-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 необходим мониторинг в реальном времени.
Метрики:
- P50, P95, P99 latency каждого этапа (retrieval, генерация, общее время).
- RPS по регионам и эндпоинтам.
- Cache hit ratio.
- GPU utilization и queue length vLLM.
- Error rate (5xx, timeout).
Инструменты
- Prometheus + Grafana для сбора и визуализации.
- Alertmanager для оповещений при превышении порогов (например, P99 >180 мс).
Пример дашборда Grafana
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 → возврат кэшированного ответа или сообщение "временно недоступно".
- Превышение latency → timeout (например, 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 мс на локальной машине или облаке.
Инструменты
- Docker Compose или Minikube для оркестрации.
- Redis (кэш), Qdrant (векторная БД), vLLM (LLM), Nginx (балансировщик).
- Locust для генерации нагрузки.
Шаги:
- Развернуть Qdrant с read replicas (2 реплики) и загрузить 100k документов.
- Настроить Redis для кэширования результатов retrieval (TTL=60 сек).
- Запустить vLLM с моделью Mistral-7B (quantized AWQ) на одном GPU.
- Написать API-сервер на FastAPI, который принимает запрос, проверяет кэш, ищет в Qdrant, генерирует ответ.
- Настроить Nginx с consistent hashing по user_id.
- Запустить 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-системы |
Навигация
- Предыдущий: 235
- Следующий: 237
- Индекс: 00. Индекс разборов