在分布式環境中,處理并發問題就沒辦法通過操作系統和JVM的工具來解決,那么在分布式環境中,可以采取一下策略和方式來處理:
避免并發
在分布式環境中,如果存在并發問題,那么很難通過技術去解決,或者解決的代價很大,所以我們首先要想想是不是可以通過某些策略和業務設計來避免并發。比如通過合理的時間調度,避開共享資源的存取沖突。另外,在并行任務設計上可以通過適當的策略,保證任務與任務之間不存在共享資源,比如在以前博文中提到的例子,我們需要用多線程或分布式集群來計算一堆客戶的相關統計值,由于客戶的統計值是共享數據,因此會有并發潛在可能。但從業務上我們可以分析出客戶與客戶之間 數據是不共享的,因此可以設計一個規則來保證一個客戶的計算工作和數據訪問只會被一個線程或一臺工作機完成,而不是把一個客戶的計算工作分配給多個線程去 完成。這種規則很容易設計,例如可以采用hash算法。
時間戳
分布式環境中并發是沒法保證時序的,無論是通過遠程接口的同步調用或異步消息,因此很容易造成某些對時序性有要求的業務在高并發時產生錯誤。比如系統A需要把某個值的變更同步到系統B,由于通知的時序問題會導致一個過期的值覆蓋了有效值。對于這個問題,常用的辦法就是采用時間戳的方式,每次系統A發送變更給系統B的時候需要帶上一個能標示時序的時間戳,系統B接到通知后會拿時間戳與存在的時間戳比較,只有當通知的時間戳大于存在的時間戳,才做更新。這種方式比較簡單,但關鍵在于調用方一般要保證時間戳的時序有效性。
串行化
有的時候可以通過串行化可能產生并發問題操作,犧牲性能和擴展性,來滿足對數據一致性的要求。比如分布式消息系統就沒法保證消息的有序性,但可以通過變分布式消息系統為單一系統就可以保證消息的有序性了。另外,當接收方沒法處理調用有序性,可以通過一個隊列先把調用信息緩存起來,然后再串行地處理這些調用。
數據庫
分布式環境中的共享資源不能通過Java里同步方法或加鎖來保證線程安全,但數據庫是分布式各服務器的共享點,可以通過數據庫的高可靠一致性機制來滿足需求。比如,可以通過唯一性索引來解決并發過程中重復數據的生產或重復任務的執行;另外有些更新計算操作也盡量通過sql來完成,因為在程序段計算好后再去更新就有可能發生臟復寫問題,但通過一條sql來完成計算和更新就可以通過數據庫的鎖機制來保證update操作的一致性。
行鎖
有的事務比較復雜,無法通過一條sql解決問題,并且有存在并發問題,這時就需要通過行鎖來解決,一般行鎖可以通過以下方式來實現:
- 對于Oracle數據庫,可以采用select ... for update方式。這種方式會有潛在的危險,就是如果沒有commit就會造成這行數據被鎖住,其他有涉及到這行數據的任務都會被掛起,應該謹慎使用
- 在表里添加一個標示鎖的字段,每次操作前,先通過update這個鎖字段來完成類似競爭鎖的操作,操作完成后在update鎖字段復位,標示已歸還鎖。這種方式比較安全,不好的地方在于這些update鎖字段的操作就是額外的性能消耗
統一觸發途徑
當一個數據可能會被多個觸發點或多個業務涉及到,就有并發問題產生的隱患,因此可以通過前期架構和業務設計,盡量統一觸發途徑,觸發途徑少了一是減少并發的可能,也有利于對于并發問題的分析和判斷。
posted on 2011-10-13 16:05
kxbin 閱讀(318)
評論(0) 編輯 收藏 所屬分類:
java基礎