2025-11-19 18:46:48 +03:00
|
|
|
|
# Redis vs PostgreSQL: Когда что использовать?
|
|
|
|
|
|
|
|
|
|
|
|
## Скорость доступа
|
|
|
|
|
|
|
|
|
|
|
|
### Redis:
|
|
|
|
|
|
- ⚡ **0.1-1 мс** (данные в памяти)
|
|
|
|
|
|
- Мгновенный доступ
|
|
|
|
|
|
- Идеально для частых чтений
|
|
|
|
|
|
|
|
|
|
|
|
### PostgreSQL:
|
|
|
|
|
|
- 🐢 **1-10 мс** (с индексами)
|
|
|
|
|
|
- Зависит от нагрузки и индексов
|
|
|
|
|
|
- Но всё равно очень быстро
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Когда Redis имеет смысл
|
|
|
|
|
|
|
|
|
|
|
|
### ✅ Используй Redis, если:
|
|
|
|
|
|
|
|
|
|
|
|
1. **Очень частые чтения** (каждый запрос, каждый клик)
|
|
|
|
|
|
- Например: счетчики, rate limiting, сессии
|
|
|
|
|
|
|
|
|
|
|
|
2. **Временные данные** (TTL, автоочистка)
|
|
|
|
|
|
- Например: SMS коды, временные токены
|
|
|
|
|
|
|
|
|
|
|
|
3. **Кеширование результатов запросов**
|
|
|
|
|
|
- Например: результаты AI классификации, шаблоны визардов
|
|
|
|
|
|
|
|
|
|
|
|
4. **Pub/Sub события** (реал-тайм)
|
|
|
|
|
|
- Например: `ocr_events:{claim_id}` для SSE
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Когда PostgreSQL достаточно
|
|
|
|
|
|
|
|
|
|
|
|
### ✅ Используй только PostgreSQL, если:
|
|
|
|
|
|
|
|
|
|
|
|
1. **Данные читаются не так часто**
|
|
|
|
|
|
- Загрузка страницы, переход между шагами
|
|
|
|
|
|
- Пользователь не заметит разницу 1-10 мс
|
|
|
|
|
|
|
|
|
|
|
|
2. **Важна консистентность**
|
|
|
|
|
|
- Нужна гарантия актуальности данных
|
|
|
|
|
|
- Нет риска рассинхронизации
|
|
|
|
|
|
|
|
|
|
|
|
3. **Данные уже в PostgreSQL**
|
|
|
|
|
|
- Не нужно дублировать
|
|
|
|
|
|
- Проще архитектура
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Для веб-формы: Анализ использования
|
|
|
|
|
|
|
|
|
|
|
|
### Когда читаются данные заявки:
|
|
|
|
|
|
|
|
|
|
|
|
1. **При загрузке страницы** (1 раз)
|
|
|
|
|
|
- Пользователь открывает форму
|
|
|
|
|
|
- Можно загрузить из PostgreSQL (10 мс) - не критично
|
|
|
|
|
|
|
|
|
|
|
|
2. **При переходах между шагами** (редко)
|
|
|
|
|
|
- Пользователь нажимает "Далее"
|
|
|
|
|
|
- Можно загрузить из PostgreSQL (10 мс) - не критично
|
|
|
|
|
|
|
|
|
|
|
|
3. **При обновлении данных** (редко)
|
|
|
|
|
|
- Пользователь заполняет форму
|
|
|
|
|
|
- Сохраняется в PostgreSQL
|
|
|
|
|
|
|
|
|
|
|
|
### Вывод:
|
|
|
|
|
|
- ❌ **НЕ критично по скорости** - пользователь не заметит разницу
|
|
|
|
|
|
- ✅ **Важнее консистентность** - данные всегда актуальные
|
|
|
|
|
|
- ✅ **Проще архитектура** - один источник истины
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Компромиссное решение
|
|
|
|
|
|
|
|
|
|
|
|
### Вариант: Кеширование в Redis с инвалидацией
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
# При чтении данных заявки
|
|
|
|
|
|
async def get_claim(claim_id: str):
|
|
|
|
|
|
# 1. Пробуем Redis (быстро)
|
|
|
|
|
|
cached = await redis.get(f"claim:{claim_id}")
|
|
|
|
|
|
if cached:
|
|
|
|
|
|
return json.loads(cached)
|
|
|
|
|
|
|
|
|
|
|
|
# 2. Если нет в кеше - из PostgreSQL
|
|
|
|
|
|
claim = await db.get_claim(claim_id)
|
|
|
|
|
|
|
|
|
|
|
|
# 3. Сохраняем в кеш на 1 час
|
|
|
|
|
|
await redis.set(f"claim:{claim_id}", json.dumps(claim), ttl=3600)
|
|
|
|
|
|
|
|
|
|
|
|
return claim
|
|
|
|
|
|
|
|
|
|
|
|
# При обновлении данных
|
|
|
|
|
|
async def update_claim(claim_id: str, data: dict):
|
|
|
|
|
|
# 1. Обновляем PostgreSQL
|
|
|
|
|
|
await db.update_claim(claim_id, data)
|
|
|
|
|
|
|
|
|
|
|
|
# 2. Инвалидируем кеш (удаляем из Redis)
|
|
|
|
|
|
await redis.delete(f"claim:{claim_id}")
|
|
|
|
|
|
|
|
|
|
|
|
# Или обновляем кеш сразу
|
|
|
|
|
|
await redis.set(f"claim:{claim_id}", json.dumps(data), ttl=3600)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Плюсы:
|
|
|
|
|
|
- ✅ Быстрый доступ (если есть в кеше)
|
|
|
|
|
|
- ✅ Актуальные данные (инвалидация при обновлении)
|
|
|
|
|
|
- ✅ Fallback на PostgreSQL (если кеш пуст)
|
|
|
|
|
|
|
|
|
|
|
|
### Минусы:
|
|
|
|
|
|
- ❌ Дополнительная сложность
|
|
|
|
|
|
- ❌ Нужно инвалидировать кеш при каждом обновлении
|
|
|
|
|
|
- ❌ Риск устаревших данных (если забыли инвалидировать)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Рекомендация для веб-формы
|
|
|
|
|
|
|
|
|
|
|
|
### Вариант 1: Только PostgreSQL (рекомендую)
|
|
|
|
|
|
|
|
|
|
|
|
**Когда использовать:**
|
|
|
|
|
|
- Данные читаются не так часто (загрузка страницы, переходы)
|
|
|
|
|
|
- Важна консистентность
|
|
|
|
|
|
- Простота архитектуры важнее скорости
|
|
|
|
|
|
|
|
|
|
|
|
**Плюсы:**
|
|
|
|
|
|
- ✅ Просто (один источник данных)
|
|
|
|
|
|
- ✅ Всегда актуальные данные
|
|
|
|
|
|
- ✅ Нет рассинхронизации
|
|
|
|
|
|
- ✅ PostgreSQL с индексами всё равно быстро (1-10 мс)
|
|
|
|
|
|
|
|
|
|
|
|
**Минусы:**
|
|
|
|
|
|
- ❌ Чуть медленнее, чем Redis (но не критично)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### Вариант 2: PostgreSQL + Redis кеш (если нужна скорость)
|
|
|
|
|
|
|
|
|
|
|
|
**Когда использовать:**
|
|
|
|
|
|
- Очень частые чтения (каждый запрос)
|
|
|
|
|
|
- Критична скорость (но для веб-формы это не так)
|
|
|
|
|
|
|
|
|
|
|
|
**Плюсы:**
|
|
|
|
|
|
- ✅ Быстрый доступ (0.1-1 мс)
|
|
|
|
|
|
- ✅ Меньше нагрузки на PostgreSQL
|
|
|
|
|
|
|
|
|
|
|
|
**Минусы:**
|
|
|
|
|
|
- ❌ Сложнее (нужна инвалидация кеша)
|
|
|
|
|
|
- ❌ Риск устаревших данных
|
|
|
|
|
|
- ❌ Больше кода для поддержки
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Итог
|
|
|
|
|
|
|
|
|
|
|
|
### Для веб-формы:
|
|
|
|
|
|
|
|
|
|
|
|
**Рекомендую: Только PostgreSQL**
|
|
|
|
|
|
|
|
|
|
|
|
**Почему:**
|
|
|
|
|
|
1. ⚡ PostgreSQL с индексами быстро (1-10 мс) - пользователь не заметит
|
|
|
|
|
|
2. ✅ Всегда актуальные данные (нет рассинхронизации)
|
|
|
|
|
|
3. ✅ Проще архитектура (один источник истины)
|
|
|
|
|
|
4. ✅ Данные читаются не так часто (не каждый запрос)
|
|
|
|
|
|
|
|
|
|
|
|
**Redis используй только для:**
|
|
|
|
|
|
- ✅ Pub/Sub (`ocr_events:{claim_id}`) - события в реальном времени
|
|
|
|
|
|
- ✅ Кеширование AI ответов (классификация, визарды) - если нужно
|
|
|
|
|
|
- ✅ SMS коды, временные токены - с TTL
|
|
|
|
|
|
|
|
|
|
|
|
**НЕ используй Redis для:**
|
|
|
|
|
|
- ❌ Основных данных заявки (есть в PostgreSQL)
|
|
|
|
|
|
- ❌ Документов (есть в PostgreSQL)
|
|
|
|
|
|
- ❌ Ответов визарда (есть в PostgreSQL)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Если всё-таки нужен Redis кеш
|
|
|
|
|
|
|
|
|
|
|
|
Можно добавить опциональное кеширование:
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
# В n8n workflow после claimsave
|
|
|
|
|
|
if (channel === 'web_form' && enable_cache === true) {
|
|
|
|
|
|
// Опционально: кешируем в Redis на 1 час
|
|
|
|
|
|
await redis.set(
|
|
|
|
|
|
`claim:${claim_id}`,
|
|
|
|
|
|
JSON.stringify(claim_data),
|
|
|
|
|
|
ttl=3600
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Но это опционально и не обязательно для веб-формы.
|
|
|
|
|
|
|
2025-11-21 15:57:18 +03:00
|
|
|
|
|
2025-11-24 13:36:14 +03:00
|
|
|
|
|