在分散式環境中,處理併發問題就沒辦法通過作業系統和JVM的工具來解決,那麼在分散式環境中,可以採取一下策略和方式來處理:
- 避免併發
- 時間戳
- 序列化
- 資料庫
- 行鎖
- 統一觸發途徑
避免併發
在分散式環境中,如果存在併發問題,那麼很難通過技術去解決,或者解決的代價很大,所以我們首先要想想是不是可以通過某些策略和業務設計來避免並 發。比如通過合理的時間排程,避開共享資源的存取衝突。另外,在並行任務設計上可以通過適當的策略,保證任務與任務之間不存在共享資源,比如在以前博文中 提到的例子,我們需要用多執行緒或分散式叢集來計算一堆客戶的相關統計值,由於客戶的統計值是共享資料,因此會有併發潛在可能。但從業務上我們可以分析出客 戶與客戶之間 資料是不共享的,因此可以設計一個規則來保證一個客戶的計算工作和資料訪問只會被一個執行緒或一臺工作機完成,而不是把一個客戶的計算工作分配給多個執行緒去 完成。這種規則很容易設計,例如可以採用hash演算法。
時間戳
分散式環境中併發是沒法保證時序的,無論是通過遠端介面的同步呼叫或非同步訊息,因此很容易造成某些對時序性有要求的業務在高併發時產生錯誤。比如系 統A需要把某個值的變更同步到系統B,由於通知的時序問題會導致一個過期的值覆蓋了有效值。對於這個問題,常用的辦法就是採用時間戳的方式,每次系統A發 送變更給系統B的時候需要帶上一個能標示時序的時間戳,系統B接到通知後會拿時間戳與存在的時間戳比較,只有當通知的時間戳大於存在的時間戳,才做更新。 這種方式比較簡單,但關鍵在於呼叫方一般要保證時間戳的時序有效性。
序列化
有的時候可以通過序列化可能產生併發問題操作,犧牲效能和擴充套件性,來滿足對資料一致性的要求。比如分散式訊息系統就沒法保證訊息的有序性,但可以通 過變分散式訊息系統為單一系統就可以保證訊息的有序性了。另外,當接收方沒法處理呼叫有序性,可以通過一個佇列先把呼叫資訊快取起來,然後再序列地處理這 些呼叫。
資料庫
分散式環境中的共享資源不能通過Java裡同步方法或加鎖來保證執行緒安全,但資料庫是分散式各伺服器的共享點,可以通過資料庫的高可靠一致性機制來 滿足需求。比如,可以通過唯一性索引來解決併發過程中重複資料的生產或重複任務的執行;另外有些更新計算操作也儘量通過sql來完成,因為在程式段計算好 後再去更新就有可能發生髒複寫問題,但通過一條sql來完成計算和更新就可以通過資料庫的鎖機制來保證update操作的一致性。
行鎖
有的事務比較複雜,無法通過一條sql解決問題,並且有存在併發問題,這時就需要通過行鎖來解決,一般行鎖可以通過以下方式來實現:
- 對於Oracle資料庫,可以採用select … for update方式。這種方式會有潛在的危險,就是如果沒有commit就會造成這行資料被鎖住,其他有涉及到這行資料的任務都會被掛起,應該謹慎使用
- 在表裡新增一個標示鎖的欄位,每次操作前,先通過update這個鎖欄位來完成類似競爭鎖的操作,操作完成後在update鎖欄位復位,標示已歸還鎖。這種方式比較安全,不好的地方在於這些update鎖欄位的操作就是額外的效能消耗
統一觸發途徑
當一個資料可能會被多個觸發點或多個業務涉及到,就有併發問題產生的隱患,因此可以通過前期架構和業務設計,儘量統一觸發途徑,觸發途徑少了一是減少併發的可能,也有利於對於併發問題的分析和判斷。
轉至 http://blog.csdn.net/cutesource/article/details/5791350