2

Imagine a 'User' microservice that holds all user's related logic, and this microservice holds a database.

How could you scale this microservice horizontally and keep consistency ?

In fact, if you just add another instance, then if one user is created, updated, or deleted the operation would only be applied in one instance, and as a result you would loose consistency.

What is the most convenient way to be able to scale horizontally and keep consistency ?

  • 1
    Ah, consistency, that quality that's so poorly understood. Consider this peculiarity: If I make two web requests to the same physical machine, one that just reads data and one that changes data, it's completely valid for the read request sent first to return after the later change request, and yet show the original data. Because latency is a thing. When dealing with shared, mutable state, it's best to start with the assumption that all reads are dirty. All distributing the db really does is increase the figurative time between reads and updates, so things are dirtier longer. – Clockwork-Muse Dec 15 '18 at 9:16
1

TL;DR

  • Your web front-ends should not store data: they should be trivial to scale.
  • Use a data store made to scale horizontally (otherwise, learn about sharding)
  • Take advantage of the fact that "microservices" already distribute load

Firstly: Your web front-ends shouldn't really be stateful. They shouldn't store anything you can't afford to lose at any given moment. All the data should live in a dedicated database cluster. You should be able to trash a web front end or add a new one without breaking anyone's sessions or data. Scaling that should be "trivial."

That said, scaling a service's database horizontally requires some sort of sharding. But, if you opt for a document-type store, horizontal scaling through sharding is usually a baked in feature that you just have to configure. (Or, it's a detail you can completely ignore if you're using a scalable database hosting service, like DynamoDB.)


Basically, sharding requires that you identify a field used to determine how data is split across nodes. That might be a user_id, which gets translated into a number. Which database node a particular user record is stored might depend on that ID and a hashing algorithm, for example.

A really basic example might be a modulus of some random, integer-ish user ID. You take user_id % number_of_servers to determine where to store/retrieve the record.

With a nosql database, a lot of the details about how this happens taken care of for you -- you just hit the cluster, and it figures out what to do.

There can certainly be more sophisticated strategies, if you need ACID-like compliance.


That said, one of the benefits of a micro-service is the deferment of this scalability problem. I.e., because your user database is distinct from your product catalog and orders databases and so forth, each of these databases can already be located on different hosts: The traffic is already somewhat distributed.

Unless you're running a truly massive and unprofitable service, you can probably defer the remaining scalability work until you have the budget to address them!

  • I think you meant to say that "Your web front-ends should NOT store data". – aridlehoover Dec 15 '18 at 15:43
  • So if I understand correctly, unless you are building a system that will face a massive load, scaling one microservice in your "micro-services cluster" is not a real problem for "standard" applications as the load is already balanced within your cluster. right ? – Woody Dec 19 '18 at 15:22
  • 1
    @Woody, Sure. That's one take-away. I would suspect that most applications out there don't even need that level of scaling. A pair of web frontends and a single database (ideally with a fallback mirror) are more than sufficient for most of us -- capable of supporting millions of monthly "visits" on sufficient hosts if our applications aren't built horrendously... – svidgen Dec 19 '18 at 15:25
  • Thanks @svidgen It was a pure theoretical questioning, as I did never put in place a micro service architecture. In lots of resources on the web, they say that micro services are scalable "by design". For stateless services it's indeed the case, but I was confused with the "horizontal scalable ready feature by design" for statefull micro services – Woody Dec 19 '18 at 16:00
0

For scalability, there is the assumption that each service is stateless and can therefore be arbitrarily scaled. Stateless here means that any state is stored externally in some database. In this view, a microservice is somewhat separate from any database it uses. In particular, you might deploy multiple instances of the service but have one shared database.

  API users
     |
Load balancing
  /  |    \
MS  MS ... MS
 \  |     / 
Shared Database

The database is not immediately scalable in that design. Note also that this design does not require microservices – you get the exact same scalability benefits from a monolithic design, as long as the processes have no internal state.

Databases are difficult to scale if we want to keep consistency: just launching another instance is not going to help. The typical solution is to give up on consistency, or to use vertical scaling: run the DB on a beefier server. In many cases, adding read replicas to a database can already help a lot. Also, using data warehousing techniques can reduce load on the production database. Microservices help slightly because different microservices can use different databases, thus allowing each microservice's database to be scaled independently.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.