Synchronizing a Method Across JVM's

bluedevil2k picture bluedevil2k · Oct 15, 2013 · Viewed 8.3k times · Source

How does one go about synchronizing a method across JVM's?

My example is a web application that restricts a user name from being logged in more than once (in other words, the first user can log on, but if another user signs on with the same user name, he gets rejected).

The web application is deployed across multiple servers, so there are multiple JVM's, and users can be attempting to sign on using different servers, depending on the load balancer.

Here's how the method looks

public synchronized static SessionData logonSync(String userName, String password) throws Exception 
{
    int count = DB.count("sessions", "WHERE user_name=?", userName);
    if (count > 0)
    {
       throw new Exception("logon.error.loginAlreadyUsed");
    }                   

    return logon(userName, password);
}

It works correctly on 1 app server because of the synchronized method, but across multiple JVM's? Two users could be attempting to log in on different web apps at the same time. How would I prevent this?

* EDIT * The app uses Memcached too, if your solution wants to take advantage of some transactional cache methods.

Answer

Barak picture Barak · Oct 15, 2013

You asked about synchronizing methods across JVMs. That requires a library that handles distributed processes. There are many options, here are just a few:

  1. Terracotta - Supports configuring certain fields as 'shared' across JVMs, so you can use standard JVM locking, like the synchronized keyword, and it will work on multiple JVMs.
  2. JGroups - Jgroups is a toolkit for distributed applications. Locking is one of the features it offers. Here is an example from their documentation

Setting up distributed locking is never easy, regardless of what library you use. If you need it, fine, but for your example this seems like overkill. Other options:

  • Add a uniqueness constraint in the Database and let is enforce uniqueness. This can have a performance impact on the database, so it really depends how much traffic you expect to get.
  • Have the load balancer use the username (or a hash of it) as the key that it uses to assign requests to a web server. This will guarantee that requests from the same username will arrive at the same web server every time - no need for a distributed lock, just use a regular one.