存檔

‘架構’ 分類的存檔

防火墻斷開數據庫或者mq的連接造成的長時間重連等待

2016年6月8日 1 條評論

鸿运彩票app www.chqvd.icu 在測試環境經?;嵊齙椒袷ハ煊?,需要假死15分鐘左右才能繼續處理業務,每天早上來都需要重啟服務才行,直覺感覺是防火墻有問題,不同于生產網絡,測試網絡之間的防火墻每隔固定時間最長24小時就會斷開無數據流量的連接,但是應用端以為連接還是好的,需要探查較長的時間來確認連接是否可用。同時也發現有人在遇到這方面的解釋,比較詳細,post一下供參考。
最近生產上發現一個問題,剛開始,應用連接數據庫正常,如果長時間沒有業務估計半小時以上,再發起業務時,發現應用重連不上數據庫,一直掛在重連那里,如果重啟應用又能很快連上數據庫(數據庫是Oracle)。后來經數據庫專家的同學看了后,發現我們的生產是RAC的,而客戶端配置了TAF,導致在發生會話切換的時候,可能原來的連接沒有釋放好,影響了重連。把Oracle客戶端的TAF關掉,重連的問題解決了。但又出現了一個很奇怪的現象,就是今天要說的重點問題,如果長時間沒業務的時候還是斷,而且斷了后執行SQL要15分鐘左右應用才能返回,這將導致應用在15分鐘內不能服務,應用返回的錯誤是 ORA-03113: end-of-file on communication channel從這個錯誤看,應該是Oracle客戶端返回了連接斷開的錯誤,但是為什么要15分鐘后才返回這個錯誤呢?

機器的網絡情況如下:

應用主機A ----> FW1(防火墻1) ---->FW2(防火墻2) ----> 數據庫主機(OracleDB)

后來經網絡專家的同學判斷,有可能是防火墻設置了會話超時,如果長時間一個會話上沒有數據防火墻就會刪除

會話,同時網上也有人遇到類似的情況:

26142928_6I68

我們做了類似的嘗試,放開防火墻的時間限制后,問題沒再出現。但是還有幾個疑問沒有解決:

1.為什么防火墻刪除會話后,主機要等15分鐘?

2.防火墻刪除會話后,會不會通知主機(給主機發RST)?

早上和同事討論,猜測是由于防火墻刪除了會話,但主機并不知道,有數據庫操作的時候,由Oracle客戶端發起TCP請求,但由于防火墻找不到會話,丟棄了這些包(目前是不是丟還不清楚),導致了TCP不停地超時重發。

查看TCP/IP詳解第一卷的21章節21.2節,都超時重發有這樣的描述:

26142928_3a2X

這里提到9分鐘,不過這本書寫得比較早,猜測linux有所不一樣,不過原理差不了太多,google了一下,

好像找到了15分鐘的說法, 參考資料[1]中提到:

TCP_RTO_MIN=(HZ/5)=0.2s
TCP_RTO_MAX=(120*HZ)=120s
linear_backoff_thresh = ilog2(120*5)=ilog2(0x258)=9
timeout:未超過linear_backoff_thresh=9的部分按TCP_RTO_MIN 2的指數倍增長,超過的部分按TCP_RTO_MAX線性增長
tcp_time_stamp:當前時鐘時間
例如數據發送階段,sysctl_tcp_retries2=9,則timeout=1023*TCP_RTO_MIN=204.6s;sysctl_tcp_retries2=11時,timeout=1023*TCP_RTO_MIN+2*TCP_RTO_MAX=448.6s
默認sysctl_tcp_retries2=15,timeout=1023*TCP_RTO_MIN+6*TCP_RTO_MAX=920.6s,約15分鐘

是根據RTO及一定的算法算出來的(具體的算法,可以看參考資料[3])

簡單說,就是如果系統配置重傳次數小于9的話,就是指數增長時間,如果大于9的話,就是最大超時時間。

而linux默認是15,所以剛好是15分鐘,查看我們主機的配置,確認是15:

[[email protected] ~]$ cat /proc/sys/net/ipv4/tcp_retries2
15

現在還有一個問題沒弄清楚,就是防火墻刪除會話后,是否會通知主機?現在看起來應該是不會的,至少在主機上是沒收到防火墻的RST,由于兩個防火墻的兩個廠商不一樣,也有可能是一個吃掉另外一個的包也說不定。假如刪除會話后,在原來的會話上來有包上來,是重建會話呢?還是直接把包丟棄?還是發RST呢?從目前主機的現象來看,猜測是:

防火墻刪除會話后,不會通知主機也就是不會給主機發RST,當有新包上來,找不到連接,但不是S包的時候,直接丟棄,

導致主機用完了重發次數后,自己發RST后給應用報斷開連接。

不過。。。以上的東東都是根據現象來猜測的,最有效的辦法是捉出tcpdump包來看,但由于是生產不敢亂動,也先這樣吧!

僅以此記,為避免以后踩坑,同時開發人員也要關心網絡部署,當時我并沒有考慮中間有兩個防火墻。

來源//m.oschina.net/blog/318965

分類: 未分類 標簽:

一致性哈希算法的實現

2016年5月29日 1 條評論

一致性哈希算法能夠減少增減節點帶來的memcache緩存失效帶來的沖擊。

下面是一個簡單的java版實現算法,其中的哈希值算法沒有實現,用HashFunction作為一個接口來提供自定義的hash值函數,大多數情況下我們可以使用md5。

circle代表有一個有序整型map,表示要緩存的對象所對應hash值。
創建ConsistentHash對象時會同時創建虛擬節點。每個復制節點都是實用對象名和后綴結合的hash值。
緩存對象分布在每一個map中的節點上。

分類: 未分類 標簽:

分布式系統的數據一致性和處理順序問題

2016年2月18日 4 條評論

現在先拋出問題,假設有一個主數據中心在北京M,然后有成都A,上海B兩個地方數據中心,現在的問題是,假設成都上海各自的數據中心有記錄變更,需要先同步到主數據中心,主數據中心更新完成之后,在把最新的數據分發到上海,成都的地方數據中心A,地方數據中心更新數據,保持和主數據中心一致性(數據庫結構完全一致)。數據更新的消息是通過一臺中心的MQ進行轉發。

先把問題簡單化處理,假設A增加一條記錄Message_A,發送到M,B增加一條記錄 MESSAGE_B發送到M,都是通過MQ服務器進行轉發,那么M系統接收到條消息,增加兩條數據,那么M在把增加的消息群發給A,B,A和B找到自己缺失的數據,更新數據庫。這樣就完成了一個數據的同步。

從正常情況下來看,都沒有問題,邏輯完全合理,但是請考慮以下三個問題

1 如何保證A->M的消息,M一定接收到了,同樣,如何保證M->A的消息,M一定接收到了

2 如果數據需要一致性更新,比如A發送了三條消息給M,M要么全部保存,要么全部不保存,不能夠只保存其中的幾條記錄。我們假設更新的數據是一條條發送的。

3 假設同時A發送了多條更新請求,如何保證順序性要求?

這兩個問題就是分布式環境下數據一致性的問題

對于第一個問題,比較好解決,我們先看看一個tcp/ip協議鏈接建立的過程

我們的思路可以從這個上面出發,在簡化一下,就一個請求,一個應答。

簡單的通信模型是這樣的

A->M : 你收到我的一條消息沒有,消息的ID是12345

M->A: 我收到了你的一條消息數據,消息數據是ID;12345

這樣就一個請求,一個應答,就完成了一次可靠性的傳輸。如果A一致沒有收到M的應答,就不斷的重試。這個時候M就必須保證冪等性。不能重復的處理消息。那么最極端的情況是,怎么也收不到M的應答,這個時候是系統故障。自己檢查一下吧。

這么設計就要求,A在發送消息的時候持久化這個消息的數據內容,然后不斷的重試,一旦接收到M的應答,就刪除這條消息。同樣,M端也是一樣的。不要相信MQ的持久化機制,不是很靠譜的。

那么M給A發送消息也采取類似的原理就可以了。

下面在看看第二個問題,如何保持數據的一致性更新,這個還是可以參考TCP/IP的協議。

首先A發送一條消息給M:我要發送一批消息數據給你,批次號是10000,數據是5條。

M發送一條消息給A:ok,我準備好了,批次號是10000,發送方你A

接著A發送5條消息給M,消息ID分別為1,2,3,4,5 ,批次號是10000,

緊接著,A發送一個信息給M:我已經完成5小消息的發送,你要提交數據更新了

接下來可能發送兩種情況

1 那么M發送消息給A:ok,我收到了5條消息,開始提交數據

2 那么M也可以發送給A:我收到了5條消息,但是還缺少,請你重新發送,那么A就繼續發送,直到A收到M成功的應答。

整個過程相當復雜。這個也就是數據一旦分布了,帶來最大的問題就是數據一致性的問題。這個成本非常高。

對于第三個問題,這個就比較復雜了

這個最核心的問題就是消息的順序性,我們只能在每個消息發一個消息的序列號,但是還是沒有最好解決這個問題的辦法。因為消息接收方不知道順序。因為即使給他了序列號,也沒有辦法告訴他,這個應該何時處理。最好的辦法是在第二種方式的基礎作為一個批次來更新。

這個只是以最簡單的例子來說明一下分布式系統的要保證數據一致性是一件代價很大的事情。當然有的博主會說,這個何必這么復雜,直接數據庫同步不就可以了。這個例子當然是沒有問題的,萬一這個幾個庫的模型都不一樣,我發送消息要處理的事情不一樣的。怎么辦?

在上文,簡單的介紹了分布式數據的同步問題,上面的問題比較抽象,在目前的互聯網應用中還很少見,這次在通過一個比較常見的例子,讓大家更深入的了解一下分布式系統設計中關于數據一致性的問題

這次我們拿我們經常使用的功能來考慮吧,最近網購比較熱門,就以京東為例的,我們來看看京東的一個簡單的購物流程

用戶在京東上下了一個訂單,發現自己在京東的賬戶里面有余額,然后使用余額支付,支付成功之后,訂單狀態修改為支付成功,然后通知倉庫發貨。假設訂單系統,支付系統,倉庫系統是三個獨立的應用,是獨立部署的,系統之間通過遠程服務調用。

訂單的有三個狀態:I:初始 P:已支付 W:已出庫,訂單金額100, 會員帳戶余額200

如果整個流程比較順利,正常情況下,訂單的狀態會變為I->P->W,會員帳戶余額100,訂單出庫。

但是如果流程不順利了?考慮以下幾種情況

1:訂單系統調用支付系統支付訂單,支付成功,但是返回給訂單系統數據超時,訂單還是I(初始狀態),但是此時會員帳戶余額100,會員肯定會馬上找京東罵京東,為啥不給老子發貨,我都付錢了

2:訂單系統調用支付系統成功,狀態也已經更新成功,但是通知倉庫發貨失敗,這個時候訂單是P(已支付)狀態,此時會員帳戶余額是100,但是倉庫不會發貨?;嵩幣慘罹┒?。

3:訂單系統調用支付系統成功,狀態也已經更新成功,然后通知倉庫發貨,倉庫告訴訂單系統,沒有貨了。這個時候數據狀態和第二種情況一樣。

對于問題一,我們來分析一下解決方案,能想到的解決方案如下

1 假設調用支付系統支付訂單的時候先不扣錢,訂單狀態更新完成之后,在通知支付系統你扣錢

如果采用這種設計方案,那么在同一時刻,這個用戶,又支付了另外一筆訂單,訂單價格200,順利完成了整個訂單支付流程,由于當前訂單的狀態已經變成了支付成功,但是實際用戶已經沒有錢支付了,這筆訂單的狀態就不一致了。即使用戶在同一個時刻沒有進行另外的訂單支付行為,通知支付系統扣錢這個動作也有可能完不成,因為也有可能失敗,反而增加了系統的復雜性。

2 訂單系統自動發起重試,多重試幾次,例如三次,直到扣款成功為止。

這個看起來也是不錯的考慮,但是和解決方案一樣,解決不了問題,還會帶來新的問題,假設訂單系統第一次調用支付系統成功,但是沒有辦法收到應答,訂單系統又發起調用,完了,重復支付,一次訂單支付了200。

假設支付系統正在發布,你重試多少次都一樣,都會失敗。這個時候用戶在等待,你怎么處理?

3 在第二種方案的基礎上,我們先解決訂單的重復支付行為,我們需要在支付系統上對訂單號進行控制,一筆訂單如果已經支付成功,不能在進行支付。返回重復支付標識。那么訂單系統根據返回的標識,更新訂單狀態。

接下來解決重試問題,我們假設應用上重試三次,如果三次都失敗,先返回給用戶提示支付結果未知。假設這個時候用戶重新發起支付,訂單系統調用支付系統,發現訂單已經支付,那么繼續下面的流程。如果會員沒有發起支付,系統定時(一分鐘一次)去核對訂單狀態,如果發現已經被支付,則繼續后續的流程。

這種方案,用戶體驗非常差,告訴用戶支付結果未知,用戶一定會罵你,你丫咋回事情,我明明支付了,你告訴我未知。假設告訴用戶支付失敗,萬一實際是成功的咋辦。你告訴用戶支付成功,萬一支付失敗咋辦。

4 第三種方案能夠解決訂單和支付數據的一致性問題,但是用戶體驗非常差。當然這種情況比較可能是少數,可以犧牲這一部分的用戶體驗,我們還有沒有更好的解決方案,既能照顧用戶體驗,又能夠保證資金的安全性。

我們再回來看看第一種方案,我們先不扣錢,但是有木有辦法讓這一部分錢不讓用戶使用,對了,我們先把這一部分錢凍結起來,訂單系統先調用支付系統成功的時候,支付系統先不扣錢,而是先把錢凍結起來,不讓用戶給其他訂單支付,然后等訂單系統把訂單狀態更新為支付成功的時候,再通知支付系統,你扣錢吧,這個時候支付系統扣錢,完成后續的操作。

看起來這個方案不錯,我們仔細在分析一下流程,這個方案還存在什么問題,假設訂單系統在調用支付系統凍結的時候,支付系統凍結成功,但是訂單系統超時,這個時候返回給用戶,告知用戶支付失敗,如果用戶再次支付這筆訂單,那么由于支付系統進行控制,告訴訂單系統凍結成功,訂單系統更新狀態,然后通知支付系統,扣錢吧。如果這個時候通知失敗,木有問題,反正錢都已經是凍結的了,用戶不能用,我只要定時掃描訂單和支付狀態,進行扣錢而已。

那么如果變態的用戶重新拍下來一筆訂單,100塊錢,對新的訂單進行支付,這個時候由于先前那一筆訂單的錢被凍結了,這個時候用戶余額剩余100,凍結100,發現可用的余額足夠,那就直接在對用戶扣錢。這個時候余額剩余0,凍結100。先前那一筆怎么辦,一個辦法就是定時掃描,發現訂單狀態是初始的話,就對用戶的支付余額進行解凍處理。這個時候用戶的余額變成100,訂單數據和支付數據又一致了。假設原先用戶余額只有100,被凍結了,用戶重新下單,支付的時候就失敗了啊,的確會發生這一種情況,所以要盡可能的保證在第一次訂單結果不明確的情況,盡早解凍用戶余額,比如10秒之內。但是不管如何快速,總有數據不一致的時刻,這個是沒有辦法避免的。

第二種情況和第三種情況如何處理,下次在分析吧。

由于互聯網目前越來越強調分布式架構,如果是交易類系統,面臨的將會是分布式事務上的挑戰。當然目前有很多開源的分布式事務產品,例如java JPA,但是這種解決方案的成本是非常高的,而且實現起來非常復雜,效率也比較低下。對于極端的情況:例如發布,故障的時候都是沒有辦法保證強一致性的。

在上文主要介紹了數據分布的情況下保證一致性的情況,在第二篇文章里面,我這里提出了三個問題

1.訂單系統調用支付系統支付訂單,支付成功,但是返回給訂單系統數據超時,訂單還是I(初始狀態),但是此時會員帳戶余額100,會員肯定會馬上找京東罵京東,為啥不給老子發貨,我都付錢了

2.訂單系統調用支付系統成功,狀態也已經更新成功,但是通知倉庫發貨失敗,這個時候訂單是P(已支付)狀態,此時會員帳戶余額是100,但是倉庫不會發貨?;嵩幣慘罹┒?。

3.訂單系統調用支付系統成功,狀態也已經更新成功,然后通知倉庫發貨,倉庫告訴訂單系統,沒有貨了。這個時候數據狀態和第二種情況一樣。

重點分析解決了第一個的問題以及相應的方案,發現在數據分布的環境下,很難絕對的保證數據一致性(任何一段區間),但是有辦法通過一種補償機制,最終保證數據的一致性。

在下面在分析一下第二個問題

訂單系統調用支付系統成功,狀態也已經更新成功,但是通知倉庫發貨失敗,這個時候訂單是P(已支付)狀態,此時會員帳戶余額是100,但是倉庫不會發貨?;嵩幣慘罹┒?。

通過在上一篇文章里面分析過,這個相對來說是比較簡單的,我可以采取重試機制,如果發現通知倉庫發貨失敗,就一致重試,

這里面有兩種方式:

1 異步方式:通過類似MQ(消息通知)的機制,這個是異步的通知

2 同步調用:類似于遠程過程調用

對于同步的調用的方式,比較簡單,我們能夠及時獲取結果,對于異步的通知,就必須采用請求,應答的方式進行,這一點在(關于分布式系統的數據一致性問題(一))里面有介紹。這里面就不再闡述。

來看看第三個問題

訂單系統調用支付系統成功,狀態也已經更新成功,然后通知倉庫發貨,倉庫告訴訂單系統,沒有貨了。這個時候數據狀態和第二種情況一樣。

我覺得這是一個很有意思的問題,我們還是考慮幾種解決的方案

1 在會員下單的時刻,就告訴倉庫,我要你把貨物留下來,

2 在會員支付訂單時候,在支付之前檢查倉庫有沒有貨,如果沒有貨,就告知會員木有貨物了

3 如果會員支付成功,這個時候沒有貨了,就會退款給用戶或者等待有貨的時候在發貨

正常情況,京東的倉庫一般都是有貨的,所以影響到的會員很少,但是在秒殺和營銷的時候,這個時候就不一定了,我們考慮假設倉庫有10臺iphone

如果采用第一種方案,

1 在會員下單的時候,相當于庫存就-1,那么用戶惡意拍下來,沒有去支付,就影響到了其他用戶的購買。京東可以設置一個訂單超時時間,如果這段時間內沒有支付,就自動取消訂單

2 在會員支付之前,檢查倉庫有貨,這種方案了,對于用戶體驗不好,但是對于京東比較好,至少我東西都賣出去了。那些沒有及時付款的用戶,只能投訴了京東無故取消訂單

3 第三種方案,這個方案體驗更不好,而且用戶感覺受到京東欺詐,但是對于京東來說,比第二種方案更有益,畢竟我還可以多賣出一點東西。

個人覺得,京東應該會采用第二種或者第三種方式來處理這類情況,我在微博上搜索了 “京東 無故取消訂單”,發現果真和我預料的處理方式。不過至于這里的無故取消是不是技術上的原因我不知道,如果真的是技術上的原因,我覺得京東可以采用不同的處理方案。對于秒殺和促銷商品,可以考慮第一種方案,大多數人都會直接付款,畢竟便宜啊,如果用戶搶不到便宜的東西,抱怨當然很大了。這樣可以照顧大多數用戶的體驗。對于一般的訂單,可以采用第二種或者第三種方式,這種情況下,發生付款之后倉庫沒有貨的情況會比較少,并且就算發生了,用戶也會覺得無所謂,大不了退錢嗎,這樣就可以實現自己的利益最大化而最低程度的減少用戶體驗。

而鐵道部在這個問題上,采用的是第一種方案,為什么和京東不一樣,就是因為用戶體驗,如果用戶把票都買了,你告訴我木有票了,旅客會殺人的。哈哈,不過鐵道部不擔心票賣不出去,第一種方案對他影響沒有什么。

說了這么多,就是說 分布式環境下(數據分布)要任何時刻保證數據一致性是不可能的,只能采取妥協的方案來保證數據最終一致性。這個也就是著名的CAP定理。

在前面三篇文章中,介紹了關于分布式系統中數據一致性的問題,這一篇主要介紹CAP定理以及自己對CAP定理的了解。

CAP定理是2000年,由 Eric Brewer 提出來的

Brewer認為在分布式的環境下設計和部署系統時,有3個核心的需求,以一種特殊的關系存在。這里的分布式系統說的是在物理上分布的系統,比如我們常見的web系統。

這3個核心的需求是:Consistency,Availability和Partition Tolerance,賦予了該理論另外一個名字 - CAP。

Consistency:一致性,這個和數據庫ACID的一致性類似,但這里關注的所有數據節點上的數據一致性和正確性,而數據庫的ACID關注的是在在一個事務內,對數據的一些約束。

Availability:可用性,關注的在某個結點的數據是否可用,可以認為某一個節點的系統是否可用,通信故障除外。

Partition Tolerance:分區容忍性,是否可以對數據進行分區。這是考慮到性能和可伸縮性。

為什么不能完全保證這個三點了,個人覺得主要是因為一旦進行分區了,就說明了必須節點之間必須進行通信,涉及到通信,就無法確保在有限的時間內完成指定的行文,如果要求兩個操作之間要完整的進行,因為涉及到通信,肯定存在某一個時刻只完成一部分的業務操作,在通信完成的這一段時間內,數據就是不一致性的。如果要求保證一致性,那么就必須在通信完成這一段時間內?;な?,使得任何訪問這些數據的操作不可用。

如果想保證一致性和可用性,那么數據就不能夠分區。一個簡單的理解就是所有的數據就必須存放在一個數據庫里面,不能進行數據庫拆分。這個對于大數據量,高并發的互聯網應用來說,是不可接受的。

我們可以拿一個簡單的例子來說明:假設一個購物系統,賣家A和賣家B做了一筆交易100元,交易成功了,買家把錢給賣家。

這里面存在兩張表的數據:Trade表Account表 ,涉及到三條數據Trade(100),Account A ,Account B

假設 trade表和account表在一個數據庫,那么只需要使用數據庫的事務,就可以保證一致性,同時不會影響可用性。但是隨著交易量越來越大,我們可以考慮按照業務分庫,把交易庫和account庫單獨分開,這樣就涉及到trade庫和account庫進行通信,也就是存在了分區,那么我們就不可能同時保證可用性和一致性。

我們假設初始狀態

trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,I)

account(accountNo,balance) = account(A,300)

account(accountNo,balance) = account(B,10)

在理想情況下,我們期望的狀態是

trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)

account(accountNo,balance) = account(A,200)

account(accountNo,balance) = account(B,110)

但是考慮到一些異常情況

假設在trade(20121001,S)更新完成之前,帳戶A進行扣款之后,帳戶A進行了另外一筆300款錢的交易,把錢消費了,那么就存在一個狀態

trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)

account(accountNo,balance) = account(A,0)

account(accountNo,balance) = account(B,10)

產生了數據不一致的狀態

由于這個涉及到資金上的問題,對資金要求比較高,我們必須保證一致性,那么怎么辦,只能在進行trade(A,B,20121001)交易的時候,對于任何A的后續交易請求trade(A,X,X),必須等到A完成之后,才能夠進行處理,也就是說在進行trade(A,B,20121001)的時候,Account(A)的數據是不可用的。

任何架構師在設計分布式的系統的時候,都必須在這三者之間進行取舍。首先就是是否選擇分區,由于在一個數據分區內,根據數據庫的ACID特性,是可以保證一致性的,不會存在可用性和一致性的問題,唯一需要考慮的就是性能問題。對于可用性和一致性,大多數應用就必須保證可用性,畢竟是互聯網應用,犧牲了可用性,相當于間接的影響了用戶體驗,而唯一可以考慮就是一致性了。

犧牲一致性

對于犧牲一致性的情況最多的就是緩存和數據庫的數據同步問題,我們把緩存看做一個數據分區節點,數據庫看作另外一個節點,這兩個節點之間的數據在任何時刻都無法保證一致性的。在web2.0這樣的業務,開心網來舉例子,訪問一個用戶的信息的時候,可以先訪問緩存的數據,但是如果用戶修改了自己的一些信息,首先修改的是數據庫,然后在通知緩存進行更新,這段期間內就會導致的數據不一致,用戶可能訪問的是一個過期的緩存,而不是最新的數據。但是由于這些業務對一致性的要求比較高,不會帶來太大的影響。

異常錯誤檢測和補償

還有一種犧牲一致性的方法就是通過一種錯誤補償機制來進行,可以拿上面購物的例子來說,假設我們把業務邏輯順序調整一下,先扣買家錢,然后更新交易狀態,在把錢打給賣家

我們假設初始狀態

account(accountNo,balance) = account(A,300)

account(accountNo,balance) = account(B,10)

trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,I)

那么有可能出現

account(accountNo,balance) = account(A,200)

trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)

account(accountNo,balance) = account(B,10)

那么就出現了A扣款成功,交易狀態也成功了,但是錢沒有打給B,這個時候可以通過一個時候的異?;指椿?,把錢打給B,最終的情況保證了一致性,在一定時間內數據可能是不一致的,但是不會影響太大。

兩階段提交協議

當然,還有一種方式就是我另外一篇文章里面《X/Open DTP-分布式事務模型》里面說的,但是再第一階段和第二階段之間,數據也可不能是一致性的,也可能出現同樣的情況導致異常。而且DTP的分布式事務模型 限制太多,例如必須有實現其功能的相關的容器支持,并且資源管理器也必須實現了XA規范。限制比較多。

國外有的架構師有兩種方案去解決CAP的限制,但是也是比較適合特定的業務,而沒有通用的解決方案,

探知分區->分區內操作->事后補償

就是上面介紹的異常檢測恢復機制,這種機制其實還是有限制,

首先對于分區檢測操作,不同的業務涉及到的分區操作可能不一樣

分區內操作限制:不同的業務對應的約束不一致

事后補償:由于業務約束不一樣,補償方式也不一樣。

所以這只能作為一種思想,不能做一個通用的解決方案

(轉載)

分類: 未分類 標簽:
单机捕鱼达人4破解版 大乐透基本走势图表图2 乐翻二人麻将怎么能赢钱 七星彩开奖结果视频 牌9的十赌九赢秘诀 排列五杀两个码最稳法 时时彩历史开奖结果查询 如何在网上开彩票投注站 北京小赛车怎么玩 3d福彩计划大师 秒速赛车的漏洞是什么 ag电子游戏有漏洞吗 20选8快乐十分怎么买稳赚 二八杠棋牌游戏 最准计划软件 重庆时时彩2.1版本安卓