Перейти к основному содержимому

Согласованность данных

Согласованность (consistency) — состояние, когда все пользователи и процессы видят одни и те же данные при чтении. Согласованность не равна целостности (integrity)
Целостность описывает корректность данных внутри системы (например, наличие внешних ключей, ограничения на значения).

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

Виды согласованности

  • Строгая (strong consistency): после записи данные моментально видны всем. Пример — традиционные реляционные БД с синхронными транзакциями
  • В конечном счёте (eventual consistency): данные со временем сходятся, но на промежутке возможны расхождения. Пример — DynamoDB, Cassandra
  • Последовательная (sequential consistency): все операции видятся в одном порядке, но нет гарантии мгновенной видимости
  • Каузальная (causal consistency): операции, имеющие причинно-следственную связь, видятся в правильном порядке
  • Слабая (weak consistency): система не гарантирует моментальной или даже определённой очередности обновлений

Примеры выбора уровня согласованности

Всегда связано с анализом рисков и бизнес-требований:

  • Если данные критичны (банковские счета, заказы, бронирования), требуется strong consistency
  • Для аналитических или временных данных подойдут eventual consistency или quorum-based решения
  • Нужно учитывать нагрузку, ожидаемые задержки, требования к откатам и репликации
  • Часто используют матрицу рещений параметрами: задержка, SLA по доступности, бизнес-ущерб при ошибке

CAP-теорема и согласованность

CAP-теорема утверждает: распределённая система может одновременно гарантировать только две из трёх свойств:

  • Согласованность (Consistency): все клиенты видят одинаковые данные
  • Доступность (Availability): система отвечает на каждый запрос (даже если ответ может быть устаревшим)
  • Устойчивость к разделению (Partition tolerance): система продолжает работать при разделении сети

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

ACID vs BASE и согласованность

ACID (Atomicity, Consistency, Isolation, Durability) — свойства традиционных реляционных транзакций. Гарантируют строгую согласованность и корректность данных, но плохо масштабируются.

BASE (Basically Available, Soft state, Eventually consistent) — подход, характерный для NoSQL-систем:

  • Basically Available — система отвечает на запросы, пусть и с устаревшими данными
  • Soft state — состояние может изменяться без явных транзакций
  • Eventually consistency — данные в итоге сходятся

BASE-системы жертвуют частью согласованности ради масштабируемости и отказоустойчивости.

Согласованность записи и чтения

В распределённых системах согласованность записи (write consistency) и чтения (read consistency) настраиваются отдельно:

  • Write Consistency — сколько реплик должны подтвердить запись
  • Read Consistency — сколько реплик участвуют в чтении

Пример в Cassandra (формат: запись + чтение):

Обозначения: ONE — участие одного узла; QUORUM — большинство узлов (обычно ⌊N/2⌋ + 1); ALL — все доступные узлы

  • QUORUM + QUORUM ⇒ strong consistency — и запись, и чтение требуют подтверждения от большинства узлов. Это обеспечивает согласованность, даже если часть реплик недоступна
  • ALL + ONE ⇒ strong, но медленно — запись подтверждается всеми узлами, чтение — любым одним. Обеспечивает согласованность, но увеличивает задержки
  • ONE + ONE ⇒ fast, but eventual consistency — достаточно одного узла для записи и чтения, быстро, но возможны расхождения между репликами

Комбинации выбираются в зависимости от требований к задержкам и допустимому уровню согласованности.
Гибкая настройка позволяет балансировать между скоростью, надёжностью и рисками.

Изоляция транзакций

В реляционных системах уровни изоляции (Read Uncommitted, Read Committed, Repeatable Read, Serializable) управляют видимостью данных внутри транзакций.
Но в распределённых БД эти гарантии сложнее поддерживать из-за сетевых задержек и репликации.
Это увеличивает количество сценариев ошибок, необходимость компенсационных механизмов и дополнительные проверки корректности состояния.

Согласованность в распределённых БД

Реляционные системы

В распределённых реляционных системах (например, CockroachDB) часто используется глобальный протокол согласования.
CockroachDB использует алгоритмы распределённого согласования (например, Raft).

Для глобальных транзакций применяются двухфазный (2PC) и трёхфазный коммиты (3PC), которые обеспечивают атомарность и согласованность, но приводят к высокой латентности.

Распределённые транзакции

Реализация глобальных транзакций — сложная задача.
Системы часто используют протокол SAGA как альтернативу 2PC: большие транзакции разбиваются на локальные, а в случае отката вызываются компенсирующие действия.
Это снижает блокировки, но требует детальной проработки бизнес-логики.

Согласованность в NoSQL-системах

Большинство NoSQL-систем (Cassandra, DynamoDB, Riak) жертвуют строгой согласованностью ради доступности и масштабирования.

Вместо блокировок они применяют:

  • Eventual consistency: копии данных сходятся со временем
  • Анти-энтропийные механизмы: фоновое сравнение и синхронизация (например, Merkle-деревья)
  • Quorum-based подходы: чтение и запись требуют определённого числа подтверждений (quorum reads/writes)

Cassandra даёт возможность выбирать уровень согласованности per-запрос: от ONE (быстро, но менее надёжно) до ALL (гарантия согласованности, но высокая задержка)

Согласованность в микросервисной архитектуре

Микросервисы редко используют глобальные транзакции. Вместо этого — подходы к eventual consistency:

  • SAGA — координация серии локальных транзакций. В случае ошибки вызываются компенсирующие действия
  • Outbox Pattern — гарантированная доставка событий через отдельную очередь (Kafka, RabbitMQ)
  • Идемпотентность и дедупликация — обязательны для безопасности повторной доставки
  • Retry-паттерны и DLQ (Dead Letter Queue) — важны для обработки временных сбоев

Примеры ошибок из-за несогласованности

  • Двойное списание при race condition между двумя фронтендами
  • Разная информация о пользователе в CRM и биллинге
  • Выдан один и тот же промокод двум пользователям
  • Удаление сущности, на которую всё ещё есть ссылки — при eventual consistency между микросервисами

Временная согласованность

Иногда допустима временная несогласованность (например, данные кэшируются на 5 секунд).
В таких случаях важно:

  • Указывать TTL (time-to-live) для устаревших данных
  • Обрабатывать stale reads — например, читать устаревшие данные, которые уже не отражают текущее состояние, но могут быть допустимы в рамках TTL или в интерфейсах с мягкими требованиями к актуальности, показывать "нефинализированные" значения
  • Использовать версионирование или метки времени при отображении пользователю ("Обновлено 2 сек назад")

Методы обеспечения согласованности

Репликация

  • Синхронная: запись дожидается подтверждения всех реплик. Высокая надёжность, но медленнее
  • Асинхронная: запись подтверждается после обновления основной реплики, остальные догоняют позже. Быстрее, но риск рассинхронизации

Консенсус-протоколы

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

Paxos и Raft широко используются именно внутри распределённых БД и сервисов (например, в etcd, Consul, CockroachDB) для репликации и выбора лидера, чтобы все копии данных оставались согласованными.

  • Paxos: сложный в реализации, требует нескольких раундов сообщений для согласования
  • Raft: более понятный, описан как «Paxos для людей», активно используется (например, в etcd, Consul)

Конфликт-резолвинг

Конфликт-резолвинг (conflict resolution) — подходы к устранению расхождений между копиями данных при eventual consistency.

CRDT (Conflict-free Replicated Data Types)

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

Пример: распределённый счётчик, который можно увеличивать на любом узле, а потом безопасно объединять — каждый инкремент учтётся, независимо от порядка доставки

Last-write-wins (LWW)

Стратегия разрешения конфликта. Сохраняется последнее по времени обновление.
Простая реализация, но возможна потеря промежуточных изменений.

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

Материалы

  1. Согласованность данных: что это на самом деле такое и почему с ней все так сложно
  2. Проблемы согласованности данных в микросервисах и их решение
  3. Согласованность, Репликация и Базы Данных по CAP
  4. Раз-два-много: уровни согласованности Apache Cassandra при распределенной обработке Big Data
  5. Консистентность данных: что это и почему она так важна
  6. Архитектурные паттерны для высокой масштабируемости. Часть 2
  7. Сага о консистентности данных
  8. 26 основных паттернов микросервисной разработки
  9. Алгоритмы консенсуса Paxos, Raft и Zab в распределённых системах
  10. Протоколы консенсуса: PoW, PoS, DPoS – в чем разница?
  11. Азбука блокчейна: протоколы и алгоритмы консенсуса
  12. Небезопасная многопоточность или Race Condition
  13. Согласованность данных в высоконагруженных системах
  14. Связывая Контексты: Руководство по Эффективному Взаимодействию
  15. CRDT: Conflict-free Replicated Data Types

Видео

  1. Микросервисы. Согласованность данных
  2. Добиваемся согласованности данных в распределенных коммуникациях с помощью Transaction Outbox
  3. Микросервисная архитектура (№6)| Согласованность данных между сервисами
  4. Distributed Systems Глава 7 Согласованность и репликация данных | Антон Жуков, Николай Ижиков
  5. Обработка тысяч одновременных записей и обеспечение согласованности данных
  6. NoSQL и согласованность. Percolator
  7. An introduction to Conflict-Free Replicated Data Types (CRDTs), en
  8. Conflict-Free Replicated Data Types (CRDTs) | System Design Fundementals, en
  9. CRDT / Структуры данных
  10. Архитектура CRDT и групповые системы
  11. Параллельные и распределенные вычисления 11. AB, FLP-теорема, CAP-теорема, CRDT
  12. Что такое CRDT? - СЕНЛА Митап - Семен Есаев

Конференции

  1. JPoint:Андрей Ершов — CRDT. Разрешай конфликты лучше, чем Cassandra
  2. Распределенные данные: CRDT-структуры данных в JS. Максим Климишин. JS Fest 2018