Blocking Java on multiple servers

I have few places to be reserved by the user. At that time, only one user can participate in the booking process, so the same seat is not reserved by multiple users. In my Java code, I used the "synchronized" keyword to do this. It works.

However, my code is now deploying to two servers, for example S1 and S2. Hypothetically, let's say there is the last place. Two users, for example U1 and U2, want to reserve this last seat. It may happen that the load balancer sends user U1 to server S1 and user U2 to server S2. Now "local" sync will work the same, but it will not be able to block another user on backup. This would make the latter place reserved for both users who are the problem.

So the question is, how can I make sure multiple users have reserved space without conflicts across multiple server environments?

+3


source to share


2 answers


There are four ways to distribute distributed systems:

  • Shared database.
  • Remote Procedure Calls
  • Messages.
  • Shared file system.

Consider a generic database approach.If you don't require massive scaling, the easiest is to use a relational database as almost all of them provide some degree of ACID (Atomocity, Consistency, Isolation and Durability).



You can set up the transaction and rollback / handle in case of a collision - this is called an optimistic locking strategy.

If you are using Spring + JPA / Hibernate all the hard work has been done for you and you just need to add the @Transactional annotation to your update method. The great book on Spring is Spring in Action.

Another option is to use a distributed cache.

+2


source


This is difficult to do at the language level. Some common caches might help, Terracotta for example deals with a synchronized keyword in a clustered environment, but I haven't tried it, and of course the performance. I would be very careful with the instances waiting for some non-trivial time, as you think.

Otherwise distributed JNDI, distributed singleton, or similar stuff made to communicate between server instances and check what during the process might help.

But this problem is usually avoided in practice by making an optimistic locking. You can just assume that it only happens in some unusual / unlikely moments and does the same as it does for one instance. And figure out a way of what to do when it isn't. It becomes more of a script of business logic, and the best way to do it is to simply find a way to make the user the least likely to complain.



Consistency is usually guaranteed at the persistence / database level, so you can write it there. I would certainly not use the synchronized keyword to lock an instance that can be kept for a few minutes or more, as this requires a memory leak or any other resource.

I like to use L2 cache when working with JPA / Hibernate who deals with this. OpenJPA has a performance friendly way of creating L2 stuff where it only notifies other instances that the object has changed and they need to discard it from their L1 cache. This might be much better in your case than "sync" using the Java sync keyword.

It's a good attitude on your side to think about how to deal with this, since in many cases my experience is ignored in many applications. This too often becomes a low probability scenario that is difficult for business-oriented managers to understand about why it should be invested. But it does have the ability to be seriously treated in case something goes wrong in production.

+2


source







All Articles