[英]Sharing a Java synchronized block across a cluster, or using a global lock?
我有一些代碼,我只想允許一個線程訪問。 我知道如何使用synchronized
塊或方法完成此操作,但這是否適用於集群環境?
目標環境是WebSphere 6.0,在集群中有2個節點。
我覺得synchronized
不起作用,因為每個節點上的每個應用程序實例都有自己的JVM,對嗎?
我在這里嘗試做的是在系統啟動時對數據庫記錄執行一些更新。 它將查找比代碼版本更舊的任何數據庫記錄,並執行特定任務以更新它們。 我只希望一個節點執行這些升級,因為我想確保每個工作項只升級一次,並且這些升級的性能不是一個大問題,因為它只發生在應用程序啟動時,它只是真正做任何事情自上次啟動以來代碼更改的時間。
數據庫是DB2v9,我通過JNDI直接訪問它(沒有ORM層)。
有人建議全球鎖定可能是這里的方式,但我不知道如何做到這一點。
有沒有人在這個舞台上有任何指針?
謝謝!
是的,你是正確的,因為同步塊不能在群集中工作。 正如您所說,原因是每個節點都有自己的JVM。
但是,有一些方法可以使同步塊在集群中工作,因為它們可以在單節點環境中工作。 最簡單的方法是使用像Terracotta這樣的產品,它將處理不同JVM之間的線程協調,以便可以在整個集群中使用正常的並發控制。 有很多文章解釋了它是如何工作的,比如OpenTerracotta簡介 。
當然還有其他解決方案。 這主要取決於你真正希望在這里實現的目標。 如果需要擴展,我不會使用數據庫鎖進行同步,因為DB不需要。 但我真的懇請你找到一個現成的解決方案,因為弄亂群集同步是一件混亂的事情:)
您是正確的,跨進程的同步將無法使用Java同步構造。 幸運的是,您的問題實際上不是代碼同步,而是與數據庫同步交互。
處理此問題的正確方法是使用數據庫級別鎖定。 據推測,您有一些包含db模式版本的表,因此您應確保在啟動/升級過程中鎖定該表。
如果您指定了數據庫類型(DB2?)和訪問方法(原始sql,jpa等),那么所涉及的精確sql / db調用可能會更清楚。
更新(2009年8月4日下午2:39) :我建議在一些持有模式版本號的表上使用LOCK TABLE語句。 這將序列化對該表的訪問,防止兩個實例同時運行升級代碼。
您也可以使用像http://www.hazelcast.com/這樣的內存數據網格。 這是一種支持鎖定的分布式數據結構。
既然你在談論2台機器,你甚至沒有共享內存,所以沒有什么可以同步的。
我們用我們的數據庫做類似的事情。 這是通過在表中添加記錄版本來實現的。 這是你應該做的,
如果遵循這些規則,您應該只有一台服務器更新數據庫。
你不能簡單地鎖定表(或整個數據庫)進行更新,所以當獲得鎖的第一個節點時,所有其他節點都無法寫入。 后續節點將等待,並且當釋放鎖時,代碼將被更新,因此不需要記錄更新。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.