CAP, PACELC и модели согласованности

↑ 6.1 Масштабирование и надёжность данных · ← Предыдущая · → Следующая

Желательно~3 мин чтенияУровень: senior

Зачем это на собесе

Теория распределённых систем нужна для обоснования выбора хранилища и объяснения компромиссов.

CAP

В распределённой системе при сетевом разделении (Partition) нужно выбрать между:

  • C — Consistency (линеаризуемость): каждое чтение видит последнюю запись;
  • A — Availability: каждый живой узел отвечает на запрос.

Partition tolerance обязательна (сети ненадёжны), поэтому практически выбор CP или AP:

КлассПоведение при разделенииПримеры
CPотвергает запросы на отстающей части, чтобы сохранить согласованностьZooKeeper, etcd, Consul, HBase, MongoDB (majority), Spanner, CockroachDB
APпродолжает отвечать, возможны расхождения (разрешаются позже)Cassandra, DynamoDB (по умолчанию), Riak, CouchDB

Замечание: CAP описывает только поведение при разделении. «CA» в реальной распределённой системе не существует; одиночный узел — не распределённая система.

PACELC

Расширение CAP: если есть разделение (P) — выбор между A и C; иначе (Else) — между задержкой (Latency) и согласованностью (C).

PA/EL: Cassandra, DynamoDB — доступность при разделении и низкая задержка в норме
PC/EC: HBase, Spanner, MongoDB (majority) — согласованность всегда, выше задержка
PA/EC: MongoDB по умолчанию (в разных конфигурациях)
PC/EL: PNUTS

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

Модели согласованности

От сильной к слабой:

МодельГарантия
Линеаризуемость (strong)система ведёт себя как один узел; чтение видит последнюю запись в реальном времени
Последовательная (sequential)единый порядок операций, согласованный с порядком каждого клиента
Причинная (causal)причинно-связанные операции видны в одном порядке всем
Read-your-writesклиент видит свои записи
Monotonic readsповторное чтение не возвращает более старое значение
Eventualпри отсутствии новых записей все реплики сойдутся

Изоляция транзакций (ACID, одиночная БД) — другая ось: Serializable, Snapshot и т. д. Strict serializability = сериализуемость + линеаризуемость (Spanner).

Кворумы

При N репликах, записи на W и чтении с R реплик: если R + W > N — чтение пересекается с последней записью (сильнее согласованность). Пример: N = 3, W = 2, R = 2. Настройка в Cassandra (QUORUM, ONE, ALL), DynamoDB (ConsistentRead), MongoDB (w: majority, readConcern).

Разрешение конфликтов

  • LWW (last write wins) по времени: просто, теряет данные, зависит от синхронизации часов;
  • векторные часы, версионирование;
  • CRDT: структуры, автоматически сходящиеся (счётчики, множества, текст);
  • слияние в приложении;
  • консенсус (Raft, Paxos) для линейной согласованности: лидер и кворум; основа etcd, Consul, CockroachDB, Kafka KRaft.

Практика

  • банки, склад, бронирование — сильная согласованность (CP, транзакции);
  • ленты, лайки, счётчики, каталоги — допускается eventual;
  • смешанный подход: критичные данные в ACID-БД, остальное в AP/кэшах;
  • обеспечивайте идемпотентность и компенсации (саги) там, где есть eventual consistency;
  • явно проектируйте, что пользователь увидит при лаге репликации.

Вопросы с ответами