4
votes

I'm starting a personal project to learn about what's the best way to implement microservices. It might be onverengineered but it's more like a learning process. It's probably irrelevant but I'm using .Net Core

How I'm think of designing the solutions is as follow:

  1. Using CQRS pattern so that can easily separate Query and Commands. At the moment, I have 2 end points for that
  2. I have a "manual" API gateway which will act as a proxy for the different microservices I would need
  3. Use NServiceBus to communicate between the microservices

Questions:

  1. I'm thinking of using Redis to cache the Queries. For example, caching the user details. However, as it's a cache, I don't think it should be the source of truth which means I will update another datastore at the same time. From my understanding of the best practices, 1 microservice should only deal with 1 datastore only. So I will create a endpoint dealing with the cache data only which make sense for me.
    What would be the best way to handle and add/update command? Update the cache and fire an event to update the main data store? Or update the data store and fire event to update the cache. My feeling is that I should update the main datastore first before the cache (because I wasn't planning to expose and endpoint to update the cache, it should for readonly purpose only) but that would lead to some potential inconsistency. While I get that, in the microservices world, the data is "eventually consistent", doesn't that mean for a simple operation like an update, the user might not directly have his personal data updated even if he submits his changes?
  2. I can see that people are more and more advocates event sourcing. If (at the moment), I don't really need an auditing or even a way to replay the events, do I need it ? I have a feeling I can do it all using an message bus / sagas which, I think, is much more performant that using an event store. Am I correct?
2
kind if hard to answer this... do you need event sourcing? Well since this is your personal POC why not try it out and see if it gave you something... - Jocke
Take a look at this - Mohsen

2 Answers

3
votes

Architecture decisions are about tradeoffs and since you define the requirements everything goes (esp. in regard to q.2) In regard to q1. It would make sense for each service to use the cache independently not as a common resource (from the deployment perspective you may use a single instance to host the different caches) wrapping the cache API with your own service doesn't seem to make a lot of sense.

Regarding handling commands - eventual consistency is, again, a choice - you can update both the source of truth and cache transactionally (real or approximate depending on your needs), you can mark in a query post update that you want the latest (not cached) version - furthermore who says you even need a cache and there are probably several other options

1
votes

I'm not sure where to begin, but I'll try to answer some of your questions. But I'm 100% with Arnon Rotem-Gal-Oz. This is all about trade-offs.

With messaging, there might be a message in the queue to order an item, which already has a depleted inventory. In other words, while the customer (and the system) thought it could order the product, when the message arrives, it is no longer in stock. From a technical perspective, you could say that this means your data is inconsistent.

From a business perspective, it means a different scenario where you might either return the money, let the customer wait for the stock to replenish or provide them with an alternative. The business can always find a way to deal with inconsistency. In other words, the real world already deals perfectly well with eventual consistency.

Another thing about eventual consistency. Lots of people have issues with eventual consistency, but they don't blink an eye when introducing a cache. But the cache is never 100% in sync with the data-store, so the data that you're retrieving from the cache is already not 100% consistent with the data-store and thus eventually consistent. I hope that answers your questions about eventual consistency a bit? o:-)

I can see that people are more and more advocates event sourcing. If (at the moment), I don't really need an auditing or even a way to replay the events, do I need it?

Even if you need auditing or a way to replay events, I don't see any reason to introduce event sourcing.

Note: I mean the kind of event sourcing where you build (or hydrate) your objects (or aggregates) based on events in some event-store.

Just store the messages you've sent somewhere. That way you have your audit log and you can replay your events. Since you're already using NServiceBus, you can its auditing feature.

If you want to know more about all this, shoot me an email at [email protected] and we can discuss this a bit further.