Виды шардирования

Самая главная проблема шардирования — как приложению понять, на каком именно сервере лежит нужный пользователь? Для этого используют ключ шардирования (Shard Key) и один из трех алгоритмов.

1. Range-based Sharding (По диапазонам)

Данные разбиваются по логическим диапазонам значений ключа. Например, пользователи с ID от 1 до 1М идут на первый шард, от 1М до 2М — на второй.

  • Плюсы: Отлично подходит для range-запросов (например, «достать все заказы за апрель», если ключ — это дата). Легко добавлять новые шарды для новых диапазонов.
  • Минусы: Огромный риск появления горячих шардов. Если мы шардируем по дате, то шард «Текущий месяц» будет перегружен, а старые шарды будут простаивать.
2. Hash-based Sharding (Хеширование)

Мы применяем хеш-функцию к ключу (например, UserID) и делим по модулю на количество серверов. shard_number = hash(user_id) % total_shards.

  • Плюсы: Идеально равномерное распределение данных. Нет перегруженных серверов, так как хеш размазывает нагрузку.
  • Минусы: Нельзя делать range-запросы. Но самая главная боль — добавление нового сервера. Если total_shards меняется с 3 на 4, хеш-функция выдаст новые результаты для всех пользователей. Придется переносить 90% базы данных. (Эту проблему решает алгоритм Consistent Hashing).

Подробнее про консистентное хеширование можешь почитать в этой статье

3. Directory-based Sharding (Lookup Table)

Используется отдельная маленькая база данных (таблица маршрутизации), в которой жестко прописано сопоставление: «User A живет на сервере 3».

  • Плюсы: Максимальная гибкость. Можно переносить конкретных тяжелых юзеров на выделенные сервера без изменения общей логики приложения.
  • Минусы: Сама таблица маршрутизации (Lookup Table) становится узким местом и точкой отказа (Single Point of Failure). Приложению приходится делать два сетевых прыжка вместо одного.

Индустриальный стандарт: Virtual Buckets.

В современном BigTech данные почти никогда не мапят напрямую на физический сервер. Сначала данные хешируют в большое количество логических шардов (buckets) (например, 4096 бакетов). А уже эти бакеты таблицей маршрутизации распределяют по физическим серверам. Это позволяет легко перекидывать бакеты между серверами при масштабировании.