Диллема обработки сообщений
Ситуация: Имеется очередь, из которой приложение читает данные и обрабатывает их. Рассмотрим пример, что приложение имеет следующий цикл обработки сообщения: 1) Взять сообщение из очереди 2) Попытаться выполнить некоторый набор действий на основе данных из сообщения. Отметим, что обработка сообщения может завершиться как успешно, так и с ошибкой. | ||
1] 1) Получаем сообщение 2) Выполняем коммит сообщения (при следующем чтении на вход пойдет следующее сообщение) 3) Выполняем обработку | Мы теряем сообщение, в случае если его обработка не завершилась успешно. | |
2] 1) Получаем сообщение 2) Выполняем обработку 3) Если п.2 выполнен успешно, то выполняем коммит сообщения (при следующем чтении на вход пойдет следующее сообщение) | В случае, если после выполнения 2 пункта наше приложение упадет (не успев выполнить пункт 3), то при повторном запуске мы обработаем то-же самое сообщение второй раз. | |
Вопросы | ||
Более надежное, но более тяжелое решение: Использование подхода номер 2 совместно с каким-либо более продвинутым механизмом транзакций. Т.е в случае падения приложения транзакция не будет завершена успешно. Но есть риск если у нас выполняются 2 действия: 1) коммит транзакции в базе, 2) коммит сообщения. (или в порядке 2, 1) В случае падения приложения между указанными шагами, мы все равно можем получить либо потерю сообщения (закоммитили сообщение, но не завершили транзакцию), либо повторную обработку (завершили транзакцию, но не закоммитил сообщение). Хоть и вероятность такого события в целом крайне мала. (зависит от системы) | ||
Замечание: на текущий момент отношу проблему к Dual write problem. Отдельный вопрос: хотим ли мы использовать очередь для приостановки обработки в случае ошибок. Зачастую мы не хотим останавливать обработку из-за одной ошибки. В таком случае важно сохранить проблемное сообщение, но при этом сделать так чтобы обработчик продолжил обрабатывать последующие сообщения. Возможен вариант, когда сообщение просто записывается в БД в статусе ожидает обработку. И фоновый обработчик разбирает таблицу и обрабатывает необходимые строки. |