2009-08-04 105 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. 每次寫入數據庫時​​都碰到版本。

如果遵循這些規則,您應該只有一臺服務器更新數據庫。