В современных архитектурах мы часто отправляем сообщения. Например, мы записали что-то в базу данных, обновили пользователя, а потом отправили сообщение с новым телом сущности в
RabbitMQ. Чтобы все, кто интересуется, узнали об этом и могли сделать что-то, на основе этой информации.А что будет, если
RabbitMQ будет недоступен в этот момент и сообщение не отправиться ☠️? Можно добавить какой-то retry, можно вообще откатить транзакцию и ответить 500. Можно "потерять" это сообщение, таких случаев ожидается мало, но лучше не "терять", ведь тогда может нарушиться цельность данных в нашей информационной системе.Есть другое решение — использовать технику
write-ahead log. В таком случае, отправка сообщения будет, грубо говоря, состоять из трех шагов:1. Записываем что нужно отправить в базу данных, в табличку
events, ставим статус PENDING
2. Какой-то worker периодически проверяет эту табличку и отправляет сообщения со статусом PENDING
3. Если сообщение отправилось, ставим ему статус SENT
4. Бонус. Время от времени удаляем строки у которых статус SENT
В таком случае, мы убиваем двух зайцев. Во-первых, наша основная операция — запись в базу данных обновления про пользователя, не падает, если мы не может сделать вторичную (отправить сообщение). Во-вторых, мы уверены, что все сообщения уйдут.Эта же техника используется движками баз данных для обеспечения atomicity и durability из
ACID. Только базы данных записывают информацию в файл, а потом в саму базу данных.⬛️ Еще раз — если вы хотите быть уверенными, что действие будет выполнено, используйте технику
write-ahead log. Это делает программу сложнее, но стабильнее.Реализовывали такое сами? Пишите в комментариях
#хардскиллы