Всем привет и с наступающим рождеством!
На собеседовании задали такую задачку:
В базе было несколько таблиц, в которые данные записывались с помощью транзакции. пусть это будет добавление данных.
Проект вырос и разделился на микросервисы. Теперь каждая таблица находится за отдельным микросервисом, в отдельной базе.
Каким образом разделить транзакцию на запросы к микросервисав, сохраняя консистентность данных.
С такой задачей я не сталкивался, о чем разумеется сообщил, и предложил использовать:
- флаги отвечающие за сохранение данных
- флаг того что данные можно использовать
- метку времени, для очистки данных по расписанию
Пример:
transaction
-----------
id
service_1_saved - метка сохранение данных на сервисах
service_2_saved
service_3_saved
service_1_transaction_complete - метка выполнения транзакции на сервисах
service_2_transaction_complete
service_3_transaction_complete
complete - метка выполнение транзакции
fail_at - метка времени
service_1(2,3)
-----------
id
data
transaction_id
transaction_complete
Суть работы:
Этап 1) Передаем в сервисы данные и устанавливаем флаг service_1.transaction_complete = 0. Пока этот флаг равен 0, данные использовать нельзя. Далее передаем в ответе, что данные сохранены, тем самым устанавливая transaction.service_1_saved.
Этап 2) Если все сервисы обработали и сохранили данные (т.е. заполнены transaction.service_(1,2,3)_saved), считаем транзакцию успешной и обновляем флаг завершения транзакции на сервисах service_(1,2,3).transaction_complete = 1. В ответ обновляем transaction.service_(1,2,3)_transaction_complete = 1
Этап 3) Если все сервисы имеют transaction.service_(1,2,3)_transaction_complete = 1, то завершаем транзакцию устанавливая transaction.complete = 1
В случае провалов, чистим данные используя связь через transaction.id = transaction_id
Такой вот у меня получился транзакципед с сильной связанностью и не очень большой надежностью :)
Вопрос: как это делают правильно?