本文從普遍認(rèn)為的分布式系統(tǒng)中,最最最重要的數(shù)據(jù)一致性開始。內(nèi)容適合人群>=0年技術(shù)相關(guān)經(jīng)驗(yàn)。
01、為什么需要分布式系統(tǒng)?
任何事物能夠被持續(xù)的運(yùn)用和發(fā)展,必然有其價(jià)值,分布式系統(tǒng)也是一樣。分布式系統(tǒng)的產(chǎn)生我認(rèn)為主要的目的就是“快”和“海量”。這個(gè)“快”可以分為兩個(gè)方面:第一個(gè)是系統(tǒng)的處理速度快,第二個(gè)是開發(fā)的速度快(歷時(shí)短)。
這2點(diǎn)本質(zhì)都是相同的,把一個(gè)動(dòng)作或者一件事情拆成兩部分或者多個(gè)部分去同時(shí)進(jìn)行,使得整體的耗時(shí)縮短。
比如:原本一件事情要一個(gè)人做的話要兩分鐘。那么我雇傭兩個(gè)人幫我各自做一部分,那么最理想情況下一分鐘就可以完成了。
當(dāng)然這兩個(gè)方面中第二項(xiàng)從某種意義上來(lái)說(shuō)是可以克服的,但是第一項(xiàng)是無(wú)法克服的。因?yàn)闆]有一個(gè)程序或者說(shuō)一臺(tái)計(jì)算機(jī),它的性能是無(wú)窮大的,如果有,那分布式系統(tǒng)也不會(huì)像現(xiàn)在這么普遍了(很多時(shí)候用錢能解決的問題都不是問題了)。
“海量”則是由于不存在無(wú)窮大的硬盤,所以我們需要把數(shù)據(jù)分別存儲(chǔ)到不同的硬盤上,才能滿足需求。這些硬盤可能在不同主機(jī)、不同機(jī)房、不同地域,未來(lái)可能會(huì)在不同的星球吧。
02、分布式系統(tǒng)的副作用
所謂每個(gè)事物都是矛盾統(tǒng)一的結(jié)合體,都具有兩面性。分布式系統(tǒng)再帶來(lái)了前面提到的好處的同時(shí),也帶來(lái)了業(yè)界普遍認(rèn)為最大的問題: 數(shù)據(jù)一致性問題。
系統(tǒng)是給人用的,構(gòu)成使用場(chǎng)景的概念叫業(yè)務(wù)。業(yè)務(wù)是核心,對(duì)一個(gè)系統(tǒng)來(lái)說(shuō),業(yè)務(wù)的發(fā)展歸根到底是建立在數(shù)據(jù)之上的。我可以慢、可以宕機(jī)、可以搞得很復(fù)雜,這些都能忍,但唯獨(dú)不能忍的就是數(shù)據(jù)問題,數(shù)據(jù)錯(cuò)誤、數(shù)據(jù)不一致等等。
分布式就意味著分治與協(xié)作,一件事一個(gè)人只負(fù)責(zé)一部分。
生活中這樣的例子也無(wú)處不在,就拿舉辦一個(gè)Party來(lái)說(shuō):一部分人去準(zhǔn)備吃的,一部分人去準(zhǔn)備喝的,一部分人去準(zhǔn)備場(chǎng)地布置。這些事情大家都可以同時(shí)進(jìn)行,但是任一環(huán)節(jié)掉鏈子了,或者說(shuō)不符合Party主題的話,都是失敗的。
不知道為什么,腦子里浮現(xiàn)的是一場(chǎng)發(fā)布會(huì),大家喊著Cheers,一口干了高腳杯里的二鍋頭。再舉個(gè)電商場(chǎng)景中的程序案例:

這里的4個(gè)操作以目標(biāo)來(lái)看,其實(shí)先后順序并不重要,重要的是要么都成功,要么都失敗,其中任意一個(gè)程序不一致那么就會(huì)出問題。這個(gè)問題本質(zhì)上和人與人之間的溝通問題是類似的,上面的Party的例子也是這個(gè)道理。
與溝通唯一的不同在于,對(duì)程序來(lái)說(shuō),不一定都要得到響應(yīng),都沒響應(yīng)也是一致。當(dāng)一個(gè)事情分成100個(gè)部分去做的時(shí)候,很可怕,從概率的角度來(lái)看,達(dá)到一致的概率是2/5050。
這里舉的程序例子并不是嚴(yán)謹(jǐn),因?yàn)閷?shí)際的分布式系統(tǒng)中因?yàn)槌恕癢rite”操作還有“Read”操作,所以一致性問題比這個(gè)更復(fù)雜,后面會(huì)有更詳細(xì)的說(shuō)明。
03、產(chǎn)生數(shù)據(jù)不一致的原因
那么是什么原因?qū)е铝藬?shù)據(jù)不一致的產(chǎn)生呢?一是程序設(shè)計(jì)問題,或者說(shuō)代碼寫錯(cuò)了。這點(diǎn)很好理解,也很容易想到解決方案,多做測(cè)試,驗(yàn)證是否符合預(yù)期咯。常見的單元測(cè)試、接口測(cè)試、自動(dòng)化測(cè)試、集成測(cè)試等等都是為了更具性價(jià)比的將BUG降低到無(wú)限接近于0,也造就了“測(cè)試工程師”這個(gè)崗位更大的作用。
但是,假設(shè)真的沒有BUG,但還是會(huì)產(chǎn)生數(shù)據(jù)不一致,因?yàn)檐浖沁\(yùn)行在硬件之上的,所以還有硬件的因素存在。并且對(duì)我們這里的大部分人來(lái)說(shuō),硬件相比軟件,我們的掌控力更弱。這其中,最為嚴(yán)重的屬網(wǎng)絡(luò)問題,網(wǎng)絡(luò)相比其它的來(lái)說(shuō)是一個(gè)更大、更復(fù)雜的組織,未知性會(huì)隨著局域網(wǎng)、廣域網(wǎng)這樣范圍越大越嚴(yán)重。想象一下,每一臺(tái)主機(jī)僅僅是一張大網(wǎng)中的一個(gè)渺小的連接點(diǎn),它所承載的鏈接越多越容易出現(xiàn)問題。
可能有的小伙伴會(huì)有疑問,其它像硬盤、電源斷電什么的,也有出現(xiàn)問題的可能性,為什么網(wǎng)絡(luò)問題最為嚴(yán)重呢?其實(shí)硬盤、電源好比是你身體的一部分,如手和腳。而網(wǎng)絡(luò)是人與人之間溝通的渠道,比如手機(jī)通話,雖然你沒有主動(dòng)掛斷電話,但是整個(gè)通話過(guò)程是有很多可能性導(dǎo)致中斷的,對(duì)方的主觀意愿也好、信號(hào)不好也罷,甚至被第三者給攔截了。相信大家也能認(rèn)可,打電話出現(xiàn)異常的概率相比自己的手腳不聽使喚是高很多的吧。
現(xiàn)實(shí)中網(wǎng)絡(luò)的特點(diǎn),常遇到的問題如:延遲、丟包、亂序等問題。為了解決這些問題,從互聯(lián)網(wǎng)第一次出現(xiàn)的1969年(當(dāng)年美軍在ARPA制定的協(xié)定下用網(wǎng)絡(luò)連接了4所大學(xué))到現(xiàn)在,幾十年間出了很多的理論和解決方案,這些會(huì)在后續(xù)的文章中給大家一一做梳理。本文先和大家具體剖析下什么是一致性。
04、詳解一致性
首先什么叫達(dá)成一致了?說(shuō)起來(lái)很簡(jiǎn)單:在任意時(shí)間、任意位置看到的同一個(gè)事物是完全一致的。
比如一場(chǎng)足球賽。我們不管在現(xiàn)場(chǎng)還是在電視機(jī)前,看到足球從球員A傳給球員B,這個(gè)信息都是一樣的。但是嚴(yán)格意義上來(lái)說(shuō),這個(gè)并稱不上真正的一致,因?yàn)殡娨暀C(jī)接收到這個(gè)信息需要經(jīng)過(guò)衛(wèi)星信號(hào)、網(wǎng)絡(luò)等的傳輸,我們看到的時(shí)候相比現(xiàn)場(chǎng)的人肯定要晚。
哪怕在現(xiàn)場(chǎng)的人,根據(jù)他所處的位置理論上看到的信息也存在延遲差,只是因?yàn)楣馑俜浅??,使得在相差幾百米之?nèi),這個(gè)延遲小到完全感受不到而已。
至此,能得出的結(jié)論是:在考慮時(shí)間維度的情況下,不存在真正意義上的一致。
況且我們?cè)诜植际较到y(tǒng)中,也沒有必要去達(dá)到真正的意義上的一致。因?yàn)樵节吔谝恢?,系統(tǒng)相當(dāng)于又歸一成一個(gè)單體了,在某一個(gè)時(shí)刻,只能做一件事,完全喪失了分布式系統(tǒng)的兩個(gè)目的之一“快”的優(yōu)勢(shì)。也因此衍生出多種一致性的變種,分別適用于不同的場(chǎng)景。為了便于理解,我們從嚴(yán)格程度的低到高來(lái)說(shuō)。
大多數(shù)情況下,為了盡可能的“快”,系統(tǒng)中使用的大部分方案都是所謂的最終一致性,也就容忍一定條件下的不一致,優(yōu)先保證局部一致,然后再通過(guò)一系列復(fù)雜的狀態(tài)同步達(dá)到全局的一致。最終一致性很多可實(shí)現(xiàn)的分支,列出幾種常見的,拋磚引玉一下:
- 因果一致性:僅要求有因果關(guān)系的操作順序得到保證。比如朋友圈的回復(fù)功能。問“飯吃了嗎?”肯定得在回答“吃了”之前。
- 讀你所寫一致性:文字看著別扭,但很好解釋。比如你在朋友圈下面回復(fù)一句話,其它好友可以不用馬上看到你的回復(fù),但是你自己必須得馬上看到,要不然回復(fù)到哪去了?
- 會(huì)話一致性:與人的一次聊天可以理解為一次會(huì)話。聊天雖然也有一定的因果關(guān)系,但是大部分場(chǎng)景下更多的是邏輯上的先后關(guān)系。
比如你闡述一個(gè)事情,分為3條信息:首先...,然后...,最后...。如果這里的一致性得不到保證那么可能會(huì)變成:最后...,首先...,然后...。
比局部一致更嚴(yán)格一些的就是全局的順序一致性,保證所有進(jìn)程看到的全局執(zhí)行順序一致,并且每個(gè)進(jìn)程自身的執(zhí)行順序和實(shí)際發(fā)生順序一致。
像上面提到的足球賽,比如實(shí)際發(fā)生的事情:①梅西把球傳給了C羅,② C羅又把球回傳給了梅西,那么每個(gè)人看到順序都應(yīng)該是這樣。哪怕現(xiàn)場(chǎng)觀眾已經(jīng)看到②了,電視機(jī)前的我們還沒看到①,但是沒關(guān)系,這個(gè)事情發(fā)生的順序,對(duì)全世界來(lái)說(shuō)都是一樣的。
再嚴(yán)格一些,就是在全局的順序一致性基礎(chǔ)上再增加一個(gè)相對(duì)時(shí)間的一致性要求,業(yè)界稱之為線性一致性。還是用上面梅西和C羅相互傳球的例子來(lái)做個(gè)比喻,相當(dāng)于梅西傳出球給C羅之后,整個(gè)球場(chǎng)“暫停”了,要等所有在觀看這場(chǎng)球賽的人都接收到這個(gè)傳球信息之后,C羅才能做下一個(gè)回傳。這里需要一個(gè)上帝(全局時(shí)鐘)來(lái)“暫?!?。這是我們實(shí)際可以做到的極限了,滿足這類要求的系統(tǒng)中,名氣最大的就屬Google的Spanner了。對(duì)不同級(jí)別的一致性匯總概述如下:

歡迎大家加入粉絲群:963944895,群內(nèi)免費(fèi)分享Spring框架、Mybatis框架SpringBoot框架、SpringMVC框架、SpringCloud微服務(wù)、Dubbo框架、Redis緩存、RabbitMq消息、JVM調(diào)優(yōu)、Tomcat容器、MySQL數(shù)據(jù)庫(kù)教學(xué)視頻及架構(gòu)學(xué)習(xí)思維導(dǎo)圖
寫在最后:
禿頂程序員的不易,看到這里,點(diǎn)了關(guān)注吧!
點(diǎn)關(guān)注,不迷路,持續(xù)更新?。?!
如需Java架構(gòu)資料,點(diǎn)關(guān)注,發(fā)簡(jiǎn)信給我即可,先到先得!