CAP-теорема, или теорема Брюера впервые была описана на симпозиуме по принципам распределенных вычислений (PODC) ученым Эриком Брюером в 2000 году, при этом Брюер заявлял, что появилась она еще в конце 1998 года. На тот момент теорема фактически являлась гипотезой, так как не имела доказательства, но в 2002 году двое ученых и исследователей из Массачусетского технологического института (MIT) Сет Гилберт и Нэнси Линч представили доказательство гипотезы, тем самым придав ей статус теоремы.
Непосредственно суть теоремы заключается в том, что любая распределенная система может обеспечить только два из трех свойств: согласованность (consistency, C), доступность (availability, A), устойчивость к разделению (partition tolerance, P).
Почему теорема Брюера значима? Распределенная система — это сеть, в которой данные хранятся на нескольких узлах, при этом они могут взаимодействовать друг с другом и выполнять общие задачи. Примерами таких систем являются облачные приложения, базы данных (например, NoSQL базы данных Cassandra и MongoDB) и микросервисные архитектуры. Понимание CAP-теоремы при проектировании таких систем позволяет разработчикам идти на компромиссы осознанно и с учетом специфических требований конкретной системы, в первую очередь обеспечивая те характеристики, которые этой системе необходимы.
Компоненты CAP-теоремы
Итак, каждая буква из названия теоремы обозначает одно из трех свойств. Рассмотрим эти свойства подробнее.
- C (consistency, согласованность) — в данном контексте это означает, что любые изменения данных мгновенно распространяются между всеми узлами и только после этого запись изменений считается успешной. Таким образом все клиенты видят одни и те же данные в каждый конкретный момент. Слово «согласованность» говорит само за себя — у разных узлов нет расхождений в данных, они согласованы между собой.
- A (availability, доступность) — все рабочие узлы всегда выполняют запросы и предоставляют ответы, не содержащие ошибок. Другими словами, клиент, который сделал запрос, гарантированно получит ответ на него, даже в случае, если один или несколько узлов не недоступны: система всегда доступна для операций чтения и записи.
- P (partition tolerance, устойчивость к разделению) — система должна продолжать работать, даже если соединение между двумя и более узлами потеряно/осуществляется со значительными задержками.
Возможные комбинации свойств
Теорема Брюера говорит о том, что одновременно можно обеспечить только две характеристики, поэтому существует три возможные комбинации этих характеристик: CA, AP и CP. Рассмотрим каждую из них по отдельности:
- CA-системы. Фокус делается на обеспечении высокой доступности и согласованности данных, в то время как при возникновении разделения сети либо будет приостановлена обработка запросов (для поддержания согласованности), либо запросы продолжат обрабатываться, но тогда пострадает согласованность данных;
- AP-системы. В таком случае в приоритете доступность и устойчивость к разделению сети, однако согласованность данных теряется, так как запросы продолжают обрабатываться даже в случае возникновения разделения сети. Обычно, когда разделение устраняется, узлы синхронизируются, но до этого момента они могут содержать разные версии данных. Если приложение должно работать непрерывно, то такая комбинация может стать лучшим вариантом;
- CP-системы. Здесь обеспечивается согласованность данных и устойчивость к разделению сети, при этом исчезает доступность, так как обработка запросов приостанавливается до устранения разделения сети. Такая комбинация характеристик нужна тогда, когда необходимо предотвратить ошибки во время прерванного соединения между узлами и несогласованности данных.
Роль CAP-теоремы в решении проблем проектирования
Теорема Брюера может быть теоретической основой для разработчиков при решении проблем, возникающих во время проектирования систем.
Во-первых, CAP-теорема побуждает разработчиков оценить приоритеты проектируемого приложения и осознать ограничения, тем самым создавая условия для поиска компромиссов и формирования более реалистичных ожиданий от этого приложения. Следовательно, разработчики сразу концентрируются на определенных характеристиках, наиболее важных в данном случае. Также теорема может применяться для переоценки приоритетов уже существующих приложений.
Во-вторых, учитывая то, что часто выбор стоит между сочетанием характеристик AP и CP, теорема Брюера в большей мере заставляет разработчиков решать, что важнее для проектируемого приложения: доступность или согласованность данных. И только в том случае, если разделение сети маловероятно, либо окажет незначительное влияние на работу приложения, выбор может быть сделан в пользу комбинации CA.
В-третьих, в зависимости от выбранных характеристик разработчики могут принимать меры по оптимизации свойства, которое они посчитали менее приоритетным. Другими словами, если была выбрана комбинация CP, то разработчики, например, могут внедрять механизмы кэширования, чтобы сделать приложение более доступным.
Ограничения и проблемы CAP-теоремы
Несмотря на то что теорема Брюера может быть полезной как для понимания работы распределенных систем, так и для их проектирования, она имеет недочеты и ограничения, из-за чего многократно подвергалась критике — кто-то считает ее вовсе не актуальной и не применимой к реальной жизни. Рассмотрим некоторые из проблем CAP-теоремы:
- CAP-теорема явно не говорит о том, что все три характеристики бинарны (либо присутствуют, либо отсутствуют), но подразумевает это. В реальности же свойства могут проявляться в какой-то степени — например, доступность может быть частичной;
- фактор задержек не учитывается — даже если задержки при ответах на запросы высокие, то доступность все еще присуща данному механизму, однако можно ли на самом деле назвать его доступным — это большой вопрос;
- фокус теоремы на наличии только двух из трех характеристик заставляет разработчиков выбирать, какие свойства важнее, тем самым ограничивая их. Конечно, в реальности не бывает идеальных систем, но при грамотном проектировании они могут достигать баланса между разными характеристиками;
- сетевое разделение — это единственная ошибка, которая может возникнуть (если опираться на CAP-теорему), но в реальности могут появляться другие неполадки и сбои, которые разработчики должны учитывать при проектировании;
- при желании поместить сложные приложения в рамки теоремы Брюера разработчики могут закрыть глаза на множество других нюансов, некоторые из которых уже были описаны (фактор задержек, различные виды неполадок).
В дополнение к этому стоит сказать и о PACELC-теореме, которая была впервые описана Дэниелом Абади. PACELC-теорема расширяет CAP-теорему, она сформулирована следующим образом: «Если происходит сетевое разделение (partition), система должна выбирать между доступностью (availability) и согласованностью (consistency). В противном случае (else), система должна выбирать между задержками (latency) и согласованностью (consistency)». Эта модель позволяет разработчикам обратить внимание на большее количество факторов и является несколько более приближенной к реальной жизни.
Также важно помнить о модели BASE, которая, можно сказать, является противопоставлением модели ACID. BASE предлагает идеи, которые лучше соотносятся с реальным положением вещей: доступность гарантируется, но в ответе на запрос могут содержаться ошибки; со временем состояние системы может меняться, а данные в конечном итоге становятся согласованными.
Подводя итог
CAP-теорема была впервые представлена Эриком Брюером в 2000 году, а спустя два года доказана Сетом Гилбертом и Нэнси Линчем. Основная идея CAP-теоремы заключается в том, что система может обладать только двумя из трех характеристик (consistency, availability, partition tolerance) одновременно. Исходя из этого формируются возможные комбинации свойств — CA, CP, AP, каждая из которых имеет свои особенности и сценарии применения.
Теорема Брюера нужна разработчикам для того, чтобы грамотно расставлять приоритеты в проектируемом приложении и осознанно жертвовать теми или иными характеристиками ради присутствия других. При этом CAP-теорема подвержена критике, так как имеет определенные проблемы и ограничения, которые заставляют усомниться в том, что данная теорема применима в реальной жизни или может быть использована, как единственная опора при проектировании приложений.
Чтобы проектировать приложения максимально эффективно, разработчики могут прибегать к нескольких подходам сразу: учитывать CAP-теорему и ее расширенную версию PACELC, философию BASE и ACID, но самое главное — помнить о том, что каждый проект требует индивидуального подхода и четкого понимания его приоритетов, и именно с этой точки зрения его стоит рассматривать в первую очередь.
Также важно понимание того, что большую часть систем невозможно описать/классифицировать по теореме Брюера, так как они могут иметь разные конфигурации, их характеристики могут не подходить под четкие определения свойств в теореме, более того, приложения могут выходить за рамки этих характеристик.