core/docs/redis-schema.md
2025-06-16 20:20:23 +03:00

15 KiB
Raw Permalink Blame History

Схема данных Redis в Discours.io

Обзор

Redis используется как основное хранилище для кэширования, сессий, токенов и временных данных. Все ключи следуют структурированным паттернам для обеспечения консистентности и производительности.

Принципы именования ключей

Общие правила

  • Использование двоеточия : как разделителя иерархии
  • Формат: {category}:{type}:{identifier} или {entity}:{property}:{value}
  • Константное время поиска через точные ключи
  • TTL для всех временных данных

Категории данных

  1. Аутентификация: session:*, oauth_*, env_vars:*
  2. Кэш сущностей: author:*, topic:*, shout:*
  3. Поиск: search_cache:*
  4. Просмотры: migrated_views_*, viewed_*
  5. Уведомления: publish/subscribe каналы

1. Система аутентификации

1.1 Сессии пользователей

Структура ключей

session:{user_id}:{jwt_token}        # HASH - данные сессии
user_sessions:{user_id}              # SET - список активных токенов пользователя
{user_id}-{username}-{token}         # STRING - legacy формат (deprecated)

Данные сессии (HASH)

HGETALL session:123:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...

Поля:

  • user_id: ID пользователя (string)
  • username: Имя пользователя (string)
  • token_type: "session" (string)
  • created_at: Unix timestamp создания (string)
  • last_activity: Unix timestamp последней активности (string)
  • auth_data: JSON строка с данными авторизации (string, optional)
  • device_info: JSON строка с информацией об устройстве (string, optional)

TTL: 30 дней (2592000 секунд)

Список токенов пользователя (SET)

SMEMBERS user_sessions:123

Содержимое: JWT токены активных сессий пользователя TTL: 30 дней

1.2 OAuth токены

Структура ключей

oauth_access:{user_id}:{provider}    # STRING - access токен
oauth_refresh:{user_id}:{provider}   # STRING - refresh токен
oauth_state:{state}                  # HASH - временное состояние OAuth flow

Access токены

Провайдеры: google, github, facebook, twitter, telegram, vk, yandex TTL: 1 час (3600 секунд) Пример:

GET oauth_access:123:google
# Возвращает: access_token_string

Refresh токены

TTL: 30 дней (2592000 секунд) Пример:

GET oauth_refresh:123:google
# Возвращает: refresh_token_string

OAuth состояние (временное)

HGETALL oauth_state:a1b2c3d4e5f6

Поля:

  • redirect_uri: URL для перенаправления после авторизации
  • csrf_token: CSRF защита
  • provider: Провайдер OAuth
  • created_at: Время создания

TTL: 10 минут (600 секунд)

1.3 Токены подтверждения

Структура ключей

verification:{user_id}:{type}:{token}    # HASH - данные токена подтверждения

Типы подтверждения

  • email_verification: Подтверждение email
  • phone_verification: Подтверждение телефона
  • password_reset: Сброс пароля
  • email_change: Смена email

Поля токена:

  • user_id: ID пользователя
  • token_type: Тип токена
  • verification_type: Тип подтверждения
  • created_at: Время создания
  • data: JSON с дополнительными данными

TTL: 1 час (3600 секунд)

2. Переменные окружения

Структура ключей

env_vars:{variable_name}             # STRING - значение переменной

Примеры переменных

GET env_vars:JWT_SECRET              # Секретный ключ JWT
GET env_vars:REDIS_URL               # URL Redis
GET env_vars:OAUTH_GOOGLE_CLIENT_ID  # Google OAuth Client ID
GET env_vars:FEATURE_REGISTRATION    # Флаг функции регистрации

Категории переменных:

  • database: DB_URL, POSTGRES_*
  • auth: JWT_SECRET, OAUTH_*
  • redis: REDIS_URL, REDIS_HOST, REDIS_PORT
  • search: SEARCH_API_KEY, ELASTICSEARCH_URL
  • integrations: GOOGLE_ANALYTICS_ID, SENTRY_DSN, SMTP_*
  • security: CORS_ORIGINS, ALLOWED_HOSTS
  • logging: LOG_LEVEL, DEBUG
  • features: FEATURE_*

TTL: Без ограничения (постоянное хранение)

3. Кэш сущностей

3.1 Авторы (пользователи)

Структура ключей

author:id:{author_id}                # STRING - JSON данные автора
author:slug:{author_slug}            # STRING - ID автора по slug
author:followers:{author_id}         # STRING - JSON массив подписчиков
author:follows-topics:{author_id}    # STRING - JSON массив отслеживаемых тем
author:follows-authors:{author_id}   # STRING - JSON массив отслеживаемых авторов
author:follows-shouts:{author_id}    # STRING - JSON массив отслеживаемых публикаций

Данные автора (JSON)

{
  "id": 123,
  "email": "user@example.com",
  "name": "Имя Пользователя",
  "slug": "username",
  "pic": "https://example.com/avatar.jpg",
  "bio": "Описание автора",
  "email_verified": true,
  "created_at": 1640995200,
  "updated_at": 1640995200,
  "last_seen": 1640995200,
  "stat": {
    "topics": 15,
    "authors": 8,
    "shouts": 42
  }
}

Подписчики автора

[123, 456, 789]  // Массив ID подписчиков

Подписки автора

// author:follows-topics:123
[1, 5, 10, 15]  // ID отслеживаемых тем

// author:follows-authors:123
[45, 67, 89]    // ID отслеживаемых авторов

// author:follows-shouts:123
[101, 102, 103] // ID отслеживаемых публикаций

TTL: Без ограничения (инвалидация при изменениях)

3.2 Темы

Структура ключей

topic:id:{topic_id}                  # STRING - JSON данные темы
topic:slug:{topic_slug}              # STRING - JSON данные темы
topic:authors:{topic_id}             # STRING - JSON массив авторов темы
topic:followers:{topic_id}           # STRING - JSON массив подписчиков темы
topic_shouts_{topic_id}              # STRING - JSON массив публикаций темы (legacy)

Данные темы (JSON)

{
  "id": 5,
  "title": "Название темы",
  "slug": "tema-slug",
  "description": "Описание темы",
  "pic": "https://example.com/topic.jpg",
  "community": 1,
  "created_at": 1640995200,
  "updated_at": 1640995200,
  "stat": {
    "shouts": 150,
    "authors": 25,
    "followers": 89
  }
}

Авторы темы

[123, 456, 789]  // ID авторов, писавших в теме

Подписчики темы

[111, 222, 333, 444]  // ID подписчиков темы

TTL: Без ограничения (инвалидация при изменениях)

3.3 Публикации (Shouts)

Структура ключей

shouts:{params_hash}                 # STRING - JSON массив публикаций
topic_shouts_{topic_id}              # STRING - JSON массив публикаций темы

Примеры ключей публикаций

shouts:limit=20:offset=0:sort=created_at  # Последние публикации
shouts:author=123:limit=10                # Публикации автора
shouts:topic=5:featured=true              # Рекомендуемые публикации темы

TTL: 5 минут (300 секунд)

4. Поисковый кэш

Структура ключей

search_cache:{normalized_query}      # STRING - JSON результаты поиска

Нормализация запроса

  • Приведение к нижнему регистру
  • Удаление лишних пробелов
  • Сортировка параметров

Данные поиска (JSON)

{
  "query": "поисковый запрос",
  "results": [
    {
      "type": "shout",
      "id": 123,
      "title": "Заголовок публикации",
      "slug": "publication-slug",
      "score": 0.95
    }
  ],
  "total": 15,
  "cached_at": 1640995200
}

TTL: 10 минут (600 секунд)

5. Система просмотров

Структура ключей

migrated_views_{timestamp}           # HASH - просмотры публикаций
migrated_views_slugs                 # HASH - маппинг slug -> id
viewed:{shout_id}                    # STRING - счетчик просмотров

Мигрированные просмотры (HASH)

HGETALL migrated_views_1640995200

Поля:

  • {shout_id}: количество просмотров (string)
  • _timestamp: время создания записи
  • _total: общее количество записей

Маппинг slug -> ID

HGETALL migrated_views_slugs

Поля: {shout_slug} -> {shout_id}

TTL: Без ограничения (данные аналитики)

6. Pub/Sub каналы

Каналы уведомлений

notifications:{user_id}              # Персональные уведомления
notifications:global                 # Глобальные уведомления
notifications:topic:{topic_id}       # Уведомления темы
notifications:shout:{shout_id}       # Уведомления публикации

Структура сообщения (JSON)

{
  "type": "notification_type",
  "user_id": 123,
  "entity_type": "shout",
  "entity_id": 456,
  "action": "created|updated|deleted",
  "data": {
    "title": "Заголовок",
    "author": "Автор"
  },
  "timestamp": 1640995200
}

7. Временные данные

Ключи блокировок

lock:{operation}:{entity_id}         # STRING - блокировка операции

TTL: 30 секунд (автоматическое снятие блокировки)

Ключи состояния

state:{process}:{identifier}         # HASH - состояние процесса

TTL: От 1 минуты до 1 часа в зависимости от процесса

8. Мониторинг и статистика

Ключи метрик

metrics:{metric_name}:{period}       # STRING - значение метрики
stats:{entity}:{timeframe}           # HASH - статистика сущности

Примеры метрик

metrics:active_sessions:hourly       # Количество активных сессий
metrics:cache_hits:daily             # Попадания в кэш за день
stats:topics:weekly                  # Статистика тем за неделю

TTL: От 1 часа до 30 дней в зависимости от типа метрики

9. Оптимизация и производительность

Пакетные операции

Используются Redis pipelines для атомарных операций:

# Пример создания сессии
commands = [
    ("hset", (token_key, "user_id", user_id)),
    ("hset", (token_key, "created_at", timestamp)),
    ("expire", (token_key, ttl)),
    ("sadd", (user_tokens_key, token)),
]
await redis.execute_pipeline(commands)

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

  1. Write-through: Немедленное обновление кэша при изменении данных
  2. Cache-aside: Lazy loading с обновлением при промахе
  3. Write-behind: Отложенная запись в БД

Инвалидация кэша

  • Точечная: Удаление конкретных ключей при изменениях
  • По префиксу: Массовое удаление связанных ключей
  • TTL: Автоматическое истечение для временных данных

10. Мониторинг

Команды диагностики

# Статистика использования памяти
redis-cli info memory

# Количество ключей по типам
redis-cli --scan --pattern "session:*" | wc -l
redis-cli --scan --pattern "author:*" | wc -l
redis-cli --scan --pattern "topic:*" | wc -l

# Размер конкретного ключа
redis-cli memory usage session:123:token...

# Анализ истечения ключей
redis-cli --scan --pattern "*" | xargs -I {} redis-cli ttl {}

Проблемы и решения

  1. Память: Использование TTL для временных данных
  2. Производительность: Pipeline операции, connection pooling
  3. Консистентность: Транзакции для критических операций
  4. Масштабирование: Шардирование по user_id для сессий

11. Безопасность

Принципы

  • TTL для всех временных данных предотвращает накопление мусора
  • Раздельное хранение секретных данных (токены) и публичных (кэш)
  • Использование pipeline для атомарных операций
  • Регулярная очистка истекших ключей

Рекомендации

  • Мониторинг использования памяти Redis
  • Backup критичных данных (переменные окружения)
  • Ограничение размера значений для предотвращения OOM
  • Использование отдельных баз данных для разных типов данных