跨JVM同步方法

时间:2013-10-15 20:02:06

标签: java concurrency jvm synchronized

如何跨JVM同步方法?

我的示例是一个Web应用程序,它限制用户名不能多次登录(换句话说,第一个用户可以登录,但如果另一个用户使用相同的用户名登录,则会被拒绝)。

Web应用程序部署在多个服务器上,因此有多个JVM,用户可以尝试使用不同的服务器登录,具体取决于负载均衡器。

以下是该方法的外观

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);
}

由于同步方法,它可以在1个应用服务器上正常工作,但是跨多个JVM?两个用户可能正在尝试同时登录不同的Web应用程序。我该怎样阻止这个?

*编辑* 如果您的解决方案想要利用某些事务缓存方法,该应用程序也会使用Memcached。

1 个答案:

答案 0 :(得分:12)

您询问了跨JVM同步方法的问题。这需要一个处理分布式进程的库。有很多选择,这里只是几个:

  1. Terracotta - 支持在JVM之间将某些字段配置为“共享”,因此您可以使用标准JVM锁定,例如synchronized关键字,它可以在多个JVM上运行。
  2. JGroups - Jgroups是分布式应用程序的工具包。锁定是它提供的功能之一。以下是documentation
  3. 的示例

    无论您使用哪个库,设置分布式锁定都不容易。如果你需要它,很好,但对于你的例子,这似乎有点矫枉过正。其他选择:

    • 在数据库中添加唯一性约束,并强制执行唯一性。这可能会对数据库产生性能影响,因此它实际上取决于您希望获得多少流量。
    • 让负载均衡器使用用户名(或其哈希值)作为用于将请求分配给Web服务器的密钥。这将保证来自同一用户名的请求每次都会到达同一个Web服务器 - 不需要分布式锁,只需使用常规用户。