В чем разница между шардированием и репликацией
Что проверяют
Понимаете ли вы, какую задачу решает каждый подход: репликация про доступность и масштабирование чтения, шардирование про объём данных и масштабирование записи. Следом обычно спрашивают, как это выглядит со стороны Java-приложения и что будет с чтением сразу после записи.
Как отвечать
- репликация: одни и те же данные лежат на нескольких узлах. Классическая схема: запись идёт на primary, чтение можно разнести по репликам. Бывает синхронной (запись подтверждается после реплики, надёжно, но медленнее) и асинхронной (быстро, но с лагом). При падении primary реплику продвигают в лидеры, в PostgreSQL для этого часто берут Patroni;
- шардирование: данные делятся по ключу, каждый шард хранит свою часть. Ключ выбирают так, чтобы нагрузка распределялась ровно, а типовой запрос попадал в один шард, например хэш от
user_id. Цена: запросы и транзакции через несколько шардов, перебалансировка при добавлении узлов.
В проде подходы комбинируют: каждый шард сам по себе реплицируется. Со стороны Java чтение с реплик часто делают через AbstractRoutingDataSource, направляя @Transactional(readOnly = true) на реплику. Шардирование решают либо в приложении (Apache ShardingSphere), либо на стороне хранилища: Citus для PostgreSQL, Vitess для MySQL, встроенное распределение данных в MongoDB и Cassandra.
Где спотыкаются
Говорят, что репликация масштабирует запись. Нет: при одном primary вся запись по-прежнему идёт в один узел, реплики лишь повторяют её.
Забывают про лаг асинхронной реплики. Пользователь сохранил профиль, следующий запрос ушёл на реплику и вернул старые данные. Решение: читать собственные свежие записи с primary или ждать, пока реплика догонит нужную позицию журнала.
Путают шардирование с партиционированием. Декларативное партиционирование в PostgreSQL делит таблицу на части внутри одного сервера, а шардирование разносит данные по разным.