Raj
Raj

Reputation: 1148

Java locking on muliple servers

I have few seats that would be reserved by the user. At a time, only one user can participate in the reservation process so that same seat is not reserved by multiple users. In my Java code I have used "synchronized" keyword to get it done. This works.

However, now my code is deployed on two servers, say S1 and S2. Hypothetically, lets say there is a last seat available. Two users, say U1 and U2, want to reserve that last seat. It might happen that the load balancer will send user U1 to server S1 and user U2 to server S2. Now the "local" synchronized would still work the same way but it will not be able to block the other user while making reservation. This would make the last seat to be reserved by both the users which is problem.

So the question is how can I make sure that multiple users reserve the seat without any conflict in multiple server environment?

Upvotes: 3

Views: 2282

Answers (2)

MarianP
MarianP

Reputation: 2759

It's difficult to be done at language level. Some distributed caches might help, Terracotta for example does deal with synchronized keyword in clustered environment, but I haven't tried it and there's certainly a performance toll. I would be very careful with making instances wait for some non-trivial time as seems to be your case.

Otherwise distributed JNDI, distributed singleton or similar stuff done to make server instances communicate and check that during the process might help.

But this problem is in practice usually avoided by doing optimistic locking. You might simply assume that this happens only in some unusual/unlikely moments and do things as in a one instance case. And figure out a way on what to do when it does not. This becomes more of business logic scenario and the best way to do it is simply finding a way to make the user least likely to be dissatisfied.

Usually there is a consistency guaranteed at the persistence/database level, so you might write it down there. I would certainly not use synchronized keyword to block an instance that might be holding for minutes or more as that asks for a memory leak or any other resource exhaustion.

I personally like using L2 cache when working with JPA/Hibernate which deals with this. OpenJPA has a performance friendly way of doing the L2 stuff when it only notifies other instances that an entity has been changed and they should revoke it from their L1 cache. This might be a much better approach in your case than 'synchronizing' using a synchronized Java language keyword.

It is a good attitude on your side to think about how to deal with it as it is neglected in many applications in my experience. It too often becomes a low probability scenario which is hard to comprehend for business oriented managers on why it should be invested in. But it has a capability of a severe backlash in case things go wrong in production.

Upvotes: 3

Jasper Blues
Jasper Blues

Reputation: 28786

There are basically four ways distributed systems can communicate:

  1. Shared Database.
  2. Remote procedure calls
  3. Messaging.
  4. Shared file-system.

Consider the shared database approach. . If you don't need massive scaling, the easiest will be to use a relational database since almost all of them provide some degree of ACID (Atomocity, Consistency, Isolation & Durability). . .

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

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

Another option would be to use a distributed cache.

Upvotes: 2

Related Questions