Ограничения реляционной модели и теорема CAP
Реляционная модель доминирует десятилетиями, но у неё есть границы. Разберём, где они проходят и почему распределённость заставляет выбирать между согласованностью и доступностью.
Теорема CAP: распределённая система не может одновременно гарантировать все три свойства — согласованность (Consistency), доступность (Availability) и устойчивость к разделению сети (Partition tolerance). При сетевом разделении приходится жертвовать либо согласованностью, либо доступностью.
Где реляционная модель упирается в потолок
Реляционные СУБД великолепны для структурированных данных с чёткой схемой, сложными связями и сильными гарантиями (ACID). Но у подхода есть болевые точки, которые особенно обостряются на больших масштабах:
- Горизонтальное масштабирование. Реляционную базу легко масштабировать вертикально (мощнее сервер), но трудно горизонтально (раскидать данные по многим машинам). Соединения, транзакции и ссылочная целостность между узлами стоят дорого: чтобы выполнить транзакцию над данными на разных серверах, нужна сложная координация.
- Жёсткая схема. Схему нужно задать заранее, а её изменение на огромных таблицах болезненно. Для быстро меняющихся, разнородных данных это неудобно.
- Плохо ложащиеся данные. Иерархические документы, графы связей, поток событий — всё это в таблицы укладывается с трудом и множеством соединений.
Эти ограничения не делают реляционную модель «плохой» — они очерчивают область, где имеет смысл искать альтернативы. И корень многих ограничений — в физике распределённых систем, которую формализует теорема CAP.
Почему горизонтальное масштабирование так трудно
Стоит понять корень проблемы, потому что из него растёт весь современный ландшафт. Вертикальное масштабирование (поставить сервер мощнее) просто, но упирается в потолок: самый дорогой сервер всё равно конечен, а данные растут. Горизонтальное (раскидать данные по многим обычным машинам) потолка почти не имеет — но даётся реляционной модели тяжело именно из-за её сильных сторон. Соединение двух таблиц, лежащих на разных серверах, требует гонять данные по сети. Транзакция, меняющая данные на нескольких узлах, требует, чтобы все узлы согласованно зафиксировали или откатили изменения, — это дорогой распределённый протокол. Ссылочная целостность между узлами — постоянная сетевая проверка. То есть ровно те гарантии, ради которых мы любим реляционные базы (ACID, связи, целостность), становятся неподъёмно дорогими, когда данные размазаны по сети. NoSQL решает это радикально — отказываясь от части гарантий; NewSQL — изобретая хитрые протоколы, чтобы сохранить гарантии при распределённости. А неизбежность сетевых сбоев в распределённой системе формализует теорема CAP, к которой и переходим.
Три свойства CAP
Эрик Брюэр сформулировал, что у распределённого хранилища есть три желанных свойства, но все три сразу недостижимы.
| Свойство | Что означает |
| Consistency (согласованность) | Любое чтение возвращает самые свежие данные; все узлы видят одно и то же |
| Availability (доступность) | Каждый запрос получает ответ (не ошибку), даже если часть узлов недоступна |
| Partition tolerance (устойчивость к разделению) | Система продолжает работать, даже если сеть распалась на изолированные части |
Важно уточнить: согласованность в CAP — это не та же буква C, что в ACID. В CAP речь о том, что все узлы распределённой системы согласованы между собой (видят одинаковое последнее значение), а в ACID — о соблюдении ограничений целостности в рамках одной базы.
Распространённые неверные трактовки CAP
Вокруг CAP накопилось столько упрощений, что стоит расчистить почву. Самое частое — формула «выбери два из трёх», будто можно навсегда отказаться от одного свойства. На деле P (устойчивость к разделению) — не предмет выбора: сетевые сбои случаются независимо от нашего желания, и распределённая система обязана как-то на них реагировать. Поэтому реальный выбор — между C и A, и только в момент разделения. В нормальном режиме, когда сеть цела, грамотная система обеспечивает и согласованность, и доступность одновременно — никакого «двух из трёх» здесь нет. Вторая частая ошибка — считать CAP жёстким переключателем «или полная согласованность, или никакой». Современная практика знает спектр промежуточных моделей согласованности (от строгой до итоговой, с множеством оттенков между ними), и многие системы позволяют настраивать уровень под конкретный запрос. CAP задаёт фундаментальное ограничение, но не диктует грубый бинарный выбор — реальность тоньше теоремы.
Почему нельзя получить всё три
Сетевые разделения (partition) в распределённой системе неизбежны: связь между дата-центрами рвётся, пакеты теряются. Значит, отказаться от P (устойчивости к разделению) на практике нельзя — система обязана как-то вести себя при разрыве. Остаётся выбор между C и A в момент разделения:
- Выбираем CP (согласованность): при разделении система отказывается отвечать на запросы, которые могли бы вернуть устаревшие данные, — жертвуем доступностью ради того, чтобы никто не прочитал неверное значение.
- Выбираем AP (доступность): при разделении система продолжает отвечать, но разные узлы могут вернуть разные (несогласованные) данные — жертвуем согласованностью ради того, чтобы всегда был ответ.
Таким образом, CAP — это не «выбери два из трёх навсегда», а более точно «когда случается разделение, выбирай между C и A». В отсутствие разделения система может давать и согласованность, и доступность.
Примеры выбора CP и AP
Чтобы выбор между согласованностью и доступностью не остался абстрактным, привяжем его к жизни. Представьте банковскую систему с узлами в двух дата-центрах. Связь между ними оборвалась (разделение). CP-выбор: пока узлы не могут согласовать баланс, система отказывается проводить операции, которые рискуют выдать устаревшие данные, — лучше показать ошибку «сервис временно недоступен», чем дважды списать или показать неверный баланс. Здесь цена ошибки слишком высока, доступностью жертвуют. AP-выбор: представьте корзину покупок или ленту соцсети при том же разрыве. Система продолжает работать на каждом узле независимо — пусть на секунду счётчик лайков или содержимое корзины на разных узлах разойдётся, это не катастрофа, а вот недоступность сервиса отпугнёт пользователя. Здесь жертвуют согласованностью. Один и тот же выбор, продиктованный разной ценой ошибки: для денег дороже неверные данные, для ленты — недоступность. Именно поэтому CAP — не про «что лучше вообще», а про «что важнее в вашей предметной области».
Согласованность — это спектр, а не выключатель
Картина «либо строгая согласованность, либо итоговая» — упрощение. Между этими полюсами лежит целый спектр моделей, и знать о нём полезно. Строгая (линеаризуемая) согласованность — любое чтение видит самую свежую запись, как будто система одна. Причинная согласованность — гарантирует порядок связанных событий (ответ не появится раньше вопроса), но допускает расхождение независимых. Чтение своих записей — пользователь всегда видит собственные изменения, даже если другим они ещё не видны. Итоговая согласованность — самый слабый полюс: узлы сойдутся когда-нибудь. Многие современные системы позволяют выбирать уровень под конкретный запрос: для показа баланса — строгая, для счётчика просмотров — итоговая. Поэтому грамотный разговор о согласованности — это не «есть она или нет», а «какая именно нужна здесь и какова её цена». Этот спектр — практическое продолжение CAP: теорема говорит, что при разделении за согласованность платят доступностью, а спектр уточняет, сколько согласованности мы готовы купить.
ACID против BASE
Из выбора в пользу доступности (AP) выросла альтернативная философия гарантий — BASE, противопоставляемая ACID:
- Basically Available — система в основном доступна (отвечает почти всегда).
- Soft state — состояние может меняться со временем даже без новых записей (за счёт распространения обновлений).
- Eventual consistency (итоговая согласованность) — узлы со временем сойдутся к одному значению, но в моменте могут расходиться.
ACID говорит «всегда согласованно, любой ценой»; BASE — «всегда доступно, согласованность наступит позже». Это не «лучше/хуже», а разные приоритеты. Для банковского баланса нужен ACID; для счётчика лайков в соцсети итоговая согласованность вполне приемлема — ничего страшного, если число лайков на секунду разойдётся между узлами.
| Подход | Приоритет | Согласованность | Типичная область |
| ACID | Корректность | сильная, немедленная | финансы, заказы, учёт |
| BASE | Доступность и масштаб | итоговая | ленты, кеши, метрики |
Типичные заблуждения
- «CAP запрещает иметь C и A одновременно всегда». Нет: выбор между C и A делается только в момент сетевого разделения; в норме доступны оба.
- «C в CAP — это C в ACID». Разные понятия: согласованность узлов между собой против соблюдения ограничений целостности.
- «BASE — это просто плохая согласованность». Это осознанный выбор доступности и масштаба там, где итоговая согласованность допустима.
- «Реляционные базы не масштабируются». Масштабируются, но в основном вертикально и с трудом — горизонтально; это ограничение, а не приговор.
Итог
- Реляционная модель ограничена в горизонтальном масштабировании, жёсткости схемы и работе с неструктурированными данными.
- Теорема CAP: при сетевом разделении распределённая система выбирает между согласованностью и доступностью.
- Согласованность в CAP (узлы видят одно значение) — не то же, что C в ACID (ограничения целостности).
- BASE (доступность + итоговая согласованность) — альтернатива ACID для систем, где приоритет — масштаб и доступность.