Детекція та вирішення конфліктів
1) Що вважати конфліктом
Конфлікт - це ситуація, коли два або більше джерела змін претендують на несумісні стани однієї і тієї ж сутності, ресурсу або інваріанта.
Синтаксичні: перетинаються зміни одного файлу/ключа (merge conflict в Git, patch-колізії в Kustomize).
Семантичні: коректний за схемою документ порушує бізнес-інваріант (сума дебету ≠ кредитом, ліміт перевищено).
Операційні/тимчасові: перегони запису/читання, дублюючі події, розбіжність причинно-наслідкових зв'язків.
Доменні: конкуруючі операції над ресурсом (подвійний продаж квитка, овербук товару).
Завдання: виявити конфлікт якомога раніше, пояснити його причину і безпечно вибрати одну з дій: автовідновлення, ретрай, злиття, компенсація, ескалація.
2) Механізми детекції
2. 1 Версійність і порівняння станів
ETag/If-Match в REST, rowversion/xmin в DB - виявлення lost update.
3-way merge (base, ours, theirs) - підсвічування несумісних правок.
Checksum/Hash по полю/документу - дешеве порівняння.
2. 2 Тимчасові та причинні мітки
Lamport clock: тотальний порядок «наближено за часом».
2. 3 Інваріанти та обмеження
Схеми і валідатори (JSON Schema/OpenAPI) - синтаксична валідність.
Інваріанти: унікальність, невід'ємність, баланс, ACL-правила.
Перевірки цілісності: FK/UNIQUE/EXCLUDE індекси, partial constraints.
Доменні assert'и в коді/політиках (OPA/Kyverno/Conftest).
2. 4 Детекція в потоках подій
Idempotency Key/Dedup Store (наприклад, Redis/DB з TTL): відбраковка дублів.
Transactional/Exactly-once в стрімінгу: transactional id, producer epoch, консюмер-офсети.
Sequence gap detection: пропуски, повторення (n, n + 1, n + 1).
2. 5 Спостережуваність і сигналізація
Прометрики помилок/конфліктів/ретраїв.
3) Стратегії вирішення
3. 1 Повністю автоматичні (безпечні за визначенням)
CRDT (Conflict-free Replicated Data Types): G-Counter, PN-Counter, OR-Set, LWW-Register, Map/Graph CRDT.
Гарантія конвергенції без координації; важливий вибір семантики втрат/збереження.
Комутативні операції: застосовуються в будь-якому порядку (інкременти, лог-апенди).
Idempotent handlers: повторення не змінює результат (upsert за ключем, put-if-absent).
Оптимістичне злиття структур: 'deep merge + policy'з детермінованим порядком.
3. 2 Напівавтоматичні (з політикою)
3-way merge + правила масивів ('replace'append'uniqueBy (key) |patchBy (key)').
LWW (Last-Write-Wins): простий, але ризик втрати причинної коректності.
Пріоритети джерел: «інтерактивне введення> конфіг з файлу> дефолти».
Бізнес-правила: «якщо ліміт перевищено - часткове підтвердження/компенсація».
3. 3 Координаційні
OCC/MVCC (оптимістичне блокування/багатоверсійність): звірка версій, ретрай.
Песимістичні блокування: `SELECT... FOR UPDATE', розподілені локи (Redlock/DB-lock/etcd).
Консенсус (Raft/Paxos): один лідер вирішує порядок; конфліктів менше, ціна - латентність.
3. 4 Людина-в-контурі (HITL)
UI для ручного мерджа/арбітації (особливо - контент, тарифи, каталоги).
Перегляд дифа, пояснення політики, кнопки: «прийняти ours/theirs», «об'єднати поля», «створити компенсацію».
4) Патерни по шарах архітектури
4. 1 API/REST/gRPC
Optimistic concurrency: `If-Match: <etag>', 409/412 при конфлікті → клієнт ретраїть з урахуванням свіжого ETag.
Idempotency-Key в POST (платежі/замовлення).
Семантичні 409: повідомляйте причину і пропоновані дії.
4. 2 Сховища даних
RDBMS: MVCC (snapshot isolation), унікальні індекси, часткові індекси.
KV/Doc stores: версії/ревізії (rev), compare-and-swap (CAS).
Мультимастер реплікація: застосовуйте годинник версій/CRDT або «write to leader only» для критичних сутностей.
4. 3 Черги/стрімінг
Exactly-once (практично - «ефективно один раз»): транзакційний продюсер + атомарний write-to-sink.
Dedup на консюмері: зберігання останніх N id, логіка upsert/merge.
Outbox/Inbox патерн: узгоджена публікація подій.
4. 4 Конфігурації та IaC
3-way merge в GitOps, policy-gates (OPA/Kyverno) до застосування.
Kustomize/Helm: детерміновані стратегії мерджа і заборона «невідомих ключів».
Terraform: план-дифф як сигнал конфлікту «drift vs desired».
5) Алгоритми та приклади
5. 1 3-way merge (спрощений)
text resolve(base, ours, theirs):
diff1 = delta(base, ours)
diff2 = delta(base, theirs)
if independent(diff1, diff2): return apply(base, diff1 ⊕ diff2)
if conflictsOnlyInArrays: return arrayPolicyMerge(...)
else:
return CONFLICT with hunks
5. 2 OCC для REST-ресурсу
http
Client reads
GET /accounts/42 -> ETag: "v17", body: {balance: 100}
Trying to write off
PUT /accounts/42
If-Match: "v17"
{balance: 50}
If someone has managed before
HTTP/1. 1 412 Precondition Failed
{error: "version_mismatch", currentEtag: "v18"}
Клієнт перечитує, застосовує дельту до актуального стану і повторює.
5. 3 Семантичний конфлікт (інваріант)
pseudo on Debit(accountId, amount):
current = read(accountId)
if current. balance - amount < 0:
return REJECT ("insufficient _ funds") # write early detection (accountId, version = current. version+1, balance=current. balance - amount)
5. 4 CRDT: OR-Set (ескіз)
Елементи додаються з унікальним tag, видалення - за конкретними tag.
Конфлікт «add vs remove» вирішується завдяки тегам: remove видаляє лише видимі add-теги.
6) Політика дозволу: Як формалізувати
Опишіть в архітектурній доктрині:1. Порядок джерел (priority chain).
2. Стратегії за типами даних: скаляри/об'єкти/масиви/мультимедіа.
3. Причинна модель: чи використовуєте ви версії, Lamport, vector clocks.
4. Семантика втрат: що може бути втрачено при LWW, де потрібен консенсус.
5. Тимчасові вікна: TTL для дедуплікації, вікна ідемпотентності.
6. Ескалація: коли авто-дозвіл заборонено, вимоги до UI/approval.
7. Компенсації: SAGA-стратегії «cancel/compensate» для перезбірки інваріантів.
7) Метрики та SLO
conflicts_total{type} - частота за типами.
conflicts_resolved_auto_ratio - частка авто-дозволів.
mean_time_to_resolution - середній час до врегулювання.
lost_update_incidents - інциденти втрачених оновлень.
idempotency_hit_rate - частка спрацювали Idempotency-ключів.
divergence_depth - глибина розбіжності реплік (версійні вектори).
SLO-приклад: «≥ 99% синтаксичних конфліктів вирішуються автоматично за ≤ 5 с, семантичні - за ≤ 15 хв з HITL».
8) Практичні сценарії
8. 1 Платежі
Ключ: ідемпотентність (Idempotency-Key), OCC на балансі, SAGA для оборотних кроків.
Конфлікт: подвійне списання → дедуп + перевірка версії балансу → часткова компенсація.
8. 2 Інвентар/квитки
Параметри: песимістичне блокування слота/місця; оптимістична бронь з витікаючим TTL; черга «compare-and-reserve».
8. 3 Контент/каталоги
3-way merge + HITL: редактор вибирає підсумок; авто-правила для «безпечних» полів (SEO-мітки, що не впливають на ціну).
8. 4 GitOps/Kubernetes
Рендер і валідація до застосування; reject on unknown keys; заборона «--force» без рев'ю.
Drift-детекція і policy-enforced відкат.
9) Анти-патерни
LWW скрізь: простота ціною втрат причинності.
Приховані ретраї без ідемпотентності: лавиноподібні дублікати.
Відсутність явної політики масивів: «тиха» втрата точок конфігурації.
Глобальні м'ютекси поверх мереж: SPOF і тривалі блокування.
«Сліпі» компенсації без аудиту причин: повторні конфлікти.
10) Чек-лист впровадження
- Визначте типи конфліктів у домені та інваріанти.
- Виберіть механізм версійності (ETag/xmin/vector clock).
- Увімкніть ідемпотентність у критичних POST/commands.
- Задайте політику мерджа за типами даних (скаляри/масиви/об'єкти).
- Увімкніть валідатори схем і доменні перевірки до коміту.
- Налаштуйте метрики конфліктів і аларми.
- Для критичних сутностей - лідер/консенсус, або CRDT.
- Пропрацюйте HITL-флоу і UX (диф, коментарі, audit log).
- Документуйте SLO і процедури компенсацій (SAGA).
11) FAQ
Q: Коли вибирати CRDT, а коли - консенсус?
A: CRDT підходить, коли допустима eventual consistency і важлива висока доступність/локальні записи. Консенсус - для даних з жорсткими інваріантами і суворим порядком операцій (грошові баланси, права доступу).
Q: Чи достатньо LWW?
A: Для кешів, метрик і вторинних індексів - часто так. Для користувацьких даних і грошей - майже завжди немає.
Q: Як вибрати вікно дедуплікації?
A: Орієнтуйтеся на максимальну очікувану затримку повторної доставки + джиттер мережі, додайте запас 3-5 × п99.
Q: Чи потрібно завжди робити HITL?
A: Ні, ні. HITL залишайте для спірних/вартісних конфліктів; решту автоматизуйте і логуйте.
12) Підсумки
Ефективна детекція і вирішення конфліктів - це комбінація версійності, причинних міток, інваріантів і чіткої політики, доповнена відповідними алгоритмами (CRDT/OT/OCC/MVCC/консенсус) і спостережуваністю. Системи, де конфлікт - «нормальна» ситуація, залишаються доступними і передбачуваними; системи, де конфлікт - «виняток», ламаються в самий невідповідний момент. Виберіть модель, формалізуйте правила і вимірюйте результат.