我有一些代码,我想只允许一个线程访问。我知道如何使用synchronized块或方法来实现这一点,但这在集群环境中可以工作吗?
目标环境为WebSphere 6.0,集群中有2个节点。
我有一种感觉,synchronized不会工作,因为每个节点上的每个应用程序实例都有自己的have虚拟机,对吧?
我在这里尝试做的是在系统启动时对数据库记录执行一些更新。它将查找任何比代码版本旧的数据库记录,并执行特定任务来更新它们。我只希望一个节点执行这些升级,因为我希望确保每个工作项只升级一次,并且这些升级的性能并不是一个大问题,因为它只在应用程序启动时发生,并且只有在代码自上次启动以来发生更改时才会真正执行任何操作。
数据库是DB2v9,我直接通过JNDI访问它(没有ORM层)。
有人建议使用全局锁,但我不确定如何做到这一点。
有谁在这个竞技场上有什么建议?
谢谢!
发布于 2009-08-04 17:42:28
您说得对,使用Java同步构造跨进程的同步将不起作用。幸运的是,您的问题实际上不是代码同步问题,而是与数据库的交互同步问题。
解决这个问题的正确方法是使用数据库级锁。假设您有一些包含db模式版本的表,因此您应该确保在启动/升级过程中锁定该表。
如果您指定了数据库类型(DB2?),那么所涉及的精确sql/db调用可能会更清楚。和访问方法(原始sql、jpa等)。
更新(8/4/20092:39 on ):我建议在一些包含模式版本号的表上使用LOCK TABLE语句。这将序列化对该表的访问,防止两个实例同时运行升级代码。
发布于 2009-08-04 17:44:14
是的,你是正确的,同步的数据块不会在集群中工作。正如您所说的,原因是每个节点都有自己的JVM。
然而,有一些方法可以让同步块在集群中工作,就像它们在单节点环境中工作一样。最简单的方法是使用像Terracotta这样的产品,它将处理不同JVM之间的线程协调,以便可以跨集群使用正常的并发控制。有许多文章解释了这是如何工作的,比如Introduction to OpenTerracotta。
当然,还有其他解决方案。这在很大程度上取决于你真正想要在这里实现什么。如果您需要扩展,我不会使用数据库锁进行同步,因为DB不需要。但我强烈建议您找到一个现成的解决方案,因为摆弄集群同步是一件很麻烦的事情:)
发布于 2012-11-07 03:09:08
您也可以使用像http://www.hazelcast.com/这样的内存数据网格来实现这一点。这是一个支持锁定的分布式数据结构。
https://stackoverflow.com/questions/1228833
复制相似问题