Synchronizing a Method Across JVM's
Asked Answered
F

1

16

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.

Feeney answered 15/10, 2013 at 20:2 Comment(8)
2 phase commit is what you need to look into.Statant
It will be better to use a flag in a database field instead of trying to solve the problem at application level.Natica
so may need a single-threaded application which listens on a specific port and each app call this port instead of calling a method, so you would take care about the whole requests.Newsdealer
+1 to the database. Make sure it's transactional (i.e., not MyISAM).Teahan
a database, really, I mean that is so 1990's. A database is the absolutely slowest and worst way to implementing a distributed lock! What a terrible suggestion and lazy uninspired solution. What you want is a distributed lock manager. too bad you can't down vote comments!Ingold
@JarrodRoberson Just because a technology is old doesn't mean it's terrible.Ockham
You mis-interpret my reason of mentioning time, using a DB for distributed lock management is naive, lazy and a complete anti-pattern, the time reference is to how long it has been a bad idea!Ingold
possible duplicate of Distributed Lock ServiceTalkative
P
18

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 it 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.
Potage answered 15/10, 2013 at 21:16 Comment(1)
Apache zookeeper is also worth having a look.Uthrop

© 2022 - 2024 — McMap. All rights reserved.