Как определить, в какой шард должны попадать данные?

«Как определить, в какой шард должны попадать данные?» — вопрос из категории Распределенные системы, который задают на 33% собеседований Data Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Выбор стратегии шардирования зависит от паттернов доступа и требований к данным. Основные подходы:

  1. Шардирование по диапазону (Range-based): Данные распределяются по интервалам ключа (например, по дате или ID пользователя).

    • Плюсы: Упрощает запросы по диапазонам (например, WHERE date BETWEEN ...).
    • Минусы: Риск неравномерной нагрузки (hotspot), если данные или запросы сконцентрированы в одном диапазоне.
      -- Пример: создание партиций по году для PostgreSQL
      CREATE TABLE orders_2024 PARTITION OF orders
      FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
  2. Шардирование по хешу (Hash-based): Шард вычисляется с помощью хеш-функции от ключа (например, user_id).

    • Плюсы: Обеспечивает равномерное распределение данных и нагрузки.
    • Минусы: Запросы по диапазону требуют обращения ко всем шардам.
      def get_shard_id(key: str, total_shards: int) -> int:
      # Используем устойчивый хеш (например, из библиотеки hashlib)
      hash_value = int(hashlib.sha256(key.encode()).hexdigest(), 16)
      return hash_value % total_shards
  3. Шардирование по справочнику (Directory-based): Используется отдельная lookup-таблица (например, в Redis или отдельной БД), которая хранит соответствие ключа шарду.

    • Плюсы: Максимальная гибкость, можно динамически переносить данные между шардами.
    • Минусы: Дополнительная точка отказа и задержка на обращение к справочнику.

Критерии выбора:

  • Равномерность нагрузки: Избегайте hotspots. Hash-based часто лучший выбор для OLTP.
  • Локализация запросов: Если часты запросы по диапазону, рассмотрите range-based.
  • Горизонтальное масштабирование: Убедитесь, что стратегия позволяет легко добавлять новые шарды (hash-based с консистентным хешированием решает эту проблему).
  • Сложность операций: JOIN данных из разных шардов (cross-shard) сложен и медлителен, проектируйте схему так, чтобы связанные данные находились в одном шарде.