一致性問題產(chǎn)生背景
? ? 互聯(lián)網(wǎng)時代信息量巨大,需要強大的計算能力,不但要求對用戶的響應(yīng)速度要快,還要求吞吐量指標(biāo)向外擴(kuò)展(即水平伸縮),于是單節(jié)點的服務(wù)器無法滿足現(xiàn)實的要求,因此要求對服務(wù)進(jìn)行拆分。
????拆分一般分為水平拆分或者垂直拆分。
????水平拆分是把原先由單一節(jié)點完成的任務(wù)拓展為多個節(jié)點,各個節(jié)點具有一致的功能,所有節(jié)點共同來處理大規(guī)模高并發(fā)的請求量。
? ? 垂直拆分一般是指按照功能進(jìn)行拆分,秉著“專業(yè)的人干專業(yè)的事”的思想,把一個復(fù)雜的功能拆分為多個單一、簡單的功能,拆分后的各個服務(wù)組合在一起,和拆分前的功能是一致的。拆分后的每個服務(wù)功能獨立,使得維護(hù)起來更為簡單、容易、安全,更適宜于產(chǎn)品的迭代,還能夠快速地進(jìn)行敏捷發(fā)布和上線。
? ? 無論是水平拆分還是垂直拆分,都有一致性的問題,既包括了應(yīng)用系統(tǒng)間的一致性,也包括了數(shù)據(jù)的一致性。對于這么多具有單一功能的模塊同一個功能池中的多個節(jié)點,保證它們的信息、工作進(jìn)度、狀態(tài)一致且協(xié)調(diào)有序的工作是必須要解決的問題。
一致性問題經(jīng)典案例
案例1:下訂單和減庫存
? ? 這是電商系統(tǒng)中最經(jīng)典的案例,即訂單系統(tǒng)和庫存系統(tǒng)如何保持一致。如果先下訂單,扣庫存失敗,那么將會導(dǎo)致超賣;如果下訂單不成功,扣庫存成功,那么會導(dǎo)致少賣。這兩種情況都會導(dǎo)致運營成本增加,嚴(yán)重甚至產(chǎn)生資損。
案例2:同步調(diào)用超時
? ? 服務(wù)化的系統(tǒng)調(diào)用常常因為網(wǎng)絡(luò)問題導(dǎo)致系統(tǒng)調(diào)用超時,即使是網(wǎng)絡(luò)狀況良好的機房,在億級流量的基數(shù)下,同步調(diào)用超時也是家常便飯。系統(tǒng)A調(diào)用系統(tǒng)B超時,系統(tǒng)A可以立即獲得超時反饋,但是系統(tǒng)B并不會知道自己超時,A也無法明確得知B系統(tǒng)是否完成預(yù)設(shè)的功能,于是系統(tǒng)A就不知道接下來要做什么,如何反饋給使用方。
案例3:異步回調(diào)超時
? ? 異步回調(diào)可看做是對同步調(diào)用的一種優(yōu)化,屬于受理模式的場景。系統(tǒng)A同步調(diào)用系統(tǒng)B,系統(tǒng)B收到請求后立刻返回受理成功給系統(tǒng)A,然后系統(tǒng)B處理完成后再異步回調(diào)系統(tǒng)A的接口告知處理結(jié)果。相較于同步調(diào)用,異步回調(diào)會立刻返回受理成功或者失敗,不會導(dǎo)致系統(tǒng)A產(chǎn)生阻塞,可以立即反饋使用方處理結(jié)果。?
? ? 但是異步調(diào)用同樣有一致性的問題,如果系統(tǒng)A因為種種原因沒有收到系統(tǒng)B的響應(yīng),那么這兩個系統(tǒng)間的狀態(tài)就會不一致,互相認(rèn)知的狀態(tài)不同會導(dǎo)致系統(tǒng)間發(fā)生錯誤,在嚴(yán)重情況下會影響核心鏈路上的交易的狀態(tài)準(zhǔn)確性,甚至?xí)?dǎo)致資金損失。
案例4:掉單
? ? 在分布式系統(tǒng)中,兩個系統(tǒng)協(xié)作處理一個流程,分別為對方的上下游,如果一個系統(tǒng)中的請求(訂單、線索等)在另外一個請求中不存在,則會導(dǎo)致掉單,掉單的后果很嚴(yán)重,甚至產(chǎn)生資金損失。
案例5:系統(tǒng)間狀態(tài)不一致
? ? 與掉單類似,不同的是,該請求在兩個系統(tǒng)中都存在,但是狀態(tài)不一致。
案例6:緩存和數(shù)據(jù)庫不一致
? ? 分布式系統(tǒng)基本上離不開關(guān)系型數(shù)據(jù)庫,依賴于關(guān)系型數(shù)據(jù)庫所提供的ACID的特性。但是在大規(guī)模、高并發(fā)的互聯(lián)網(wǎng)系統(tǒng)里,一些系統(tǒng)對讀操作要求的性能極高,因此往往需要在數(shù)據(jù)庫前加一層緩存,那么緩存和數(shù)據(jù)庫之間的一致性問題就尤為重要,是保持強一致性還是弱一致性呢?
案例7:本地緩存節(jié)點間不一致
? ? 一個服務(wù)池中的多個節(jié)點為了滿足較高的性能要求,需要使用本地緩存。如果緩存資源是靜態(tài)的、不變的,就永遠(yuǎn)不會有問題。如果這些資源是半靜態(tài)或者經(jīng)常更新的,則被更新時各個節(jié)點會有更新順序的,在更新的瞬間,某個時間窗口內(nèi)的數(shù)據(jù)是不一致的,如果這些數(shù)據(jù)是為某個開關(guān)服務(wù)的,那么就有可能出現(xiàn)重復(fù)的請求進(jìn)入了不同的節(jié)點,一個是開關(guān)打開的邏輯,一個是開關(guān)關(guān)閉的邏輯,會導(dǎo)致請求被處理兩次,前后的狀態(tài)也會不一致,甚至?xí)a(chǎn)生資金損失。
? ? 接下來將會對上述案例進(jìn)行詳解,并探討對應(yīng)的解決方案
參考資料
? ? 《分布式服務(wù)架構(gòu)》--李艷鵬、楊彪著? ??