分布式系統(tǒng)看峻、微服務(wù)架構(gòu)的一致性和冪等性問題相關(guān)概念解析

前言

什么是分布式系統(tǒng)?關(guān)于這點其實并沒有明確且統(tǒng)一的定義互妓。在我看來,只要一個系統(tǒng)滿足以下幾點就可以稱之為分布式系統(tǒng)

  • 系統(tǒng)由物理上不同分布的多個機器節(jié)點組成
  • 系統(tǒng)的多個節(jié)點通過網(wǎng)絡(luò)進行通信,協(xié)調(diào)彼此之間的工作澈蚌。
  • 系統(tǒng)作為整體統(tǒng)一對外提供服務(wù),其分布式細(xì)節(jié)對客戶端透明宛瞄。

要想更好的理解分布式系統(tǒng),并正確使用甚至構(gòu)建分布式系統(tǒng),需要理解其中的兩個關(guān)鍵概念——分布式系統(tǒng)的數(shù)據(jù)一致性和分布式系統(tǒng)的冪等性。

二裸影、分布式系統(tǒng)的數(shù)據(jù)一致性

對于分布式系統(tǒng),數(shù)據(jù)可能存在于不同的物理節(jié)點上,節(jié)點之間只能通過網(wǎng)絡(luò)進行通信來協(xié)調(diào)彼此之間的狀態(tài),而網(wǎng)絡(luò)通信需要時間并且其本身并不十分可靠,因而如何保持?jǐn)?shù)據(jù)一致性成為了分布式系統(tǒng)的難題。對于不同的分布式系統(tǒng),其一致性語義以及面對的一致性難題可能略有差別

1.1 分布式存儲系統(tǒng)中的一致性問題

在分布式存儲系統(tǒng)中,為了保持系統(tǒng)的高可用,同時增加讀操作的并發(fā)性,同一份數(shù)據(jù)會有多份副本,不同的副本存儲于不同的節(jié)點上,如下圖所示

在并發(fā)環(huán)境下,因為存在多個客戶端同時讀取同一數(shù)據(jù)在不同節(jié)點上的副本,因而如何維護數(shù)據(jù)的一致性視圖就非常重要,即對于使用該分布式系統(tǒng)的客戶端而言,對于多副本數(shù)據(jù)的讀寫其表現(xiàn)應(yīng)該和單份數(shù)據(jù)一樣,通常系統(tǒng)是通過數(shù)據(jù)復(fù)制的方式來達(dá)到這一點的,

  • 客戶端將節(jié)點1中的副本A修改為10,系統(tǒng)將通過網(wǎng)絡(luò)通信的方式將節(jié)點2和節(jié)點3中的副本A也更新為10。然而網(wǎng)絡(luò)通信是需要時間的,假設(shè)在系統(tǒng)還未將節(jié)點1中的A值同步到節(jié)點2和節(jié)點3,此時另一個客戶端訪問了節(jié)點2和節(jié)點3,這個時候系統(tǒng)怎么辦彤委?
  • 甚至,考慮更極端的場景,節(jié)點之間的網(wǎng)絡(luò)被斷開,不同節(jié)點無法感知到彼此的存在,當(dāng)然也就無法保持多副本數(shù)據(jù)的同一視圖,那么這個時候系統(tǒng)又該怎么辦焦影?

1.2 微服務(wù)應(yīng)用的分布式一致性問題

微服務(wù)架構(gòu)下,原有的單體應(yīng)用按功能被拆分成一個個微服務(wù)應(yīng)用,每個微服務(wù)應(yīng)用被部署在不同的機器節(jié)點上,只完成原有單體應(yīng)用的某一部分功能,操作屬于該業(yè)務(wù)功能的數(shù)據(jù)庫或表。彼此之前通過網(wǎng)絡(luò)通信的方式協(xié)調(diào)彼此之間的工作,作為整體共同對外提供服務(wù),因而一個業(yè)務(wù)功能的實現(xiàn),可能會涉及到多個微服務(wù)的調(diào)用,操作物理上不同的多個數(shù)據(jù)庫或表。比如對于下單并支付這個業(yè)務(wù)功能而言,需要調(diào)用下單微服務(wù)和支付微服務(wù)來共同完成柄瑰。

對于下單并支付這一業(yè)務(wù)功能,應(yīng)用先調(diào)用訂單微服務(wù),在訂單數(shù)據(jù)庫中添加一條訂單記錄,成功后再調(diào)用支付微服務(wù)添加相應(yīng)的支付記錄,只有這兩個微服務(wù)都調(diào)用成功,該業(yè)務(wù)功能才算執(zhí)行成功蒲跨。這個過程可能存在以下的問題:

  • 訂單微服務(wù)調(diào)用成功,訂單記錄已落地,但是支付微服務(wù)由于各種原因遲遲得不到響應(yīng),此時用戶通過訂單號查詢只能查到訂單記錄而查不到支付記錄,這對于已經(jīng)成功付款的用戶而言肯定是無法接受的,這種情況該怎么辦镐作?
  • 訂單微服務(wù)調(diào)用成功,訂單記錄已落地,但是支付微服務(wù)調(diào)用失敗,此時訂單記錄和支付記錄所對應(yīng)的業(yè)務(wù)狀態(tài)不一致,這時候系統(tǒng)該怎么辦?

1.3 對于一致性的正確理解

分布式存儲系統(tǒng)的一致性問題,主要在于如何維持多副本的一致性視圖上,即如何使多份數(shù)據(jù)對外表現(xiàn)的和一份數(shù)據(jù)一樣该贾。而微服務(wù)架構(gòu)下的分布式應(yīng)用系統(tǒng),其一致性問題主要在于如何使不同微服務(wù)的數(shù)據(jù)對同一業(yè)務(wù)狀態(tài)的描述保持一致,比如對于下單并支付這一業(yè)務(wù)操作而言,下單和支付要么同時成功,要么應(yīng)該同時失敗,而不應(yīng)該一個成功一個失敗,并且在這個過程中,某部分已經(jīng)成功或失敗的數(shù)據(jù)是否應(yīng)該對客戶端可見。在聯(lián)系一下本地事務(wù)ACID中的一致性,我們可能會產(chǎn)生一定的混亂:它們講的一致性是一個東西嗎?先說下我的個人理解:不管是ACID的一致性還是不同分布式系統(tǒng)中的一致性,它們本質(zhì)上講的是一件事:數(shù)據(jù)的一致性,在于正確的反應(yīng)現(xiàn)實世界,對發(fā)生于現(xiàn)實世界的事情的正確描述寇荧。這就要求,一致性的數(shù)據(jù)至少要滿足以下兩個條件:

  • 1.符合系統(tǒng)本身具有的約束條件,比如數(shù)據(jù)庫中的數(shù)據(jù)要遵循主碼,外碼,check約束。
  • 2.與特定業(yè)務(wù)有關(guān)的所有數(shù)據(jù),它們對業(yè)務(wù)執(zhí)行狀態(tài)的描述應(yīng)該保持一致峦嗤。比如從A賬戶轉(zhuǎn)賬100元到B賬戶這一業(yè)務(wù)操作,不管A賬戶和B賬戶是否在一個數(shù)據(jù)庫,也不管這一業(yè)務(wù)操作是否執(zhí)行成功,兩個賬戶的總金額應(yīng)該保持不變;如果有關(guān)賬戶金額的數(shù)據(jù)存儲在分布式系統(tǒng)的多個不同的副本,則這些副本的數(shù)據(jù)應(yīng)該一樣。

從這個意義上,不管是單機數(shù)據(jù)庫還是分布式存儲系統(tǒng)還是微服務(wù)架構(gòu)下的分布式應(yīng)用,對一致性的追求本質(zhì)上是一樣的:在滿足系統(tǒng)本身約束的前提下,對于發(fā)生的業(yè)務(wù)操作及其執(zhí)行狀態(tài)的一致性描述装黑。只不過由于分布式系統(tǒng)數(shù)據(jù)的分布式存儲以及網(wǎng)絡(luò)通信狀況的復(fù)雜,使得分布式系統(tǒng)要保持?jǐn)?shù)據(jù)一致性相比單機應(yīng)用要考慮更多復(fù)雜的因素,實現(xiàn)也要困難的多恋谭。很多文章把它們做了嚴(yán)格的區(qū)分,個人覺得很沒有必要,也不利于對于一致性的正確理解,從哲學(xué)的角度看,是割裂了事物共性和個性之間的聯(lián)系铜幽。

二、分布式一致性模型

就好像單機數(shù)據(jù)庫中為事務(wù)的隔離性設(shè)置了不同的級別,分布式系統(tǒng)中對數(shù)據(jù)的一致性級別也有分類除抛∈ㄑ睿總的來說可以分為強一致性和弱一致性兩大類,弱一致性中又可以繼續(xù)細(xì)分為最終一致性,因果一致性,會話一致性,單調(diào)讀一致性和單調(diào)寫一致性等多種,不過弱一致性中只有最終一致性比較重要,其他的可以暫時忽略。

  • 強一致性
  • 以帶多副本的分布式存儲系統(tǒng)為例,所有連接到分布式系統(tǒng)的客戶端看到的某一數(shù)據(jù)的值都是一樣的到忽。當(dāng)某個客戶端修改了這個值,后續(xù)的所有客戶端都能讀取到這個更新的值,并且所有的更新操作都在這個新的值的基礎(chǔ)上進行,直到這個值被再次修改,如下圖所示,在A修改X前所有客戶端都能讀取到X的值為1,在A將X修改為2之后,所有客戶端都能讀取到這個更新后的值橄教。
  • 最終一致性
  • 所有不能滿足強一致性要求的都稱為弱一致性,而最終一致性是其中比較強的一種清寇。在最終一致性模型下,當(dāng)數(shù)據(jù)項X被修改后,客戶端并不一定能馬上看到這個更新后的值(有些可能讀取到了新值,有些讀取到的可能還是舊值),但是在一段時間后,所有客戶端都能讀取到這個更新后的值并進行相關(guān)操作。最終一致性模型下,分布式數(shù)據(jù)最終能達(dá)到一致,但是需要經(jīng)過一段時間,這段時間稱為不一致窗口护蝶。
  • 如下圖所示,在A將X修改為2后,在不一致窗口內(nèi)只有B能讀取到X=2,其他客戶端讀取到的依舊是X=1盔夜。但是在不一致窗口后,所有客戶端都能讀取到X=2椭微。

三、追求強一致性的約束——CAP定理

嚴(yán)格意義上來講,真正的一致性模型只有一種——強一致性,這也是一種理想化的模型。它為分布式數(shù)據(jù)維護了完全一致的視圖,使得一旦修改了數(shù)據(jù)后,所有客戶端能夠馬上看到這個更新后的值并基于這個新值進行后續(xù)的操作,使得我們操作分布式數(shù)據(jù)和操作本地數(shù)據(jù)一樣纺弊。在分布式系統(tǒng)中要實現(xiàn)一致性需要考慮其他因素,比如可用性和分區(qū)容忍性,而這些因素相互有制約,這種制約關(guān)系在CAP定理中被很好的進行了描述犹菱。

CAP是"Consistency","Availabilty","Partition Tolerance"的簡稱,分別代表了:強一致性,可用性和分區(qū)容忍性,它們的含義分別如下:

  • 強一致性:在分布式系統(tǒng)同一份數(shù)據(jù)有多副本的情況下,對于數(shù)據(jù)的操作效果和只有單份數(shù)據(jù)一樣悍抑。
  • 可用性:客戶端在任何時刻對數(shù)據(jù)的讀/寫操作都應(yīng)該保證在時限內(nèi)完成。
  • 分區(qū)容忍性:當(dāng)分布式系統(tǒng)出現(xiàn)網(wǎng)絡(luò)分區(qū),不同分區(qū)間的機器無法進行網(wǎng)絡(luò)通信時,系統(tǒng)仍然能夠繼續(xù)工作。

CAP定理的內(nèi)容:對于一個分布式系統(tǒng),無法同時實現(xiàn)強一致性,可用性和分區(qū)容忍性,即CAP三要素不可兼得贩幻。

3.1 如何理解CAP三要素不可兼得

由于網(wǎng)絡(luò)的不可靠性,網(wǎng)絡(luò)分區(qū)的情況不可避免的會發(fā)生,當(dāng)出現(xiàn)網(wǎng)絡(luò)分區(qū)時,不同分區(qū)的機器無法進行通信趣些。分布式系統(tǒng)必須能夠在出現(xiàn)網(wǎng)絡(luò)分區(qū)的情況下繼續(xù)工作,因而對于分布式系統(tǒng)而言,P即分區(qū)容忍性是必須要具備的要素,那么問題就轉(zhuǎn)化為了,在系統(tǒng)滿足分區(qū)容忍性的前提下,為什么強一致性和可用性不可兼得令境。

假設(shè)數(shù)據(jù)項A的三個副本分別存儲在不同的物理節(jié)點,在某一時刻,系統(tǒng)狀態(tài)如下圖所示

當(dāng)客戶端將節(jié)點1上的A修改為2后,系統(tǒng)出現(xiàn)了網(wǎng)絡(luò)分區(qū),其中節(jié)點1和節(jié)點2在一個網(wǎng)絡(luò)分區(qū)中,而節(jié)點3在另一個分區(qū)中

當(dāng)有客戶端嘗試讀取節(jié)點3上的A值時,系統(tǒng)將面臨兩難困境

  • 系統(tǒng)等待節(jié)點3從節(jié)點1同步A的值,待數(shù)據(jù)一致后再返回客戶端響應(yīng),但是因為節(jié)點3和節(jié)點1不在一個分區(qū)中,雙方無法進行通信,導(dǎo)致系統(tǒng)無法在限定時間內(nèi)給客戶端返回讀取結(jié)果,這明顯不符合可用性的要求亲配。
  • 系統(tǒng)立即返回一個A=1的舊值給客戶端,由于A的值在不同節(jié)點上不一樣,導(dǎo)致一致性的條件被破壞玷犹。

因而,對于滿足分區(qū)容錯性的系統(tǒng)而言,強一致性和可用性的要求難以同時被滿足领跛。其實這是很容易理解的,即使沒有網(wǎng)絡(luò)分區(qū),因為不同節(jié)點上的數(shù)據(jù)需要經(jīng)過網(wǎng)絡(luò)通信來保持一致性,這個過程本身就比較花時間,當(dāng)需要在給定很短的時限內(nèi)基于客戶端響應(yīng)時,對于一致性的保證自然就比較弱府喳。

3.2 如何正確理解CAP定理

  • 對于分布式系統(tǒng)而言CAP三要素不可兼得,但并不意味著在任何時刻都必須從中做出取舍,或者在構(gòu)建分布式系統(tǒng)之初就選擇其中兩個而放棄另一個,這種看法具有片面性。
  • 由于網(wǎng)絡(luò)分區(qū)出現(xiàn)的可能性非常小,系統(tǒng)在正常運行的情況下還是應(yīng)該兼顧AC兩者,在進入網(wǎng)絡(luò)分區(qū)模式后才需要對P進行保證,從A和C中選擇犧牲一個。
  • A和C并不是一個硬幣的兩面,只能選擇其中一個;A和C應(yīng)該看成天平,系統(tǒng)可以選擇向哪邊傾斜,但另一邊也應(yīng)該一定程度的保留趣斤。
  • 對于A和C之間的選擇,不應(yīng)該粗粒度的整個系統(tǒng)級別進行選取,而應(yīng)該針對系統(tǒng)中的不同子系統(tǒng),針對性的采取不同的取舍策略漫仆。

四、一致性的妥協(xié)——最終一致性和Base原則

由CAP定理可知,在分布式系統(tǒng)中過于追求數(shù)據(jù)的強一致性將導(dǎo)致可用性一定程度被犧牲,這意味著系統(tǒng)將不能很好的響應(yīng)用戶的請求,這會一定程度影響用戶體驗。因而對于大部分布式系統(tǒng)而言,應(yīng)當(dāng)在保證系統(tǒng)高可用的前提下去追求數(shù)據(jù)的一致性,BASE原則正是對這一思想的描述翰撑。

  • BA(Basically Available)
  • 基本可用:系統(tǒng)在絕大部分時間應(yīng)處于可用狀態(tài),允許出現(xiàn)故障損失部分可用性,但保證核心可用溯警。
  • S(Soft State)
  • 軟狀態(tài):數(shù)據(jù)狀態(tài)不要求在任何時刻都保持一致,允許存在中間狀態(tài),而該狀態(tài)不影響系統(tǒng)可用性。對于多副本的存儲系統(tǒng)而言,就是允許副本之間的同步存在延時,并且在這個過程中系統(tǒng)依舊可以響應(yīng)客戶端請求浙炼。
  • E(Eventual Consistency)
  • 最終一致性:盡管軟狀態(tài)不要求分布式數(shù)據(jù)在任何時刻都保持一致,但經(jīng)過一定時間后,這些數(shù)據(jù)最終能達(dá)到一致性狀態(tài)蔬顾。

BASE理論的核心思想是:把分布式系統(tǒng)的可用性放在首位,放棄CAP中對數(shù)據(jù)強一致性的追求,只要系統(tǒng)能保證數(shù)據(jù)最終一致。

4.1 CAP,BASE以及ACID的關(guān)系

CAP描述了對于一個分布式系統(tǒng)而言重要的三要素:數(shù)據(jù)一致性,可用性,分區(qū)容錯性之間的制約關(guān)系,當(dāng)你選擇了其中的兩個時,就不得不對剩下的一個做一定程度的犧牲翻伺。BASE和ACID都可以看做是對CAP三要素進行取舍后的某種特殊情況

  • BASE強調(diào)可用性和分區(qū)容錯性,放棄強一致性,這是大部分分布式系統(tǒng)的選擇,比如NoSQL系統(tǒng),微服務(wù)架構(gòu)下的分布式系統(tǒng)
  • ACID是單機數(shù)據(jù)的事務(wù)特性,因為不是分布式系統(tǒng)無需考慮分區(qū)容錯,故而是選擇了可用性和強一致性后的結(jié)果未妹。
  • 它們之間的關(guān)系如下所示

五扫尖、分布式系統(tǒng)的冪等性

冪等的概念來自于抽象代數(shù),比如對于一元函數(shù)來說,滿足以下條件

即可稱為滿足冪等性茵瀑。在計算機科學(xué)中,一個操作如果多次執(zhí)行產(chǎn)生的影響與一次執(zhí)行的影響相同,這樣的操作即符合冪等性怠益。在分布式系統(tǒng)中,服務(wù)消費方調(diào)用服務(wù)提供方的接口,多次調(diào)用的結(jié)果應(yīng)該與一次調(diào)用的結(jié)果一樣,這正是分布式環(huán)境下冪等性的語義。為什么冪等性對分布式系統(tǒng)而言如此重要瘾婿?因為在分布式環(huán)境下,服務(wù)的調(diào)用一般采用http協(xié)議或者rpc的方式,即雙方需要通過網(wǎng)絡(luò)進行通信,而因為網(wǎng)絡(luò)故障或者消息超時的存在,可能服務(wù)消費方已經(jīng)成功調(diào)用了服務(wù)提供方的服務(wù)接口,但是消費方并沒有收到來自對方的成功響應(yīng),導(dǎo)致消費方以為服務(wù)調(diào)用失敗從而再次進行調(diào)用,也就是說網(wǎng)絡(luò)的不可靠性導(dǎo)致了服務(wù)接口被多次調(diào)用的可能蜻牢。分布式系統(tǒng)必須保證在這種情況下,即使接口被多次調(diào)用,它對系統(tǒng)產(chǎn)生的影響應(yīng)該與該接口只被調(diào)用一次的結(jié)果一樣。

六偏陪、微服務(wù)架構(gòu)的分布式一致性和冪等性問題

6.1 微服務(wù)架構(gòu)下的分布式一致性問題

微服務(wù)架構(gòu)下,處理一個業(yè)務(wù)請求可能需要調(diào)用多個微服務(wù)進行處理,以前面的下單并支付場景為例,完成該業(yè)務(wù)請求需要先后調(diào)用訂單微服務(wù)的下單接口和支付微服務(wù)的支付接口,只有這兩個接口都調(diào)用成功,該業(yè)務(wù)操作才算執(zhí)行成功抢呆。那么微服務(wù)架構(gòu)中是如何保證同屬于一個業(yè)務(wù)單元的多個操作的原子性以及保證分布式數(shù)據(jù)一致性的?——答案是分布式事務(wù)。

分布式事務(wù)是指事務(wù)的參與者笛谦、支持事務(wù)的服務(wù)器抱虐、資源服務(wù)器以及事務(wù)管理器分別位于不同的分布式系統(tǒng)的不同節(jié)點之上

并且根據(jù)遵循的一致性原則不同,可以分為剛性分布式事務(wù)和柔性分布式事務(wù)兩大類。

  • 遵循ACID原則的剛性事務(wù)
  • 剛性事務(wù)追求數(shù)據(jù)的強一致性,比如基于兩階段提交和三階段提交的分布式事務(wù)就屬于剛性事務(wù),通過分布式事務(wù),客戶端可以看到描述業(yè)務(wù)執(zhí)行狀態(tài)的多個數(shù)據(jù)的一致性視圖,比如下單并支付這個業(yè)務(wù)操作,客戶端要么能夠同時查詢到下單和支付成功的信息,要么能夠同時查詢到下單和支付失敗的信息,其他不一致的情況對于客戶端而言都是不可見的饥脑。比如下單成功,支付還在處理;下單成功,支付失敗,下單記錄正在回滾恳邀。也就是說,當(dāng)訂單數(shù)據(jù)和支付數(shù)據(jù)不一致時,對于客戶端的訪問請求應(yīng)該予以拒絕。

這當(dāng)然導(dǎo)致了系統(tǒng)可用性的降低,加上剛性事務(wù)實現(xiàn)時會導(dǎo)致同步阻塞的問題,鎖定資源等問題,會極大的影響系統(tǒng)的吞吐量和設(shè)計彈性,所以實際上微服務(wù)架構(gòu)不太會采用剛性事務(wù)灶轰。

  • 遵循BASE原則的柔性事務(wù)
  • 柔性事務(wù)只對數(shù)據(jù)的最終一致性進行保證,允許系統(tǒng)存在一定時間的數(shù)據(jù)不一致,比如訂單記錄已經(jīng)被更新但是支付記錄還沒落地時,又比如訂單記錄更新成功但是支付失敗訂單記錄回滾的過程谣沸。

在這個不一致窗口內(nèi),系統(tǒng)允許客戶端對不一致的數(shù)據(jù)進行訪問,因而系統(tǒng)的可用性相比而言會更好,加上其擴展性良好以及吞吐量的優(yōu)勢,一般微服務(wù)架構(gòu)下都會采用柔性事務(wù)。柔性事務(wù)有多種不同的實現(xiàn)方式,比如基于可靠事件的模式,基于補償?shù)哪J?基于Sagas長事務(wù)的模式等,具體的實現(xiàn)原理以及優(yōu)缺點對比就放到下一篇在詳解解釋笋颤。

6.2 微服務(wù)架構(gòu)下的冪等性問題

6.2.1 冪等性場景

在微服務(wù)架構(gòu)下,不同微服務(wù)間會有大量的基于http,rpc或者mq消息的網(wǎng)絡(luò)通信,接口的重復(fù)調(diào)用以及消息的重復(fù)消費可能會經(jīng)常發(fā)生,比如以下這些情況

  • 調(diào)用訂單創(chuàng)建接口,第一次調(diào)用超時,調(diào)用方又嘗試了一次,但其實第一次調(diào)用已經(jīng)成功,只是調(diào)用方?jīng)]有及時收到響應(yīng)乳附。
  • 訂單支付完成后,需要向MQ發(fā)送一條消息,但該消息重復(fù)發(fā)送了兩條。
  • 網(wǎng)絡(luò)波動導(dǎo)致服務(wù)提供方的接口被調(diào)用了兩次。
  • 用戶在使用產(chǎn)品時,無意地觸發(fā)多筆交易赋除。
  • 某些未關(guān)閉的重試機制阱缓。

微服務(wù)架構(gòu)應(yīng)該具有冪等性,當(dāng)接口被重復(fù)調(diào)用時,消息被重復(fù)消費時,對系統(tǒng)的產(chǎn)生的影響應(yīng)該和接口被調(diào)用一次,消息被消費一次時一樣。

6.2.2 CRUD操作的冪等性分析

  • 新增請求:不具備冪等性
  • 查詢請求:重復(fù)查詢不會影響系統(tǒng)狀態(tài),查詢天然具備冪等性
  • 基于主鍵的更新請求
  • 要更新的值依賴于前值,不具備冪等性举农。比如update goods set number=number-1 where id=1
  • 要更新的值不依賴于前值,具備冪等新荆针。比如update goods set number=newNumber where id=1
  • 刪除請求
  • 基于主鍵的物理刪除(delete)刪除具備冪等性
  • 基于主鍵的邏輯刪除(update)也具有冪等性

總結(jié):通常只需要對新增請求和更新請求作冪等性保證。

6.2.3 如何解決冪等性問題

  • 全局唯一ID
  • 根據(jù)業(yè)務(wù)生成一個全局唯一ID,在調(diào)用接口時會傳入該ID,接口提供方會從相應(yīng)的存儲系統(tǒng)比如Redis中去檢索這個全局ID是否存在,如果存在則說明該操作已經(jīng)執(zhí)行過了,將拒絕本次服務(wù)請求;否則將相應(yīng)該服務(wù)請求并將全局ID存入存儲系統(tǒng)中,之后包含相同業(yè)務(wù)ID參數(shù)的請求將被拒絕颁糟。
  • 去重表
  • 這種方法適用于在業(yè)務(wù)中有唯一標(biāo)識的插入場景航背。比如在支付場景中,一個訂單只會支付一次,可以建立一張去重表,將訂單ID作為唯一索引。把支付并且寫入支付單據(jù)到去重表放入一個事務(wù)中,這樣當(dāng)出現(xiàn)重復(fù)支付時,數(shù)據(jù)庫就會拋出唯一約束異常,操作就會回滾滚停。這樣保證了訂單只會被支付一次。
  • 多版本并發(fā)控制
  • 適合對更新請求作冪等性控制,比如要更新商品的名字,這是就可以在更新的接口中增加一個版本號來做冪等性控制
boolean updateGoodsName(int id,String newName,int version);

數(shù)據(jù)庫更新的SQL語句如下

update goods set name=#{newName},version=#{version} where id=#{id} and version<${version}
  • 狀態(tài)機控制
  • 適合在有狀態(tài)機流轉(zhuǎn)的情況下,比如訂單的創(chuàng)建和付款,訂單的創(chuàng)建肯定是在付款之前粥惧。這是可以添加一個int類型的字段來表示訂單狀態(tài),創(chuàng)建為0,付款成功為100,付款失敗為99,則對訂單狀態(tài)的更新就可以這樣表示
update order set status=#{status} where id=#{id} and status<#{status}
  • 插入或更新
  • 在MySQL數(shù)據(jù)庫中键畴,如果在insert語句后面帶上ON DUPLICATE KEY UPDATE 子句,而要插入的行與表中現(xiàn)有記錄的惟一索引或主鍵中產(chǎn)生重復(fù)值,則對舊行進行更新;否則執(zhí)行新紀(jì)錄的插入突雪。
  • 我們可以利用該特性防止記錄的重復(fù)插入,比如good_id和category_id構(gòu)成唯一索引,則重復(fù)執(zhí)行多次該SQL,數(shù)據(jù)庫中也只會有一條記錄起惕。
insert into goods_category (goods_id,category_id,create_time,update_time) 
 values(#{goodsId},#{categoryId},now(),now()) 
 on DUPLICATE KEY UPDATE
 update_time=now()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市咏删,隨后出現(xiàn)的幾起案子惹想,更是在濱河造成了極大的恐慌,老刑警劉巖督函,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘀粱,死亡現(xiàn)場離奇詭異,居然都是意外死亡辰狡,警方通過查閱死者的電腦和手機锋叨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宛篇,“玉大人娃磺,你說我怎么就攤上這事〗斜叮” “怎么了偷卧?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吆倦。 經(jīng)常有香客問我听诸,道長,這世上最難降的妖魔是什么蚕泽? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任蛇更,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘派任。我一直安慰自己砸逊,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布掌逛。 她就那樣靜靜地躺著师逸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪豆混。 梳的紋絲不亂的頭發(fā)上篓像,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音皿伺,去河邊找鬼员辩。 笑死,一個胖子當(dāng)著我的面吹牛鸵鸥,可吹牛的內(nèi)容都是我干的奠滑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼妒穴,長吁一口氣:“原來是場噩夢啊……” “哼宋税!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起讼油,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤杰赛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后矮台,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乏屯,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年瘦赫,在試婚紗的時候發(fā)現(xiàn)自己被綠了瓶珊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡耸彪,死狀恐怖伞芹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝉娜,我是刑警寧澤唱较,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站召川,受9級特大地震影響南缓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜荧呐,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一汉形、第九天 我趴在偏房一處隱蔽的房頂上張望纸镊。 院中可真熱鬧,春花似錦概疆、人聲如沸逗威。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凯旭。三九已至,卻和暖如春使套,著一層夾襖步出監(jiān)牢的瞬間罐呼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工侦高, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嫉柴,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓奉呛,卻偏偏與公主長得像计螺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子侧馅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容