0

My task is to process asynchronously balance deltas for multiple clients and provide aggregated balance amounts.

I have a REST service which accepts requests from N clients C₁…Cₙ, each of them has its own financial balance value which changes throughout time. These clients send their positive/negative balance updates to the REST service, it accumulates and aggregates them. For instance, C₁ has initial balance amount of 100 and sends this sequence: [+20, -15, +5], so the resulting balance should be 110.

Amount of requests is quite a big and my current solution is the following. Each request is being stored as a separate record in DB table specifying client ID and a delta value. The pool of background worker threads sums deltas for those clients which are assigned to a certain thread. For instance, only Thread₁ and no other will process, say, C₁, C₁₀, C₂₀ and C₃₀. The assignment is performed on insertion of a new record with delta value.

This approach has one drawback. For example, if several clients (say, C₁₀, C₂₀) which produce heavy traffic are assigned on the same worker thread (say, Thread₁), all other threads will be idling most of the time as opposed to this Thread₁. Reassignment of C₂₀ to Thread₂ would make the system more performant, but it is not possible in this design. It requires dynamic reassignment which requires some kind of "stop-accepting-requests" action followed by clients weight recalculation and reassignment. (UPD: Or calculating each client weight in the background and stopping accepting requests at least from those clients which should be reassigned.)

Letting workers process arbitrary records will lead to wrong balance values since it is not allowed for the balance to be less than zero.

Are there any ideas on how to improve this solution?

  • Do you really need an assignment of threads to clients? Why not initiate a thread per command, let the thread get the current balance from the database, recalculate the balance, write it back to the db, and end the thread? For making the balance calculations in the correct oder, you just have to avoid processing a new command for the same client as long as the previous command for that client was not processed completely. Would that become too slow? – Doc Brown Mar 1 '18 at 21:50
  • I think this may be really slow and I'm trying to avoid single command processing with database involved in this. My goal was to perform bulk calculations. – igorp1024 Mar 1 '18 at 22:20
  • 1
    Maybe this will become slow, maybe not. But you should do at least a rough estimate on this to be sure. Ok, let us assume this will be too slow: I think rebalancing will get way easier if you design the system so not handle multiple clients by one thread at once. Do you know the number x of threads your system can handle? Do you know the number of clients y to expect which will connect simultanously? Is y really so much bigger than x that you need to handle more than one client per thread? We need some numbers here to help you with the design (and you need them, too). – Doc Brown Mar 2 '18 at 6:38
  • If your request consists of a single signed integer addition, just doing that directly will inevitably be much, much faster than pretty much any queueing/control/dispatch logic. It's certainly much faster than storing the request in a DB and retrieving it later to perform a single addition. – Useless Mar 5 '18 at 10:25
2

There is really not enough information to answer this question because it depends on an understanding of the worst-case latency requirement, which is not supplied in the question, and would be difficult to use without understanding the specifics of your system, even if it was supplied.

Here are some thoughts in random order (combine them as needed):

  • You could establish that initially, all threads process requests from all clients.

    Then as the threads get hot, you can selectively drop clients from the threads, making sure that each client has at least one thread.

  • When you detect a hot thread, select a hot client to move to a cold thread. Command the hot thread to forward the client's current balance to the cold thread, while at the same time, changing new requests to go to the cold thread.

  • Have your threads constantly sharing the balances with the other threads in advance so they can take over at a moment's notice.

  • Only do the above with threads that rise above a certain heat, and for clients above some other heat.

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.