更新時間:2022-06-16 10:06:58 來源:動力節(jié)點 瀏覽865次
隨著大型網(wǎng)站的各種高并發(fā)訪問、海量數(shù)據(jù)處理等場景越來越多,如何實現(xiàn)網(wǎng)站的高可用、易伸縮、可擴(kuò)展、安全等目標(biāo)就顯得越來越重要。為了解決這樣一系列問題,大型網(wǎng)站的架構(gòu)也在不斷發(fā)展。提高大型網(wǎng)站的高可用架構(gòu),不得不提的就是分布式。在關(guān)于分布式事務(wù)、兩階段提交協(xié)議、三階提交協(xié)議一文中主要用于解決分布式一致性問題的集中協(xié)議,那么這篇文章主要講解業(yè)內(nèi)公認(rèn)的比較難的也是最行之有效的paxos算法。
Paxos 算法是分布式一致性算法用來解決一個分布式系統(tǒng)如何就某個值(決議)達(dá)成一致的問題。
人們在理解paxos算法是會遇到一些困境,那么接下來,我們帶著以下幾個問題來學(xué)習(xí)paxos算法:
1.paxos到底在解決什么問題?
2.paxos到底如何在分布式存儲系統(tǒng)中應(yīng)用?
3.paxos的核心思想是什么?
在關(guān)于分布式一致性的探究中我們提到過,分布式的一致性問題其實主要是指分布式系統(tǒng)中的數(shù)據(jù)一致性問題。所以,為了保證分布式系統(tǒng)的一致性,就要保證分布式系統(tǒng)中的數(shù)據(jù)是一致的。
在一個分布式數(shù)據(jù)庫系統(tǒng)中,如果各節(jié)點的初始狀態(tài)一致,每個節(jié)點都執(zhí)行相同的操作序列,那么他們最后能得到一個一致的狀態(tài)。為保證每個節(jié)點執(zhí)行相同的命令序列,需要在每一條指令上執(zhí)行一個“一致性算法”以保證每個節(jié)點看到的指令一致。
所以,paxos算法主要解決的問題就是如何保證分布式系統(tǒng)中各個節(jié)點都能執(zhí)行一個相同的操作序列。

上圖中,C1是一個客戶端,N1、N2、N3是分布式部署的三個服務(wù)器,初始狀態(tài)下N1、N2、N3三個服務(wù)器中某個數(shù)據(jù)的狀態(tài)都是S0。當(dāng)客戶端要向服務(wù)器請求處理操作序列:op1op2op3時(op表示operation)(這里把客戶端的寫操作簡化成向所有服務(wù)器發(fā)送相同的請操作序列,實際上可能通過Master/Slave模式處理)。如果想保證在處理完客戶端的請求之后,N1、N2、N3三個服務(wù)器中的數(shù)據(jù)狀態(tài)都能從S0變成S1并且一致的話(或者沒有執(zhí)行成功,還是S0狀態(tài)),就要保證N1、N2、N3在接收并處理操作序列op1op2op3時,嚴(yán)格按照規(guī)定的順序正確執(zhí)行opi,要么全部執(zhí)行成功,要不就全部都不執(zhí)行。
所以,針對上面的場景,paxos解決的問題就是如何依次確定不可變操作opi的取值,也就是確定第i個操作什么,在確定了opi的內(nèi)容之后,就可以讓各個副本執(zhí)行opi操作。
Paxos是一個十分巧妙的一致性算法,但是他也十分難以理解,就連他的作者Lamport都被迫對他做過多種講解。我認(rèn)為對paxos算法講解的最清楚的就是維基百科了。但是要看懂維基百科中的介紹需要很強(qiáng)的數(shù)學(xué)思維(paxos畢竟是一個算法),而且有很多關(guān)于定理的推論、證明等過程。那么本篇文章主要站在程序的角度,通俗的,循序漸進(jìn)的講解到底什么是paxos算法。
我們先把前面的場景簡化,把我們現(xiàn)在要解決的問題簡化為如何確定一個不可變變量的取值(每一個不可變變量可以標(biāo)識一個操作序列中的某個操作,當(dāng)確保每個操作都正確之后,就可以按照順序執(zhí)行這些操作來保證數(shù)據(jù)能夠準(zhǔn)確無誤的從一個狀態(tài)轉(zhuǎn)變成另外一個狀態(tài)了)。
接下來,請跟我一步一步的學(xué)習(xí)paxos算法。
要學(xué)習(xí)paxos算法,我們就要從他要解決的問題出發(fā),假如沒有paxos算法,當(dāng)我們面對如何確定一個不可變變量的取值這樣一個問問題的時候,我們應(yīng)該如何解決呢?
這里暫不介紹paxos中的角色的概念,讀者可以自行從維基百科中了解。不了解的話也可以直接往下看,看著看著就了解了。
問題抽象
我們把確定一個不可變變量的取值問題定義成:
設(shè)計一個系統(tǒng),來存儲名稱為var的變量。
var的取值可以是任意二進(jìn)制數(shù)
系統(tǒng)內(nèi)部由多個Accepter組成,負(fù)責(zé)管理和存儲var變量。
系統(tǒng)對外提供api,用來設(shè)置var變量的值propose(var,V) =><ok,f> or<error>
將var的值設(shè)置為V,系統(tǒng)會返回ok和系統(tǒng)中已經(jīng)確定的取值f,或者返回error。
外部有多個Proposer機(jī)器任意請求系統(tǒng),調(diào)用系統(tǒng)API(propose(var,V) =><ok,f> or<error> )來設(shè)置var變量的值。
系統(tǒng)對外提供api,用來設(shè)置var變量的值propose(var,V) => or
將var的值設(shè)置為V,系統(tǒng)會返回ok和系統(tǒng)中已經(jīng)確定的取值f,或者返回error。
外部有多個Proposer機(jī)器任意請求系統(tǒng),調(diào)用系統(tǒng)API(propose(var,V) => or )來設(shè)置var變量的值。
系統(tǒng)需要保證var的取值滿足一致性
如果var沒有被設(shè)置過,那么它的初始值為null
一旦var的值被設(shè)置成功,則不可被更改,并且可以一直都能獲取到這個值
系統(tǒng)需要滿足容錯特性
可以容忍任意proposer出現(xiàn)故障可以容忍少數(shù)acceptor故障(半數(shù)以下)
暫時忽略網(wǎng)絡(luò)分化問題和acceptor故障導(dǎo)致var丟失的問題。
到這里,問題已經(jīng)抽象完成了,讀者可以再仔細(xì)看看上面的系統(tǒng)描述。如果這樣設(shè)置一個系統(tǒng),是不是就可以保證變量var的不可變性了呢?
這里還是再簡單講解一下,上面的系統(tǒng)確實可以保證變量var的不可變性。
因為var的初始值為null,當(dāng)有proposer請求接口propose(var,v)設(shè)置var的值的時候,系統(tǒng)會將var設(shè)置為v,并返回f(f==v)。
var變量被初始化以后,再有proposer請求propose(var,v)設(shè)置var的值的時候,系統(tǒng)會直接返回系統(tǒng)中已有的var的值f,而放棄proposer提供的v。
以上就是關(guān)于“分布式一致性算法:paxos算法”的介紹,大家如果想了解更多相關(guān)知識,可以關(guān)注一下動力節(jié)點的Java在線學(xué)習(xí),里面的課程內(nèi)容細(xì)致全面,從入門到精通,很適合沒有基礎(chǔ)的小伙伴學(xué)習(xí),希望對大家能夠有所幫助哦。