csadewa

csadewa

Question about implementing sharding of request based on aggregate to fix concurrency bugs

Currently, i was working on a project in which the backend services is in microservice + each service can have multiple instance. However, i from time to time deals with concurrency issue in case of two API request which mutate same data happen at very similar time. There’s many way to “deal” with such concurrency issue, like optimistic locking (ecto implement this BTW), random delay on processing request, etc. But i am currently researching on possibility of using Request sharding based on Domain Aggregate.

The system work like this: When there is a HTTP (Mutation) Request, it will be handled by HTTP Handler process which would determine the aggregate ID for HTTP request (request can be already have the ID, or it may need to do additional query to DB for the ID). then HTTP handler would send message to unique worker process (based on Aggregate ID) which would process all request for work for a particular aggregate ID serially. After work is finished, unique worker send the result back to HTTP handler which would forward it as HTTP Response.

The question i was wondering:

  1. was anyone have ever work on similar system? was it performant enough?
  2. I am not sure how to implement step “3. Send request to work on Mutation Request
    To unique worker based on Aggregate ID” and “5. Send Work Result back to Request Handler” in a multiple microservice instance environment, could you give pointer?

Marked As Solved

sb8244

sb8244

Author of Real-Time Phoenix

I worked on a system that would send requests to a process based on a shard ID. The process was made unique using :global process (I know about netsplits). That system worked really well for us and we never hit any issues with that aspect of it. That system was doing external API requests, not database queries, so I didn’t have the ability to do anything fancy with the database. However, it was an optimization solution. It would be correct even if the cluster netsplit and 2 processes did the same work.

If it was possible, I would certainly try to solve this via the database and not have any fanciness on the Elixir application side. The reason is that you have a correctness problem here. If you mutate incorrectly, then your data is incorrect. This makes the problem of netsplits or general blips a much bigger concern.

My immediate thought process follows this order:

  1. Atomic updates are preferable. No magic required anywhere
  2. SELECT FOR UPDATE a single record to lock it during the write. Always perform modifications after the record is loaded to 100% guarantee you have the latest version
  3. Advisory lock around a group of operations to ensure they don’t enter simultaneously
  4. SGP (single global process) based on aggregate ID to perform the updates

The database operations are preferred for the reasons I mentioned above. If you go the SGP route, then it’s likely still okay performance-wise, because there’s a global process per domain aggregate ID.

This is a fairly deep question because it highly depends on your microservice architecture. I only ever did this within the cluster of a single application and would never have tried it cross microservice. There’s just too much that can go wrong. Likely, you’ll need to use whatever request/response API you prefer between the microservices (like HTTP, gRPC, etc).

Also Liked

sb8244

sb8244

Author of Real-Time Phoenix

No, we didn’t even consider locks in our case. The process based approach seemed to fit really well and didn’t have any real downside for us.

There’s other details about the particular use case that pointed to processes being the right approach. I wrote about it at the time: Stephen Bussey - 28 Days - Demo - Single process in a distributed system

The big thing here is optimization vs correctness. Even if every node became split, the application would still be correct in the case I’m referencing.

In this case, you’ll probably find the blog post above useful. I’d still point you to the database approach if it’s possible, but maybe it’s okay you have a bit of fun sometimes as long as you know the downsides you might experience.

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

We're in Beta

About us Mission Statement