Понятие согласованности данных сложное, неоднозначное и включает в себя широкий спектр определений, лишь частично совпадающих друг с другом. Команда VK Cloud перевела статью, в которой автор определяет термин «согласованность» в области распределенных БД и рассуждает на тему этой самой согласованности.

Три вида согласованности данных


Понятие согласованности — одно из самых неоднозначных в ИТ. Если попробовать найти определение этого термина в интернете, можно споткнуться о множество различных трактовок, у каждого автора она своя. При этом не особенно очевиден факт, что значение термина меняется, если речь идет о базах данных или распределенных системах.
Попробуем обозначить три основных типа согласованности. 

Согласованность в теореме Брюера


Первый из них обозначен буквой C в аббревиатуре CAP в теореме Брюера (Consistency, Availability, Partition tolerance). Согласно этой теореме, в распределенной системе можно обеспечить выполнение только двух из трех следующих свойств:

  1. Согласованность: при чтении данных система выдает актуальную версию.
  2. Доступность: каждый запрос к корректно работающему узлу завершается корректным ответом.
  3. Устойчивость к разделению: система продолжает работать, несмотря на сбои в сетевом трафике между некоторыми узлами.

Далее в теореме Брюера поднимается вопрос: чем вы жертвуете? Доступностью ради сохранения согласованности или согласованностью ради сохранения доступности? 

В сущности, теорема Брюера рассматривает репликацию, в частности, сбои сети во время репликации.

Допустим, вам нужно реплицировать один и тот же фрагмент данных на разных узлах. Например, чтобы повысить устойчивость системы к сбоям или уменьшить время задержки для пользователей с помощью размещения данных ближе к ним. Если на нескольких узлах размещен один и тот же фрагмент, вам нужно сетевое соединение, чтобы передавать обновление данных с узла на узел.


Система из трех узлов. Клиент направляет запрос «присвоить значение Х элементу 1». Узел A реплицирует эту операцию на узлы B и C

Однако, как нам напоминает Вернер Фогельс, «все постоянно ломается». И ваша сеть тоже.


Узел C не может взаимодействовать с узлами A и B из-за нарушения связности сети. Соответственно, он не может получить обновления значений с узла A

Согласно теореме Брюера, нам нужно решить, что делать в этом случае — как изолированному узлу C реагировать на запрос от клиента?

  1. Если вы выбираете подход AP (доступность и устойчивость к разделению), узел C выдает в ответ данные, находящиеся локально на этом узле. В этом смысле узел C доступен: он может выдать корректный ответ, который, правда, не всегда будет наиболее актуальным.
  2. Если остановиться на подходе CP (согласованность и устойчивость к разделению), вы не разрешите узлу C выдать ответ, ведь у него могут быть устаревшие данные. Если для вас в приоритете согласованность данных, узел C не сможет ответить, что снижает доступность системы (в терминологии теоремы Брюера).
  3. Если вы выбираете подход CA (согласованность и доступность), вы жульничаете! Помните, мы исходим из допущения о нарушении связности сети.

Теорему Брюера никогда не удастся опровергнуть, и маркетинговые попытки вендоров баз данных утверждать обратное должны вызвать у вас разумное сомнение. Правда, нужно понимать ограничения теоремы:

  • Она рассматривает работу системы только в условиях сбоя. Сбои неизбежны, и неплохо бы знать, как ваша база данных поведет себя в этом случае. Правда, скорее всего, большую часть времени она будет функционировать нормально. Но и в этой ситуации в ее работе будут интересные компромиссы, их обсудим ниже.
  • Речь идет о конкретных сбоях. А именно о нарушении связности сети между узлами. Но ведь есть масса других неисправностей — от нехватки памяти на отдельном узле до пожара в ЦОД. Все это может серьезно повлиять на доступность системы, и не только в том смысле, в каком ее рассматривает теорема Брюера. Поэтому важно учитывать и эти неполадки. 
  • В ней используется уникальное понятие «доступность». Согласно теореме Брюера, понятие доступности подразумевает корректный ответ от корректно работающего узла. Это значит, что, если клиент обращается к изолированному узлу C, он считается доступным, если выдал успешный ответ.

Мы часто думаем о доступности как о проценте успешных ответов за определенный период времени (то есть сколько у системы «девяток» доступности). У системы на базе подхода CP может все-таки оказаться очень высокая доступность благодаря тому, что все клиенты обязательно используют большинство узлов без нарушения связи. О доступности можно подробнее прочитать в статье Марка Брукера «Доступность и доступность».

Несмотря на эти ограничения, теорема Брюера помогает осознать, на какие компромиссы приходится идти при репликации данных в распределенной системе.

Согласованность в ACID-транзакциях


Второй тип согласованности связан с ACID-транзакциями. Аббревиатура ACID обозначает совокупность гарантий относительно поведения базы данных при объединении нескольких действий в единую логическую операцию, которую часто называют транзакцией.
Теорема Брюера — это концепция, касающаяся репликации в распределенных системах. ACID же применима только к базам данных. Четыре составляющие ACID-транзакции:

  1. Атомарность: все операции будут выполнены полностью или не выполнены совсем. 
  2. Согласованность: после транзакции база данных остается в допустимом состоянии.
  3. Изолированность: параллельные транзакции рассматриваются как выполняемые последовательно.
  4. Надежность: завершенная транзакция сохраняется даже в случае сбоя.

В этой концепции определение согласованности сильно отличается от теоремы Брюера. В ACID согласованность означает, что транзакция не может привести к недопустимому состоянию.

То есть в каждом столбце значения относятся к нужным типам данных и необходимые значения будут предоставлены. Хотя транзакции не особенно усложняют здесь суть дела.

Более вероятный источник проблем с согласованностью — это, скорее, ссылочная целостность. Если в таблице указан внешний ключ, благодаря согласованности запись, на которую он указывает, будет все еще существовать после завершения транзакции.

Это очень полезное свойство, но не думаю, что именно оно чаще всего приходит в голову, когда говоришь о компромиссах, связанных с согласованностью в базах данных. Это не совсем компромисс в привычном смысле слова — скорее, обещание, что база данных будет делать то, что собиралась.

Изолированность как часть ACID — это интересная концепция, имеющая довольно много общего с темой согласованности. Подробнее мы поговорим об этом дальше.

Модели согласованности базы данных


Третье определение термина также применимо к базам данных — это концепция моделей согласованности базы. Много интересного о моделях согласованности можно узнать из аналитики Jepsen — это блог, набор статей и консалтинговый сервис Кайла Кингсбери. Кайл проверяет на прочность разные распределенные системы, выясняя, как они ведут себя при том или ином сбое. Это качественное, интересное решение. Сотрудники Jepsen отлично разбираются в распределенных системах, так что не переживайте, если вы несколько раз перечитали представленный анализ и поняли процентов 15 написанного.

У сервиса Jepsen довольно удобная разбивка по разным моделям согласованности, но вам все равно трудно будет понять, что к чему, если вы не разобрались с терминологией.

В модели согласованности базы данных есть два основных элемента:

  1. Linearizability влияет на обработку в базе данных отдельного фрагмента данных, который реплицируется на нескольких узлах.
  2. Serializability влияет на обработку в базе данных одновременного выполнения транзакций, каждая из которых может работать с несколькими фрагментами данных.

Linearizability похожа на согласованность в теореме Брюера, о которой мы говорили выше, только это еще более строгая последовательность. Если теорема Брюера применима только к нарушениям связности, Linearizability описывает, как система работает в любой момент времени. Это значит, что, когда система начинает и завершает операцию записи фрагмента данных, это действие должно учитываться во всех последующих операциях с этими данными.

Обратите внимание, что Linearizability в обязательном порядке подразумевает подход CP. С Linearizability связаны и не такие строгие модели согласованности: они обеспечивают высокую доступность (в терминах теоремы Брюера).

По-видимому, Linearizability (и ее более мягкие версии) не предусматривает конечную согласованность. Особенно в системах с балансировкой нагрузки, таких как DynamoDB, в которой не поддерживаются тесные связи с определенным узлом. Поговорим о конечной согласованности подробнее.

Linearizability = один фрагмент данных, Serializability = несколько фрагментов. В частности, Serializability — это способ обработки параллельных транзакций, выполняемых с одними и теми же фрагментами данных.

Самый «безопасный» подход в данном случае — это выстроить транзакции в порядке их поступления и последовательно выполнять их, так, чтобы каждая транзакция завершалась до начала следующей. В реальности дело тогда движется достаточно медленно, поэтому мы часто исправляем ситуацию, выполняя несколько транзакций параллельно. Но при параллельном выполнении есть несколько разных уровней безопасности.

Что не так с дискуссиями на тему согласованности


Теперь, когда мы разобрались с основной терминологией, давайте перейдем к доброжелательной критике. Вот несколько идей, которые направят ваш мыслительный процесс.

Неполнота теоремы Брюера


Теорема Брюера полезная и правильная. Что бы вы ни думали, вы не можете волевым решением создать систему на базе подхода CA. И все же теорема неполна. Например, в дискуссиях часто говорят: «Мы не можем выбрать $DATABASE, потому что это система на базе подхода AP, а нам не нужна конечная согласованность».

Конечная согласованность — это интересная тема, и вы сталкиваетесь с ней не только в случае нарушения связности из теоремы Брюера. Хотя нужно представлять себе, как система будет работать в случае нарушения связности: помните, что большую часть времени она будет работать без сбоев. Но и периоды нормальной эксплуатации не обходятся без компромиссов, о которых не стоит забывать.

Даниэль Абади расширил теорему Брюера, создав теорему PACELC. В ней предусмотрено два режима эксплуатации: в период нарушения связности и в период нормальной работы.

Первые три буквы аббревиатуры PACELC совпадают с буквами аббревиатуры CAP (Partition tolerance, Availability, Consistency). Следующие три буквы обозначают действия в режиме без нарушения связности. ELC расшифровывается как «а еще оптимизировать время задержки или согласованность?».

Давайте обдумаем этот компромисс. Напомним, что согласованность — это и репликация данных на нескольких машинах, и предоставление наиболее актуальной версии этих данных с любого из узлов. Но у нее есть своя цена. Если для распределенной системы нужен высокий уровень согласованности, прежде чем подтвердить клиенту операцию записи, обязательно нужно скопировать данные на все узлы. В зависимости от расположения узлов и конфигурации сети такой подход может заметно снизить скорость выполнения запросов на операции записи.

Альтернативный вариант — подтвердить клиенту операцию записи, обновив элемент данных только на подмножестве машин в системе. Другие узлы в системе можно обновить асинхронно после завершения записи. Тогда время задержки для клиента сократится благодаря снижению уровня согласованности для этого фрагмента данных. Если другой клиент направит запрос к данным на узел, до которого еще не дошло последнее обновление, он получит устаревшую версию. Для многих систем применяется именно этот подход, который часто называют конечной согласованностью. В его популяризации участвовали Вернер Фогельс и некоторые системы Amazon, которые он помогал проектировать. 

Прелесть PACELC в том, что она позволяет рассматривать согласованность в общем случае, когда база данных работает без сбоев. Можете ли вы смириться с тем, что время от времени для чтения выводятся неактуальные данные? Если нет, устраивает ли вас увеличение задержки и снижение доступности, которые связаны с высоким уровнем согласованности?

Вольное применение ACID


Сегодня многие работают с NoSQL. И их коллеги, чаще пересекающиеся с SQL, справедливо указывают на отсутствие ACID-транзакций в большинстве баз данных NoSQL. Иногда можно услышать следующее: «Да, масштабируемость в NoSQL — штука интересная, но мне не хочется иметь дело с багами параллелизма, отказавшись от ACID-транзакций». Всегда казалось, что это, безусловно, сильный аргумент в пользу реляционных баз данных. Но оказалось, что правда — вещь более тонкая, чем кажется. Модели согласованности и изолированность в ACID не так прямолинейны.

Сериализуемость — это аспект моделей согласованности, связанный с транзакциями. Хоть и считается, что большинство реляционных баз данных поддерживают ACID-транзакции, они не дают полной гарантии сериализуемости при их выполнении. Обычно они предлагают довольно вольные гарантии, такие как повторное чтение или Snapshot isolation, что иногда приводит к неожиданным проблемам при выполнении параллельных операций.

Подробно изолированность в базе данных рассматривается еще на одном отличном сайте Hermitage project, а также в статье Мартина Клеппманна. Проект Hermitage помогает проверять типы изолированности и возможные проблемы в наиболее популярных реляционных базах данных. А в своей статье Мартин обсуждает баг распараллеливания в NoSQL БД. Из-за него люди думают, что реляционная база данных спасет их, не понимая, что с уровнями изолированности, заданными по умолчанию, они столкнутся с той же проблемой!

Все это не подрывает престиж реляционных баз данных и не снижает значимость ACID-транзакций. Скорее, мы призываем к разумной осторожности при выборе базы данных и рекомендуем разобраться, что она действительно гарантирует.

Слишком много разговоров про абсолют


Наконец, кажется, что, обсуждая модели и концепции согласованности, специалисты слишком много говорят о крайностях, хотя здесь есть некоторые нюансы. И потом, новые технологии или методы работы могут в будущем изменить применяемые методы математического анализа.

Например, время от времени руководители или ведущие архитекторы компаний-разработчиков БД утверждают, что им удалось создать систему на базе подхода CA. Это просто неправильное понимание CAP. Но есть и крупица правды в том, что нарушения связности сети реже встречаются в определенных ситуациях. По мере того как развиваются наши дата-центры, а в сетях повышается устойчивость к сбоям, решение в пользу согласованности или доступности становится все менее кардинальным.

Аналогичный эффект наблюдается и с сокращением времени восстановления распределенных систем после сбоя. Хотя это не относится непосредственно к теореме Брюера, имеет смысл рассмотреть, что происходит с согласованностью и доступностью в случае сбоя узлов, а не нарушения связности сети.

Одновременный сбой на нескольких узлах может привести к снижению доступности (в классическом смысле, отличном от определений в теореме Брюера) и другим проблемам. Однако гибкость облачных решений в сочетании с практиками сокращения времени восстановления может значительно снизить вероятность одновременного сбоя узлов.

Наконец, если рассматривать обратную зависимость между временем задержки и согласованностью в PACELC, важную роль могут сыграть определенные стратегии, используемые для репликации данных на другие узлы. Хотя превысить скорость света мы еще не можем, многие современные системы фактически являются согласованными, а их реплики отстают буквально на несколько миллисекунд. В 2013 году Питер Бэйлис и Ади Годси опубликовали исследования на эту тему, и с тех пор ситуация, без сомнения, улучшилась.

Здесь мы можем сделать важный вывод: надо учитывать не только крайние области спектра, но и промежуточные положения между ними. Эти крайние значения помогают направлять и заземлять обсуждение, но игнорировать промежуточные области все же не стоит.

Команда VK Cloud развивает собственные базы данных разных типов. Новым пользователям дарим три месяца на тестирование сервиса и консультацию архитектора по построению собственного решения.

Комментарии (2)


  1. gandjustas
    00.00.0000 00:00
    +1

    Сколько можно это обсуждать:

    • В CAP partition, consistency и availability это атомарные величины. В реальности - непрерывные. И вопрос звучит так: "сколько процентов доступности или согласованности вы готовы потерять при заданном проценте partition".

    • Пока вы работаете в одном датаценре, то можете считать что никаких partition у вас нет. Я знаю, что в облаке они могут случиться даже в рамках одного "региона", но это тоже крайне редкое явление.

    • CAP теорема не рассматривает поведение клиента. Если клиент умеет повторять запросы, то можно нивелировать "недоступность" по CAP и не только по CAP. Более того, повторяя запросы между серверами можно нивелировать partition.

    • Несмотря на весь маркетинг подавляющему большинству конечных потребителей нужна согласованность данных. Системы не обеспечивающие согласованность можно даже не рассматривать для прикладных задач.

    • CA-системы это давно известные и прекрасно работающие системы на основе кворума. Как и подавляющее большинство современных NoSQL баз.

    • AP-системы это кэш в том или ином виде над некоторым консистентным хранилищем или без него.

    • Комбинируя AP и CA системы можно выполнить нужные вам требования.


  1. Tzimie
    00.00.0000 00:00

    Как говорится, если протон распадается, то все базы eventually consistent