4 ms·
> That's not going to be true. It might be true when things are running well, but when it fails, it'll either be at most once or at least once. Silly question
by MuffinFlavored 2y ago
> That's not going to be true. It might be true when things are running well, but when it fails, it'll either be at most once or at least once.
Silly question as somebody not very deep in the details on this.
It's not easy to make distributed systems idempotent across the board (POST vs PUT, etc.)
Distributed rollbacks are also hard once you reach interacting with 3rd party APIs, databases, cache, etc.
What is the trick in your "on message received handler" from the queue to achieve "exactly once"? Some kind of "message hash ID" and then you check in Redis if it has already been processed either fully successfully, partially, or with failures? That has drawbacks/problems too, no? Is it an impossible problem?
- samtheprogram 2y agoYou don’t achieve exactly once at the protocol/queue level, but at the service/consumer level. This is why SQS guarantees at-least-once. It’s generally what you described, but the term I’ve seen is “nonce” which is essentially an ID on the message that’s unique, and you can check against an in-memory data store or similar to see if you’ve already processed the message, and simply return / stop processing the message/job if so.
- mcqueenjordan 2y agoAnd just to add a small clarification since I had to double take: this isn't exactly-once delivery (which isn't possible), this is exactly-once processing. But even exactly-once processing generally has issues, so it's better to assume at least once processing as the thing to design for and try to make everything within your processing ~idempotent.
- bastawhiz 2y ago> What is the trick in your "on message received handler" from the queue to achieve "exactly once"? There's no trick. The problem isn't "how to build a robust enough system" it's "how can you possibly know whether the message was successfully processed or not". If you have one node that stores data for the queue, loss of that node means the data is gone. You don't know you don't have it. If you have multiple nodes running the queue and they stop talking to each other, how do you know whether one of the other nodes already allowed someone to process a particular message (e.g., in the face of a network partition), or didn't let someone else process the message (e.g., that node experienced hardware failure). At some point, you find yourself staring down the Byzantine generals problem. You can make systems pretty robust (and some folks have made extremely robust systems), but there's not really a completely watertight solution. And in most cases, the cost of watertightness simply isn't worth it compared to just making your system idempotent or accepting some reasonably small amount of data loss.