Гарантия консистентности двух и более состояний
Статья
описывает проблему гарантии полноты и неизбыточности при последовательной установке двух состояний;
выдвигает гипотезу о невозможности разрешения проблемы без участия состояний (без идемпотентности состояний);
предлагает Общее решение.
Задача
Поток T должен установить два состояния S1 и S2.
S1 и S2 возвращают синхронный ответ при успехе сохранения и не более.
Требуется гарантировать полноту и не избыточность установки состояний.
Проблема
Поток Т выполняет запись в S1.
При провале поток Т возвращает отказ.
При успехе поток Т должен выполнить запись в S2.
Начиная с этого момента возникает проблема неопределенности при ошибке установки S2 или крахе потока Т.
состояние S1 уже установлено, а S2 не установлено;
однозначно не определен результат исполнения потока T;
повторный вызов потока Т не разрешит ситуацию.
Гипотеза
Не существует решения при котором поток Т гарантирует полноту и неизбыточность установки двух состояний, при том что состояния возвращают исключительно синхронный ответ о результате сохранения.
Никакие механизмы со стороны Т не могут разрешить указанную проблему без идемпотентности S1.
Варианты решения
Состояние S1 должно быть идемпотентным например:
защита от дублированного получения данных;
возможность оповещения T по его инициативе о результатах сохранения.
T должен обладать возможностью повтора установки состояний при отказе.
Общее решение гарантии консистентности состояний
Ниже перечислены рассматриваемые виды состояний:
S - (simple state) простое состояние без поддержки транзакций и идемпотентности, например:
очереди сообщений (kafka, итд);
внешние сервисы;
базы без идемпотентных проверок, с триггерами или автокоммитом;
журналирование.
I - (idempotent state) - состояние с поддержкой идемпотентности:
базы данных;
сервисы;
файлы.
T - (transact state) - состояния, поддерживающие транзакционную целостность.
базы данных TSQL.
Таблица возможных комбинаций
Таблица демонстрирует:
возможные комбинации последовательной установки состояний в синхронном потоке;
гарантию итоговой консистентности для различных вариантов;
последствия сбоя в потоке между установкой состояний.
Обязательным условием является повтор вызова потока пр отказе на любой стадии.
пример:
Поток получает сообщение из очереди, которая гарантирует повторяемость.
Вызов потока из UI не гарантирует повторяемость события, так как пользователь получив ошибку, может не выполнить повторное действие.
Состояния | Гарантия | Пример | Негативные последствия |
---|---|---|---|
SS | нет | Push сообщения в очередь; Write в журнал | Накопление дублей сообщений в очереди |
SI | нет | Commit сообщения очереди; Идемпотентный вызов сервиса | Отсутствие вызова сервиса |
ST | нет | Commit сообщения очереди; Insert в базу | Накопление дублей сообщений в очереди |
IS | да | Insert с предпроверкой в базу; Commit сообщения очереди | Многократные попытки Insert |
II | да | Insert с предпроверкой в базу; Update с предпроверкой в базу | Многократные попытки Insert |
IT | да | Вызов внешнего сервиса; Запись в базу | Многократный вызов внешнего сервиса |
TS | нет | Insert в базу; Push в очередь | Накопление дублей в БД |
TI | нет | Insert в базу; Запись с предпроверкой в базу | Накопление дублей в БД |
TT | да | Insert в базу; Запись в базу в одной транзакции | Полный откат транзакции |
Общие правила гарантии сохранения состояний
Повторяемость вызова при любом отказе в потоке
И идемпотентность предыдущего изменения состояния
ИЛИ изменение всех состояний в единой транзакции.