2

У меня есть приложение, в котором мне нужно хранить некоторые данные в базе данных (например, mysql), а затем публиковать некоторые данные в очереди сообщений. Моя проблема: если приложение сработает после хранения в базе данных, мои данные никогда не будут записаны в очередь сообщений, а затем будут потеряны (таким образом, в конечном итоге моя система не будет гарантирована). Как я могу решить эту проблему?Возможная согласованность с записями базы данных и записей сообщений

+0

Вы должны были бы трекер, который знает, какие сообщения были отправлены и то, что не были отправлены –

+0

Это может помочь https://vimeo.com/111998645 – tomliversidge

ответ

5

У меня есть приложение, в котором мне нужно хранить некоторые данные в базе данных (например, mysql), а затем публиковать некоторые данные в очереди сообщений. Моя проблема: если приложение сработает после хранения в базе данных, мои данные никогда не будут записаны в очередь сообщений, а затем будут потеряны (таким образом, в конечном итоге моя система не будет гарантирована). Как я могу решить эту проблему ?

В этом конкретном случае ответом является загрузка данных очереди из базы данных.

То есть вы пишете сообщения, которые должны быть поставлены в очередь в базу , в той же транзакции, которую вы используете для записи данных. Затем, асинхронно, вы читаете эти данные из базы данных и записываете их в очередь.

См. Reliable Messaging without Distributed Transactions, Udi Dahan.

Если приложение аварийно завершает работу, восстановление происходит просто - во время перезагрузки вы запрашиваете базу данных для всех непризнанных сообщений и отправляете их снова.

Обратите внимание, что эта конструкция действительно ожидает, что потребители сообщений будут разработаны для at least once delivery.

+1

Очень полезное видео. Но я удивлен, что нет известных библиотек, которые делают «часть» процесса – ayorosmage

+1

. Более того, необходима база данных, поддерживающая транзакции. Таким образом, я думаю, что базы данных nosql, такие как mongodb, не могут быть использованы для этого. – ayorosmage

+0

Должны ли быть события домена идемпотентны? Являются ли другие варианты для реализации возможной согласованности с использованием событий, отличных от idempotent? – xfg

2

Это слишком долго для комментария.

Я предполагаю, что у вас есть очередь сообщений без потерь, где, как только вы получите подтверждение для записи данных, в очереди гарантируется запись.

В принципе, вам нужен цикл с транзакцией, которая может откат или статус в базе данных. Псевдо-код для сделки:

  • начать транзакцию
  • Вставьте в базу данных
  • Запись в очередь сообщений
  • Когда очередь сообщений подтверждает, фиксации транзакции

Лично я бы, вероятно, сделать это со статусом:

  • Вставьте в базу данных со статусом «в ожидании» (или что-то в этом роде)
  • Запись в очередь сообщений
  • Когда сообщение, подтверждающее, изменить статус на «приверженность» (или что-то подобное)

В случае восстановления после сбоя, вам может потребоваться проверить очередь сообщений, чтобы увидеть, действительно ли какие-либо «ожидающие» записи были записаны в очередь.

+2

Спасибо за ваш ответ, я до сих пор есть некоторые проблемы: 1) Если я пишите в очередь сообщений перед совершением транзакции, сообщение в очереди может быть обработано до совершения транзакции. 2) Если мой идентификатор создается базой данных, я не могу включить его в сообщение, отправленное в очередь. – ayorosmage

0

В дополнение к тому, что сказал @Gordon Linoff, предполагая, что долговечный обмен сообщениями (что-то вроде MSMQ?), Метод/обработчик будет транзакционным, поэтому, если все будет успешным, сообщение будет записано в очередь и данные на ваш просмотреть модель, если она не удалась, все провалится ...

Чтобы уменьшить проблему с идентификатором, вам нужно будет использовать GUID вместо ключей сгенерированных БД (если вы используете обмен сообщениями, в любом случае вам нужно будет удалить вашу ссылочную целостность и ввести GUIDS как ключи).

Еще одно предложение: не обновляйте базу данных, а только вставку/upsert (ожидающую строку, а затем завершенную строку) и попросите читателя выполнить проекцию данных на основе последней строки (например)