Ответ
Шардирование (или секционирование) — это техника горизонтального масштабирования баз данных, при которой данные разделяются и хранятся на нескольких независимых серверах (шардах). Каждый шард содержит свою часть данных.
Плюсы:
- Горизонтальное масштабирование и производительность: Позволяет распределить нагрузку по множеству серверов, обрабатывая запросы параллельно. Это решает проблему производительности, когда один сервер (вертикальное масштабирование) перестает справляться с нагрузкой.
- Повышенная доступность и отказоустойчивость: Выход из строя одного шарда не приводит к отказу всей системы. Часть данных и функциональности останется доступной, пока ведутся работы по восстановлению сбойного узла.
Минусы:
- Сложность реализации и поддержки: Требуется разработка логики для маршрутизации запросов к нужному шарду. Усложняются операции резервного копирования, восстановления, мониторинга и миграции схемы данных.
- Сложность запросов: Выполнение запросов, затрагивающих несколько шардов (например,
JOIN
между таблицами на разных шардах), становится крайне неэффективным или невозможным. Часто это требует денормализации данных или агрегации результатов на уровне приложения. - Проблема "горячих" шардов (Hotspots): При неудачном выборе ключа шардирования нагрузка может распределяться неравномерно. Один шард может стать "горячим", принимая на себя большую часть запросов и становясь узким местом.
- Распределенные транзакции: Обеспечение ACID-транзакций на нескольких шардах — сложная задача, требующая использования двухфазного коммита (two-phase commit) или других сложных паттернов, что снижает производительность.
Пример ключа шардирования в Go
Простейший способ — шардирование по хэшу (остатку от деления). Например, по ID пользователя:
// getShardID определяет номер шарда для данного userID
func getShardID(userID int64, numShards int) int {
// Простой, но не самый лучший способ
return int(userID % int64(numShards))
}
Важное замечание: Указанный выше подход имеет серьезный недостаток: при изменении количества шардов (numShards
) почти все данные придется перемещать, так как изменится результат вычисления остатка для большинства userID
.
Для решения этой проблемы в реальных системах используют консистентное хеширование (Consistent Hashing), которое минимизирует количество перемещаемых ключей при добавлении или удалении серверов.