CAP-теорему сформулировал Эрик Брюер ещё в 2000 году, а двумя годами позже Гилберт и Линч её доказали. С тех пор её цитируют на каждой конференции по распределённым данным, но на практике трактуют вкривь и вкось. Разберём, что теорема реально требует от архитектора и какие решения она диктует – не в теории, а на проекте.
Формулировка проста. Распределённая система не может одновременно гарантировать все три свойства: согласованность (Consistency), доступность (Availability) и устойчивость к разделению сети (Partition tolerance). Выбрать можно только два из трёх. Распределённый кластер всегда подвержен сетевым разделениям – узлы теряют связь, пакеты пропадают, дата-центры отваливаются. Значит, P исключить нельзя. Реальный выбор сводится к одному вопросу: что вы приносите в жертву при разрыве сети – согласованность или доступность.
CP против AP: цена разрыва сети
Когда узлы кластера перестают видеть друг друга, система обязана решить. Либо она отказывает в обслуживании части запросов, чтобы не выдать устаревшие данные, – это путь CP. Либо она продолжает отвечать всем, рискуя вернуть разные значения с разных узлов, – это путь AP.
Для банковской проводки или реестра прав ответ очевиден: лучше отказ, чем рассогласование баланса. Здесь работают системы с сильной согласованностью – классические РСУБД с синхронной репликацией, HBase, MongoDB в режиме строгого чтения с primary. Для счётчика просмотров, корзины интернет-магазина или каталога товаров доступность важнее: пользователь не должен видеть ошибку из-за того, что один узел отвалился. Здесь уместны Cassandra, Riak, Voldemort – системы, которые сливают конфликтующие версии позже. Мы подробно сравнивали поведение этих хранилищ в обзоре NoSQL-решений.
Eventual consistency – не магия, а компромисс
AP-системы опираются на «согласованность в конечном счёте». Звучит мягко, но за этим стоит жёсткая инженерная работа: векторные часы, разрешение конфликтов на стороне приложения, кворумы чтения и записи. Формула N/R/W в Dynamo-подобных хранилищах – это рычаг, которым вы плавно двигаете систему от AP к CP. Если R + W > N, чтение видит последнюю запись, и вы покупаете согласованность ценой латентности и доступности.
Главная ошибка – считать, будто eventual consistency освобождает от ответственности за данные. Наоборот, она перекладывает её с базы на разработчика. Конфликты придётся разрешать руками: какая версия профиля верна, как слить две корзины, что делать с двумя «последними» адресами доставки. Для веба это часто оправдано, и мы разбирали такие сценарии в материале о NoSQL для веб-нагрузок.
Как выбирать на реальном проекте
Не выбирайте хранилище по моде. Разложите систему на подсистемы и примените CAP к каждой отдельно. Платёжный модуль, аутентификация, журнал аудита требуют CP. Лента событий, рекомендации, кэш профилей живут с AP без потерь. Полиглотное хранение – норма зрелой архитектуры, а не признак хаоса. Прошлый год показал, что российские заказчики из госсектора и финансов перестали бояться смешанных стеков, – мы фиксировали это в итогах 2011 года.
Главное – заранее проговорить с заказчиком, что происходит при разрыве сети. Это бизнес-решение, а не техническая деталь. Регламенты, требования регулятора, цена простоя против цены ошибки в данных – всё это определяет точку на оси CAP раньше, чем вы выберете СУБД.
Точку на оси CAP закладывают на этапе проектирования хранилища данных и BI-контура, где выбор согласованности и доступности приходится обосновывать перед бизнесом и регулятором. CAP-теорема не запрещает строить надёжные системы. Она лишь требует честно назвать, чем вы готовы пожертвовать.