Распределённые системы: CAP и согласованность
CAP - самая цитируемая и самая неверно понятая теорема распределённых систем. Собес проверяет, понимаешь ли ты, что P не выбирают, и различаешь ли линеаризуемость от eventual не по маркетингу БД, а по гарантиям.
Стержень: partition это погода, а не опция; выбор C против A случается только в момент партиции, а в мирное время трейдоф другой - латентность против консистентности.
// Формулировки: «объясни CAP», «что такое линеаризуемость?», «какие аномалии видит клиент при eventual consistency?».
CAP и PACELC
CAP про поведение в момент сетевого разделения: раз узлы не видят друг друга (P - данность), система либо отказывает в ответе ради консистентности (CP), либо отвечает, рискуя отдать устаревшее, ради доступности (AP). «Выбрать CA» бессмысленно - партиции не спрашивают разрешения.
PACELC достраивает картину: если партиция (P), то A или C; иначе (Else) - латентность против консистентности. Даже без сбоев сильная консистентность стоит задержки на кворумы или поход к лидеру.
// Поэтому «строгая консистентность» из рекламы БД и формальная линеаризуемость - не одно и то же; спрашивай, что именно гарантируется.
- CP / AP
- при партиции: консистентность / доступность
- PACELC
- при партиции A/C, иначе латентность/консистентность
Линеаризуемость и eventual
Линеаризуемость - «как будто одна машина»: чтение после подтверждённой записи гарантированно её видит, а операции выглядят мгновенными в реальном времени. Дорого - кворум или поход к лидеру на каждой операции.
Eventual consistency - реплики сойдутся когда-нибудь после прекращения записей: дёшево и доступно. Интересный вопрос - какие аномалии видит клиент, пока не сошлось.
// Client-centric гарантии закрывают главные боли eventual: read-your-writes (вижу свою запись сразу) и monotonic reads (время не идёт назад между чтениями). Достигаются липкими сессиями или чтением «своих» данных с лидера.
- линеаризуемость
- операции как на одной машине в реальном времени
- read-your-writes
- клиент всегда видит собственные записи
Кворумы и выбор per-операция
Кворумное чтение-запись: если W + R > N, множества узлов записи и чтения пересекаются, и чтение зацепит последнюю запись (при N=3 это W=2, R=2). W=1, R=1 - быстро, но читаешь прошлое.
Консистентность выбирают per-операция, а не per-система: баланс счёта - линеаризуемо, счётчик лайков - eventual. Одна и та же система может давать оба режима настройками.
// Между строгой и eventual есть causal consistency - следствия не видны раньше причин (комментарий не появится раньше поста) без полной цены линеаризуемости. Часто это ровно то, что нужно продукту.
- кворум W+R>N
- пересечение множеств записи и чтения гарантирует свежесть
- causal consistency
- причина видна раньше следствия; дешевле линеаризуемости
Как отвечать: «Объясни CAP, и почему нельзя «выбрать CA»?»
CAP говорит: при сетевом разделении система вынуждена выбирать между консистентностью и доступностью. Ключевое - P, partition tolerance, это не пункт меню, а данность: в реальной сети разделения случаются, и притвориться, что их нет, нельзя. Поэтому «выбрать CA» бессмысленно это значит «выберу работать только когда сеть идеальна». Реальный выбор такой: когда узлы потеряли связь, я либо отказываюсь отвечать, чтобы не отдать устаревшее (CP), либо отвечаю тем, что есть, рискуя рассинхроном (AP). Причём выбор делается per-операция: для баланса счёта я хочу CP и линеаризуемость, для ленты лайков - AP и eventual. И CAP описывает только момент партиции; в мирное время трейдоф - латентность против консистентности, это уже PACELC.
Почему это сильный ответ: снят главный миф (P - не выбор), объяснён реальный смысл CP/AP, добавлен per-операция-подход и PACELC - видно понимание, а не заученная тройка букв.
На чём валят
- −«Выберу CA» - партиции не спрашивают; P не опция, а погода.
- −Прочитал сразу после записи с реплики и «данные пропали» - read-your-writes не обеспечен.
- −Требовать линеаризуемость для ленты новостей - платить латентностью за ненужное.
- −Считать кворум N/W/R защитой от всего: конфликт-резолюшн и hinted handoff всё равно нужны.
- −Путать «строгую консистентность» из маркетинга БД с формальной линеаризуемостью.
Проверьте себя
Пять вопросов из банка по этой подтеме. Всего их 11, остальные разбираются в тренажёре.
- Чем strong consistency отличается от eventual consistency?A)Это два близких названия по сути одной модели согласованностиB)Strong допускает устаревшие чтения, а eventual возвращает свежие данныеC)Strong: чтение видит последнюю запись сразу; eventual: реплики сходятся со временемD)Eventual consistency означает, что реплики согласуются лишь после ручной синхронизации
показать ответ и разбор
+C)Strong: чтение видит последнюю запись сразу; eventual: реплики сходятся со временем// разбор: При strong consistency любое чтение после записи видит именно её — как одна машина, но это дорого и снижает доступность/латентность. При eventual реплики сходятся к общему значению лишь спустя время: чтение может вернуть устаревшее, зато система дешевле, доступнее и лучше масштабируется. Многие продукты выбирают eventual плюс точечные гарантии вроде read-your-writes.
- Почему на практике «CA»-систем (согласованность+доступность без устойчивости) не бывает?A)Потому что согласованность и доступность несовместимы даже без сетевого разделенияB)Потому что закон прямо запрещает строить системы без устойчивости к сетевому разделениюC)Потому что CA-системы стоят слишком дорого, хотя технически вполне возможныD)Сетевые разделения в распределённой системе неизбежны, поэтому P отбрасывать нельзя
показать ответ и разбор
+D)Сетевые разделения в распределённой системе неизбежны, поэтому P отбрасывать нельзя// разбор: В любой реальной распределённой системе сети рвутся, а узлы падают — разделение (P) не опция, а данность. Значит, выбирать приходится между CP и AP; «CA» осмысленно лишь для одной машины. Уточнение даёт PACELC: даже без разделения (E, else) остаётся трейдофф между latency (L) и consistency (C).
- Что такое read-your-writes consistency?A)Пользователь после своей записи сразу видит именно её, а не старое значениеB)Гарантия, что пользователи по всему кластеру видят каждую запись одновременноC)Блокировка чтений до завершения текущих операций записи в системеD)Требование, чтобы запись немедленно синхронно реплицировалась на реплики
показать ответ и разбор
+A)Пользователь после своей записи сразу видит именно её, а не старое значение// разбор: Read-your-writes — гарантия, что пользователь всегда видит результат собственных изменений, даже если система в целом eventual. Иначе бывает конфуз: «я оставил комментарий, обновил — а его нет» (чтение ушло на отстающую реплику). Реализуют, например, привязкой пользователя к реплике-лидеру для его собственных данных (sticky routing).
- Что описывает модель согласованности «read-your-writes»?A)Все клиенты одновременно и мгновенно видят запись сразу после её подтвержденияB)Запись становится видимой её автору лишь после того, как её прочитали все остальные клиентыC)Клиент не видит собственных записей до тех пор, пока они не будут синхронно реплицированы на остальные узлы кластераD)Клиент после своей записи всегда видит её в последующих чтениях (но не обязательно чужие свежие записи)
показать ответ и разбор
+D)Клиент после своей записи всегда видит её в последующих чтениях (но не обязательно чужие свежие записи)// разбор: Read-your-writes (read-your-own-writes) — гарантия, что клиент, сделавший запись, в своих дальнейших чтениях эту запись увидит. Без неё возможен раздражающий эффект: обновил профиль, перезагрузил — старое (чтение попало на отставшую реплику). Это более слабая гарантия, чем строгая согласованность: чужие свежие записи видеть не обязательно, важна лишь собственная. Реализуют, направляя чтения клиента на лидера или на догнавшую его реплику.
- Что такое монотонное чтение (monotonic reads) и какой баг оно предотвращает?A)Гарантия не увидеть более старое состояние после более нового: чтения не «откатываются» назад во времениB)Гарантию, что реплики в кластере содержат идентичные данныеC)Гарантию, что данные читаются строго в том же порядке, в каком они были записаны продюсеромD)Гарантию, что каждое следующее чтение обязательно возвращает более свежие данные, чем прошлое
показать ответ и разбор
+A)Гарантия не увидеть более старое состояние после более нового: чтения не «откатываются» назад во времени// разбор: Monotonic reads гарантирует, что последовательные чтения клиента не возвращают всё более старые данные. Без неё при чтении с разных реплик с разным лагом можно сначала увидеть свежее значение, а потом — устаревшее (эффект «путешествия в прошлое»): комментарий то появляется, то исчезает при обновлении. Гарантию дают, закрепляя клиента за одной репликой (session stickiness) или требуя, чтобы реплика была не старее ранее прочитанного.
дальше
Теорию прочитали. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.