2009-08-04 104 views
13

我有一些代码,我想只允许一个线程访问。我知道如何使用​​块或方法来完成此操作,但是这会在群集环境中工作吗?跨群集共享Java同步块,或使用全局锁?

目标环境是WebSphere 6.0,集群中有2个节点。

我有一种感觉​​将无法​​正常工作,因为每个节点上的应用程序的每个实例都将有它自己的JVM,对吧?

我在这里要做的是在系统启动时对数据库记录执行一些更新。它将查找比代码版本更旧的任何数据库记录,并执行特定任务来更新它们。我只希望一个节点执行这些升级,因为我想确保每个工作项目只升级一次,并且这些升级的性能并不是一个大问题,因为它只发生在应用程序启动时,并且它只是真的做任何事情代码自上次启动以来已更改。

数据库是DB2v9,我直接通过JNDI(无ORM层)访问它。

有人建议,全局锁定可能是这里的方法,但我不知道该怎么做。

有没有人在这个舞台上有任何指针?

谢谢!

+0

我认为你将不得不在你的问题上更具体。你想要协调什么行动? – 2009-08-04 17:28:24

+0

@Software Monkey-当然,对不起。我刚添加了一段解释我的意图。请让我知道如果它仍然不清楚。 – pkaeding 2009-08-04 17:38:15

+0

那么你真正想要的是一个全局锁。我不知道websphere,所以我不能帮助在这里,但寻求帮助创建一个锁可能会更多的响铃与那些谁:) :) – bdonlan 2009-08-04 17:39:36

回答

5

您是正确的,跨进程的同步将无法使用Java同步结构工作。幸运的是,你的问题实际上不是代码同步,而是同步与数据库的交互。

解决此问题的正确方法是使用数据库级锁。假设你有一些包含数据库模式版本的表,所以你应该确保在启动/升级过程中锁定该表。

如果您指定了数据库类型(DB2?)和访问方法(raw sql,jpa等),则涉及的精确sql/db调用可能会更清晰。

更新(2009年8月4日下午2点39分):我建议LOCK TABLE声明某些表格上持有该模式的版本号。这将序列化对该表的访问,以防止两个实例一次运行通过升级代码。

0

难道你不能简单地锁定表(或整个数据库)的更新,所以当第一个节点获得锁时,所有其他节点将无法写入。随后的节点将等待,并且当锁被释放时,代码将被更新,因此不需要记录更新。

7

是的,您正确同步块将不会跨群集工作。正如你所说,原因是每个节点都有自己的JVM。

但是,有些方法可以使同步块在集群中工作,因为它们可以在单节点环境中工作。最简单的方法是使用像Terracotta这样的产品,它将处理不同JVM之间线程的协调,以便在整个集群中使用正常的并发控制。有很多文章解释如何工作,如Introduction to OpenTerracotta

当然还有其他解决方案。它主要取决于你真正想在这里实现什么。如果您需要扩展,我不会使用数据库锁进行同步,因为数据库不会。但我真的希望你找到一个现成的解决方案,因为乱搞集群同步是凌乱的业务:)

3

因为你在谈论2台机器,你甚至没有共享内存,所以没有什么可以同步。

我们对数据库做了类似的事情。这是通过在表中添加记录版本来实现的。这是你应该做的,

  1. 添加一个记录/行版本的列。
  2. 通过逻辑来检查记录是否需要更新。
  3. 更新记录时,请确保数据库中的记录版本与您拥有的相同。
  4. 每次写入数据库时​​都碰到版本。

如果遵循这些规则,您应该只有一台服务器更新数据库。