跨集群共享 Java 同步块,还是使用全局锁?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1228833/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sharing a Java synchronized block across a cluster, or using a global lock?
提问by pkaeding
I have some code that I want to only allow access to by one thread. I know how to accomplish this using either synchronizedblocks or methods, but will this work in a clustered environment?
我有一些代码,我只想允许一个线程访问。我知道如何使用synchronized块或方法来实现这一点,但这在集群环境中是否可行?
The target environment is WebSphere 6.0, with 2 nodes in the cluster.
目标环境是 WebSphere 6.0,集群中有 2 个节点。
I have a feeling that synchronizedwon't work, since each instance of the application on each node will have its own JVM, right?
我有一种感觉synchronized行不通,因为每个节点上的每个应用程序实例都有自己的 JVM,对吗?
What I am trying to do here is perform some updates to database records when the system is booted. It will look for any database records that are older that the version of the code, and perform specific tasks to update them. I only want one node to perform these upgrades, since I want to be sure that each work item is only upgraded once, and performance of these upgrades is not a big concern, since it only happens at application startup, and it only really does anything when the code has been changed since the last time it started up.
我在这里尝试做的是在系统启动时对数据库记录执行一些更新。它将查找任何比代码版本旧的数据库记录,并执行特定任务来更新它们。我只想要一个节点来执行这些升级,因为我想确保每个工作项只升级一次,并且这些升级的性能不是一个大问题,因为它只发生在应用程序启动时,它只真正做任何事情自上次启动以来代码已更改时。
The database is DB2v9, and I am accessing it directly via JNDI (no ORM layer).
数据库是 DB2v9,我直接通过 JNDI(无 ORM 层)访问它。
It has been suggested that a global lock might be the way to go here, but I'm not sure how to do that.
有人建议全局锁定可能是这里的方法,但我不确定如何做到这一点。
Does anyone have any pointers in this arena?
有没有人在这个领域有任何指示?
Thanks!
谢谢!
采纳答案by jsight
You are correct that synchronization across processes will not work using the Java synchronization constructs. Fortunately, your problem really isn't one of code synchronization, but rather of synchronizing interactions with the database.
您是正确的,跨进程同步将无法使用 Java 同步构造进行。幸运的是,您的问题确实不是代码同步问题,而是与数据库的交互同步问题。
The right way to deal with this problem is with database level locks. Presumably you have some table that contains a db schema version, so you should make sure to lock that table for the duration of the startup/upgrade process.
处理这个问题的正确方法是使用数据库级锁。大概你有一些包含数据库模式版本的表,所以你应该确保在启动/升级过程中锁定该表。
The precise sql/db calls involved would probably be more clear if you specified your database type (DB2?) and access method (raw sql, jpa, etc).
如果您指定了数据库类型(DB2?)和访问方法(原始 sql、jpa 等),则所涉及的精确 sql/db 调用可能会更加清楚。
Update (8/4/2009 2:39PM): I suggest the LOCK TABLEstatement on some table holding the version # of the schema. This will serialize access to that table preventing two instances from running through the upgrade code at once.
更新(2009 年 8 月 4 日下午 2:39):我建议在保存模式版本号的某个表上使用LOCK TABLE语句。这将序列化对该表的访问,防止两个实例同时运行升级代码。
回答by Kaitsu
Yes, you are correct in that synchronizedblocks won't work across a cluster. The reason is, as you stated, that each node has its own JVM.
是的,您是正确的,因为同步块不能跨集群工作。正如您所说,原因是每个节点都有自己的 JVM。
There are ways, however, to get synchronized blocks to work in a cluster as they would work in a single-node environment. The easiest way is to use a product like Terracotta, which will handle the coordination of threads between different JVMs so that normal concurrency controls can be used across the cluster. There are many articles explaining how this works, like Introduction to OpenTerracotta.
然而,有一些方法可以让同步块在集群中工作,就像它们在单节点环境中工作一样。最简单的方法是使用像Terracotta这样的产品,它将处理不同 JVM 之间线程的协调,以便可以跨集群使用正常的并发控制。有很多文章解释了这是如何工作的,比如OpenTerracotta 简介。
There are other solutions, of course. It mostly depends on what you really want to achieve here. I wouldn't use database locks for synchronizing if you need to scale, as DB doesn't. But I really urge you to find a ready-made solution, because messing around with cluster synchronization is messy business :)
当然,还有其他解决方案。这主要取决于您在这里真正想要实现的目标。如果需要扩展,我不会使用数据库锁进行同步,因为 DB 不需要。但我真的敦促你找到一个现成的解决方案,因为搞乱集群同步是一件很麻烦的事情:)
回答by vishr
You can use a in-memory-data-grid like http://www.hazelcast.com/for this too. This is a distributed data structure that supports locking.
您也可以为此使用内存数据网格,例如http://www.hazelcast.com/。这是一种支持锁定的分布式数据结构。
回答by ZZ Coder
Since you are talking about 2 machines, you don't even have shared memory so there is nothing to synchronize.
由于您在谈论 2 台机器,因此您甚至没有共享内存,因此无需同步。
We do something similar with our database. This is achieved by adding record versioning in the table. This is what you should do,
我们对我们的数据库做了类似的事情。这是通过在表中添加记录版本控制来实现的。这是你应该做的
- Add a column for record/row version.
- Go through the logic to check if record needs to be updated.
- When you update record, make sure the record version in DB is the same as what you have.
- Bump up version every time you write to the database.
- 为记录/行版本添加一列。
- 通过逻辑检查记录是否需要更新。
- 更新记录时,请确保数据库中的记录版本与您拥有的相同。
- 每次写入数据库时都会提高版本。
You should only have one server updating the database if you follow these rules.
如果您遵循这些规则,您应该只有一台服务器来更新数据库。
回答by Robin
Couldn't you simply lock the table (or entire db) for updates, so when the first node in obtained the lock all other nodes would not be able to write. Subsequent nodes would wait, and when the lock is released the code would be updated so no record update would be required.
您不能简单地锁定表(或整个数据库)以进行更新,因此当第一个节点获得锁定时,所有其他节点将无法写入。后续节点将等待,当锁被释放时,代码将被更新,因此不需要更新记录。

