I have developed web application using grails web framework and am developing this for my e-commerce platform where am giving offers to users like "Flash Sale".
I have successfully created the api for this in one of my controller where am booking for the product. The logic here is If that product is completely sold and is not available i.e in other words if i have 0 products remaining then i shouldn't book the product and should tell the booking user about this, for this am returning status code as 204.
The confusion which is bothering me here is, What if many customers starts booking the product exactly at the same time altogether. Scenario lets say i have only 20 pieces of product to be sold and 21 customers started booking the product at the same time. For this I shall lock/ process the api requests one by one (queuing). Am not having idea of how to do this, please help me out.
Have you ever used the synchronized keyword in Java? It is used to form a thread queue where threads will form a line to access a particular piece of code. In order to determine whether or not a thread should wait, you pass an object instance to the synchronized block and if there is already another thread using the same block on the same instance, it will wait until all previous threads are done. This article explains the use of synchronized: https://www.geeksforgeeks.org/synchronized-in-java/.
Also, here is an example of what I mean. I am going to just use a static object instance, meaning that all threads will use the same object instance which will make them all wait their turn:
static Object threadLock = new Object();
void doSomething() {
// region Some code that all threads can execute at once
...
// endregion
// region Synchronized code
synchronized(threadLock) {
// Have your winner logic here. Threads will only go into this block in a first-come-first-served basis.
}
// endregion
}
You could also mark the entire method as synchronized for simplicity, but then all logic in the method must be done in a synchronous manner when it may not be needed. Use either approach at your own discretion.
Related
Let's say I have a command to edit a single entry of an article, called ArticleEditCommand.
User 1 issues an ArticleEditCommand based on V1 of the article.
User 2 issues an ArticleEditCommand based on V1 of the same
article.
If I can ensure that my nodes process the older ArticleEditCommand commands first, I can be sure that the command from User 2 will fail because User 1's command will have changed the version of the article to V2.
However, if I have two nodes process ArticleEditCommand messages concurrently, even though the commands will be taken of the queue in the correct order, I cannot guarantee that the nodes will actually process the first command before the second command, due to a spike in CPU or something similar. I could use a sql transaction to update an article where version = expectedVersion and make note of the number of records changed, but my rules are more complex, and can't live solely in SQL. I would like my entire logic of the command processing guaranteed to be concurrent between ArticleEditCommand messages that alter that same article.
I don't want to lock the queue while I process the command, because the point of having multiple command handlers is to handle commands concurrently for scalability. With that said, I don't mind these commands being processed consecutively, but only for a single instance/id of an article. I don't expect a high volume of ArticleEditCommand messages to be sent for a single article.
With the said, here is the question.
Is there a way to handle commands consecutively across multiple nodes for a single unique object (database record), but handle all other commands (distinct database records) concurrently?
Or, is this a problem I created myself because of a lack of understanding of CQRS and concurrency?
Is this a problem that message brokers typically have solved? Such as Windows Service Bus, MSMQ/NServiceBus, etc?
EDIT: I think I know how to handle this now. When User 2 issues the ArticleEditCommand, an exception should be throw to the user letting them know that there is a current pending operation on that article that must be completed before then can queue the ArticleEditCommand. That way, there is never two ArticleEditCommand messages in the queue that effect the same article.
First let me say, if you don't expect a high volume of ArticleEditCommand messages being sent, this sounds like premature optimization.
In other solutions, this problem is usually not solved by message brokers, but by optimistic locking enforced by the persistence implementation. I don't understand why a simple version field for optimistic locking that can be trivially handled by SQL contradicts complicated business logic/updates, maybe you could elaborate more?
It's actually quite simple and I did that. Basically, it looks like this ( pseudocode)
//message handler
ModelTools.TryUpdateEntity(
()=>{
var entity= _repo.Get(myId);
entity.Do(whateverCommand);
_repo.Save(entity);
}
10); //retry 10 times until giving up
//repository
long? _version;
public MyObject Get(Guid id)
{
//query data and version
_version=data.version;
return data.ToMyObject();
}
public void Save(MyObject data)
{
//update row in db where version=_version.Value
if (rowsUpdated==0)
{
//things have changed since we've retrieved the object
throw new NewerVersionExistsException();
}
}
ModelTools.TryUpdateEntity and NewerVersionExistsException are part of my CavemanTools generic purpose library (available on Nuget).
The idea is to try doing things normally, then if the object version (rowversion/timestamp in sql) has changed we'll retry the whole operation again after waiting a couple of miliseconds. And that's exactly what the TryUpdateEntity() method does. And you can tweak how much to wait between tries or how many times it should retry the operation.
If you need to notify the user, then forget about retrying, just catch the exception directly and then tell the user to refresh or something.
Partition based solution
Achieve node stickiness by routing the incoming command based on the object's ID (eg. articleId modulo your-number-of-nodes) to make sure the commands of User1 and User2 ends up on the same node, then process the commands consecutively. You can choose to process all commands one by one or if you want to parallelize the execution, partition the commands on something like ID, odd/even, by country or similar.
Grid based solution
Use an in-memory grid (eg. Hazelcast or Coherence) and use a distributed Executor Service (http://docs.hazelcast.org/docs/2.0/manual/html/ch09.html#DistributedExecution) or similar to coordinate the command processing across the cluster.
Regardless - before adding this kind of complexity, you should of course ask yourself if it's really a problem if User2's command would be accepted and User1 got a concurrency error back. As long as User1's changes are not lost and can be re-applied after a refresh of the article it might be perfectly fine.
The communication is based on socket and the it is keep-alive connection. User use account name to log in, I need to implement a feature when two user use same account to log in, the former one need to be kicked off.
Codes need to updated:
void session::login(accountname) // callback when server recv login request
{
boost::shared_ptr<UserData> d = database.get_user_data(accountname);
this->data = d;
this->send(login success);
}
boost::shared_ptr<UserData> Database::get_user_data(accountname)
{
// read from db and return the data
}
The most simple way is improve Database::get_user_data(accountname)
boost::shared_ptr<UserData> Database::get_user_data(accountname)
{
add a boost::unqiue_lock<> here
find session has same accountname or find user data has same accountname in cache,
if found, then kick this session offline first, then execute below codes
// read from db and return the data
}
This modification has 2 problems:
1, too bad concurrency because the scenario happen rarely. However, if I need to check account online or not, I must cache it somewhere(user data or session), that means I need to write to a container which must has exclusive lock whatever the account same or not. So the concurrency can hardly improved.
2, kick other one off by calling "other_session->offline()" in "this thread" that might concurrent with other operations executing in other thread at same time.
If I add lock in offline(), that will result in all others function belong to session also need to add that lock, obviously, not good. Or, I can push a event to other_session, and let other_session handle the event, that will make sure "offline" executing in its own thread. But the problem is that will make offline executing async, codes below "other one offline" must executed after "offline" runs complete.
I use boost::asio, but I try to describe this problem in common because I think this is a common problem in server writing. Is there a pattern to solve this? Notice that this problem gets complex when there are N same account log in at same time
If this scenario rarely happens, I wouldn't worry about it. lock and release of mutex are not long actions the user would notice (if you had to do it thousands of times a second it could be a problem).
In general trying to fix performance issues that are not there is a bad idea.
I am running a python application on the App Engine using Django. Additionally, I am using a session-management library called gae-sessions. If threadsafe is set to "no", there is no problem, but when threadsafe is set to "yes", I occasionally see a problem with sessions being lost.
The issue that I am seeing is that when treading is enabled, multiple requests are ocassionally interleaved in GAE-Sessions middleware.
Within the gae-sessions library, there is a variable called _tls, which is a threading.local() variable. When a user makes an http request to the website, a function called process_request() is first run, followed by a bunch of custom html generation for the current page, and then a function called process_response() is run. State is remembered between the process_request and process_response in the _tls "thread safe" variable. I am able to check uniqueness of the _tls variable by printing out the _tls value (eg. "<thread._local object at 0xfc2e8de0>").
What I am occasionally witnessing is that on what appears to be a single thread in the GAE-Sessions middleware (inferred to be a single thread by the fact that they have the same memory location for the thread_local object, and inferred by the fact that data from one request appears to be overwriting data from another requst), multiple http requests are being interleaved. Given User1 and User2 that make a request at the same time, I have witnessed the following execution order:
User1 -> `process_request` is executed on thread A
User2 -> `process_request` is executed on thread A
User2 -> `process_response` is executed on thread A
User1 -> `process_response` is executed on thread A
Given the above scenario, the User2 session stomps on some internal variables and causes the session of User1 to be lost.
So, my question is the following:
1) Is this interleaving of different requests in the middleware expected behaviour in App-Engine/Django/Python? (or am I totally confused, and there is something else going on here)
2) At what level is this interleaving happening (App-Engine/Django/Python)?
I am quite surprised by seeing this behaviour, and so would be interested to understand why/what is happening here.
I found the following links to be helpful in understanding what is happening:
http://blog.notdot.net/2011/10/Migrating-to-Python-2-7-part-1-Threadsafe
Is Django middleware thread safe?
http://blog.roseman.org.uk/2010/02/01/middleware-post-processing-django-gotcha/
Assuming that I am understanding everything correctly, the reason that the above happened is the following:
1) When Django is running, it runs most of the base functionality in a parent (common) thread that includes the Django Middleware.
2) Individual requests are run in child threads which can interact with the parent thread.
The result of the above is that requests (child threads) can indeed be interleaved within the Middleware - and this is by design (only running a single copy of Django and the Middleware would save memory, be more efficient, etc.). [see the first article that I linked to in this answer for a quick description of how threading and child/parent processes interact]
With respect to GAE-Sessions - the thread that we were examining was the same for different requests, given that it was the parent thread (common for all children/requests), as opposed to the child threads that we were looking at each time that the middleware was entered.
GAE-Sessions was storing state data in the middleware, which could be over-written by different requests, given the possible interleaving of the child threads within the parent (Django + Middlware) thread. The fix that I applied to GAE-Sessions was to store all state data on the request object, as opposed to within the middlware.
Fixes: previously a writable reference to response handler functions was stored in the DjangoSessionMiddlware object as self.response_handlers - which I have moved to the request object as request.response_handlers. I also removed the _tls variable, and moved data that it contained into the request object.
I'm somehow stuck with implementing a reporting functionailty in my Log-Parser Application.
This is what I did so far:
I'm writing an Application that reads Logfiles and searches the strings for multiple regular Expressions that can be defined in a user-configuration file. For every so called "StringPipe"-defintion that is parsed from the configuration the Main-Process spawns a worker thread that will search for a single regex. The more definitons the user creates, the more worker threads are spawned. The Main Function reads a bunch of Logstrings and then sends the workers to process the strings and so on.
Now I want every single worker thread that is spawned to report information about the number of matches it has found, how long it took, what it did with those strings and so on. These Information are used to export as csv, write to DB and so on.
Now I'm stuck at the point where I created a Class "Report". This Class provides member functions that are called by the worker threads to make the Report-Class gather the Infos needed for generating the report.
For that my workers (which are boost::threads / functors) have to create a Report-Object which they can call those reporting functions for.
The problem is in my Design, because when a worker-thread finishes his job, it is destroyed and for the next bunch of strings that needs to be processed a new instance of this worker functor is spawned and so it needs to create a new Report Object.
This is a problem from my understanding, because I need some kind of container where every worker can store it's reported infos into and finally a global report that contains such infos as how long the whole processing has taken, which worker was slowest and so on.
I just need to collect all these infos together, but how can I do this? Everytime a worker stops, reports, and then starts again, it will destroy the Report-Object and it's members, so all the infos from previous work is gone.
How can I solve this problem or how is such a thing handled in general?
First, I would not spawn a new thread do the RE searching and such. Rather, you almost certainly want a pool of threads to handle the jobs as they arise.
As far as retrieving and processing the results go, it sounds like what you want are Futures. The basic idea is that you create an object to hold the result of the computation, and a Future to keep track of when the computation is complete. You can either wait for the results to be complete, or register a call-back to be called when a future is complete.
Instead of having the worker thread create the report object, why don't you have the main thread create the empty report and pass a pointer to the worker thread when created. Then the worker thread can report back when it has completed the report, then the main thread can add the data from that report to some main report.
So, the worker thread will never have ownership of the actual report, it fill just populate its data fields and report back to the main thread.
A monitor is supposed to solve problems with semaphores in concurrent environments.
I'm looking for a good analogy using a monitor verses semaphore.
Please use information for the analogy:
4 tasks (TaskA, TaskB, TaskC, TaskD)
1 variable varX
Each Task wants to manipulate varX based on some event.
Lets say a bunch of patients wants to go see a doctor.
A semaphore implementation would be they all stand outside the door to the office, as soon as one patient comes out, they all try to squeeze through, one person manages to get in, the rest have to wait again.
A monitor implementation would be, all incoming patients are sent to a waiting room instead, some semblance of order will be determined and when one patient is done, another will be sent to the doctor.
They are basically the same thing, monitors are just more structured than semaphores.
You can also see a monitor as a public toilet. Once someone went in an closed the toilet door, the person inside wants no one else to be in that space (i.e. the monitor). All other people (threads) have to queue up in front of the toilet and wait (wait()). Only after the person inside has finished, it comes out and the next person can go in.
Some of the people waiting might have constipation problems. For obvious reasons, they don't want to go in or return unless they're ready to make proper use of the toilet. This is where they want to wait (wait()) until their stomach signals them (signal()) that they are ready to go to the toilet. Before this happens, they let everyone else pass.
Source: www.mijnadres.net/published/Monitor%20Object%20Pattern.pdf
Its important to separate out the resource contention from the event notification. A Monitor and Semaphore are used to limit access to a shared resource. A monitor is basically a semaphore whose count is 1. If each of your tasks wants to get access to the single varX, then you need to protect it using your monitor (or sempahore of 1):
Monitor.Enter
// do something with varX
Monitor.Exit
or
Semaphore.Acquire
// do something with varX
Semaphore.Release
With a Semaphore you can obviously set the number of allowed concurrenct participants to the shared resource.
Nick.