I'm learning about microservice data replication right now, and one thing I'm having trouble with is coming up with the right architecture for ensuring event atomicity. The way I understand it, the basic flow is:
- Commit changes to a database.
- Publish an event detailing the changes on the global message bus.
But what if, for example, a power outage occurred in-between Steps 1 and 2? In a naively-built system, that would mean the changes persist but the event detailing them will never be published. I've pondered the following ideas to create better guarantees, but I'm not quite sure of all the pros and cons of each:
A: Use an embedded database (like SQLite) in my microservice instance to track the full transaction, from the commit to the main database to the event publishing.
B: Create an Events table in my main database, using database transactions to insert the Event and commit the relevant changes at the same time. The service would then push the Event to the bus, and then make another commit to the main database to mark the Event as Published.
C: As above, create an Events table in my main database, using database transactions to insert the Event and commit the relevant changes at the same time. Then, notify (either manually via REST/Messages from within the service or via database hooks) a dedicated EventPusher service that a new event has been appended. The EventPusher service will query the Events table and push the events to the bus, marking each one as Published upon acknowledgement. Should a certain amount of time pass without any notification, the EventPusher will do a manual query.
What are the pros and cons of each of the choices above? Is there another superior option I have yet to consider?