Strong Consistency: коли потрібно
Strong Consistency (лінійризованість) - модель, при якій всі операції виглядають так, немов виконуються миттєво і послідовно в єдиному глобальному порядку, узгодженому з реальним часом. Користувач прочитає останнє підтверджене значення, а два паралельних клієнта не «обженуть» один одного логічно.
Сувора узгодженість дає просту ментальну модель і захищає жорсткі інваріанти, але вимагає координації (кворумів/лідера), що підвищує затримку і чутливість до мережевих розділень.
1) Коли Strong - обов'язковий
Фінанси та розрахунки
Баланси та списання: «подвійна трата» неприпустима.
Переклади та взаєморозрахунки: одна і та ж сума не може бути проведена двічі.
Інвентар і ліміти
Залишки товару/місця в готелі/квитки: не можна йти в від'ємні значення.
Ліміти операцій в одиницю часу (кредитні ліміти, API-кредити).
Унікальність і цілісність
Унікальні логіни/ідентифікатори/правила дедуплікації.
Інваріанти на рівні домену: «у відділенні повинен чергувати ≥1 лікар», «в черзі не може бути> N активних завдань».
Аудит і незмінні журнали
Події, що служать юридичним джерелом істини: порядок і повнота критичні.
Якщо порушення інваріанта несе неприйнятний бізнес-ризик (втрата грошей, санкції, втрата довіри) - вибирайте Strong Consistency.
2) Що саме «суворе»
Linearizability (операційний рівень): читання бачить найостанніший успішний запис; часи поважаються.
Serializable (транзакційний рівень): результат еквівалентний виконанню транзакцій послідовно (може бути strong, але іноді реалізований без жорсткого real-time порядку).
Важлива різниця: Serializable захищає від аномалій рівня транзакцій (phantom/write-skew), а Linearizable - про моментальність і порядок одиночних операцій. Часто потрібні обидві властивості (наприклад, гроші в БД + журнал подій).
3) Ціна строгості: PACELC и CAP
PACELC: при поділі мережі (P) доводиться вибирати C (строгість) або A (доступність). Strong → CP: краще відмовити або заблокувати, ніж порушити інваріант. Коли поділу немає (EL), платимо L - координацією/кворумами зростає p95/p99.
Практика: strong для «ядра інваріантів», навколо - швидкі проекції/кеші з eventual, щоб не страждав UX.
4) Як досягають Strong Consistency
Лідерство і кворуми
Єдиний лідер приймає записи; читання - у лідера або за кворумом реплік.
Кворум'W'для запису і'R'для читання з'R + W> N'підвищує шанси читати «останнє».
Алгоритми узгодження
Raft/Paxos: лог реплікації, підтвердження більшості, термін/індекси.
Синхронна реплікація: запис підтверджується тільки після персистентності на кворумі.
Годинник і порядок
TrueTime/Hybrid Logical Clocks (HLC): обмеження розсинхрону годин для безпечної глобальної серіалізації.
Fence-токени/версіонування: захист від «ранкових» лідерів і спліт-брейну.
Ізоляція транзакцій
Serializable (SI + перевірка конфліктів/локи за предикатами): захист від phantom/write-skew.
Strict-serializable: серіалізованість + лінійризованість щодо реального часу.
5) Мульти-регіон: варіанти і компроміси
Глобальний лідер (CP)
Записи йдуть через один регіон-лідер; читання - локальні кеші/проекції або через лідера.
Плюси: Проста модель. Мінуси: p95/RTT до лідера, при P - блокування записів.
Регіональні лідери + синхронний кворум
Георозширений кворум з декількох регіонів; кожен запис чекає підтверджень> 50%.
Плюси: без єдиної «вузької шиї», висока стійкість. Мінуси: міжконтинентальна латентність.
Geo-partitioning
Дані «домашні» для регіону (тенант/юрисдикція); глобальні операції - через саги/агрегати.
Плюси: низькі затримки для локальних записів. Мінуси: планування меж даних.
6) Налаштування R/W і читань
Записи: 'W = majority'- стандарт для strong.
Читання:- «Найсвіжіше» -'R = majority'або читання у лідера.
- Для зниження L - «stale-ok» читання з реплік для другорядних екранів (з явним маркуванням в UX).
- Read-repair / lease read: оптимізації без втрати строгості при коротких орендах лідера.
7) Продуктивність і UX
Латентність: орієнтуйтеся на RTT між клієнтом і лідером/кворумом (міжрегіонально сотні мс).
Патерн «write-strong, read-fast»: strong на записі + кеш/проекції на читаннях, з RYW для автора.
Batch/пакети: групуйте записи, але стежте за хвостовою латентністю.
Контури деградації: при інциденті - read-only, чесні статуси, заборона небезпечних мутацій.
8) Спостережуваність strict-шляху
Метрики
p50/p95/p99 latency: write-кворум, read-кворум, лідерські читання.
Успішність кворумів, повтори/відкати, зміни лідера.
Реплікаційний лаг (очікувано малий, але моніторити обов'язково).
Частка «стейл» читань (якщо включені).
Трейсинг
Спани: «прийняття лідером», «реплікація», «коміт кворуму».
Теги: `term`, `leader_id`, `quorum_size`, `region`.
Алерти
Зростання p95/p99, часта переобрання лідера, кворум-timeouts, split-brain індикатори.
9) Тести і хаос
Jepsen-подібні: мережеві розділення, затримки, дропи, clock-skew.
Safety-інваріанти: неможливість подвійної витрати/негативних залишків/подвійного бронювання.
Лідерство: відмова лідера, перевибори під навантаженням, fence-токени.
Узгодженість читань: читання відразу після запису має бачити «нове» (RYW/linearizable read).
10) Плейбуки інцидентів
Втрата кворуму: переключити в read-only, сповістити клієнтів, направити запис в «домашній» регіон при наявності geo-partitioning.
Зростання латентності міжрегіонально: тимчасово знизити обсяг строгих записів (міграція частини потоків у черзі/проекції), локалізувати трафік.
Флап лідера: збільшити таймаути виборів, перевірити мережі/годинні дрейфи/GC-паузи.
Split-brain: включити fence-токени/lease-перевірки, зупинити старих лідерів на рівні оператора.
11) Типові помилки
Вимагати Strong «скрізь»: вибух латентності і вартості замість фокусування на інваріантах.
Намагатися бути CA при реальних поділах: у момент P система все одно робить вибір, часто неявно.
Dual-write в різні регіони без саг/координатора: фантоми і втрата інваріантів.
Відсутність RYW: користувач не бачить свою щойно записану сутність - падіння довіри.
Ігнорування годинників: без HLC/TrueTime-кордонів легко отримати «стрибаючий» час і гонки.
Немає плану деградації: при P починаються хаотичні часткові збої.
12) Швидкі рішення (рецепти)
Платежі/баланси: лідер + majority-кворум; транзакції strict-serializable; короткі таймаути, жорстка відмова при P.
Бронювання (місця/слоти): write-strong через лідер, читання - кеш з RYW; TTL-резерви + TCC.
Глобальний SaaS: geo-partition по `tenant/region`; строгі операції в домашньому регіоні, звіти/пошук - через проекції.
Аудит/журнал: append-only CP-журнал; читання можна кешувати, але верифікувати контрольними точками.
13) Чек-лист перед продом
- Виписані інваріанти, що вимагають strong; решта - в АР/проекції.
- Вибрано режим: єдиний лідер/кворум міжрегіонально/geo-partition.
- Налаштовані'W = majority','R = leader'majority'для критичних шляхів.
- Забезпечені RYW/monotonic для UX; явно позначені «stale-ok» читання.
- Включені метрики кворуму, лагів, латентностей; алерти на p95/p99 і переобрання.
- Є degrade-план: read-only, відключення небезпечних мутацій, черги на «після шторму».
- Хаос-тести: розділення, clock-skew, відмова лідера; перевірені safety-інваріанти.
- Документація контрактів: що строго, що «може відставати», комунікація для продукту/підтримки.
Висновок
Strong Consistency - інструмент захисту істини там, де помилка неприйнятна. Застосовуйте її точково навколо жорстких інваріантів, усвідомлено сплачуючи за координацію латентністю і доступністю в шторми. Комбінуйте: CP-ядро для критичного, AP-читання і проекції для швидкості. З правильною телеметрією, деградацією і тестами ви збережете і коректність, і користувальницький досвід.