У меня есть следующий потребитель rabbitMq:
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, MQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
sendNotificationIntoTopic(message);
saveIntoDatabase(message);
}
};
Может возникнуть следующая ситуация:
- Сообщение было успешно отправлено в тему
- Соединение с базой данных потеряно, поэтому вставка базы данных не удалась.
В результате мы имеем несоответствие данных.
Ожидаемый результат: либо оба действия были успешно выполнены, либо оба не были выполнены вообще.
Какие-нибудь решения, как я могу достигнуть этого?
приписка
В настоящее время у меня есть следующая идея (пожалуйста, прокомментируйте)
Можно предположить, что брокер не потерял ни одного сообщения.
Мы должны подписаться на тему, которую хотим отправить.
- Сохранить запись в базе данных и установить поле
status
со значением 'pending'
- Попытка отправить данные в тему. Если отправка прошла успешно - обновите поле
status
со значением 'success'
У нас должна быть запланированная работа, которая должна проверять строки с ожидающим статусом. На данный момент возможны 2 случая:
3.1 Уведомление не было отправлено вообще
3.2 Уведомление было отправлено, но сохранить в базе данных не удалось (вероятность очень низкая, но это возможно)
Таким образом, мы должны как-то различать два случая: мы можем хранить сообщения из темы в коллекции, а задание может проверять, принято сообщение или нет. Поэтому, если задание обнаружило сообщение, соответствующее строке базы данных, мы должны обновить статус до «успех». В противном случае мы должны удалить запись из базы данных.
Я думаю, что моя идея имеет некоторые недостатки (например, если у нас есть многоузловое приложение, мы должны хранить сообщения в Hazelcast (или аналогах), но это дополнительная точка гипотетического сбоя)