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