騰訊開源的 Paxos庫 PhxPaxos 程式碼解讀---Accept階段(一)
騰訊開源的 Paxos庫 PhxPaxos 程式碼解讀---Accept階段(一)
在看Accept階段程式碼之前, 我們再回想一下 Basic Paxos演算法;
1. Basic Paxos 演算法是為了使叢集中的Acceptor們達成一個最終的值, 或者不能達成一個最終的值;
就是說, 要麼達成一個最終的值, 某個時間點上, 多數派節點都是一個一致的值, 這個值就是最終的值;
否則, 沒有多數派在某個時間點達成一個一致的值, 這個值不斷被新的提議(Proposal)重新整理, 無法達成最終值;
這種情況一般意味著發生了活鎖;
2. 一個最終的值一旦被確定, 不能再有Proposor發出提議進行修改, 為了確保這點, 有了針對Proposor的約束:
Proposor必須收到多數派的響應, 才能進行Accept提議; 原因如下:
Proposor只有收到多數派響應訊息, 才能確定是否已經有多數派接受過提議(Proposal),
如果多數派響應訊息裡面已經攜帶了接受過的提議, 則有兩種可能:
1. 多數派已經已經達成了一致, 必然會有某些Acceptor的響應攜帶了這個值;
2. 多數派還沒有達成一致, 但是Proposor正好收到了某個已經接受過提議的Acceptor的響應;
上述情況不論是哪種, Proposor都需要用已有的提議發起Accept請求,
這樣是為了促使Acceptor們儘快的達成一致;
3. 對於Acceptor的約束, 則是必須要大於等於當前已經接受過的最大ProposalID, 才能重新整理這個值,;
我們給出一個典型的場景來說明, 以 2個Proposor, 3個Acceptor為例:
第1個時間片段:
Proposor1發起Prepare請求(1, 100), 成功到達 Acceptor1和Acceptor2, Acceptor的狀態如下:
Acceptor1(1, null); Acceptor2(1, null); Acceptor3(null, null)
第2個時間片段:
Proposor2發起Prepare請求(2, 101), 成功到達 Acceptor1和Acceptor2, Acceptor的狀態如下:
Acceptor1(2, null); Acceptor2(2, null); Acceptor3(null, null)
第3個時間片段:
Proposor1發起Accept請求(1, 100), 1 < 2, 被Acceptor拒絕, Acceptor的狀態如下:
Acceptor1(2, null); Acceptor2(2, null); Acceptor3(null, null)
第4個時間片段:
Proposor2發起Accept請求(1, 100), 2=2, 被Acceptor接受, Acceptor的狀態如下:
Acceptor1(2, 100); Acceptor2(2, 100); Acceptor3(null, null)
在處理Prepare和Accept請求時, 我們不僅要考慮網路中的非同步情況, 還要考慮在接受一個提議時程式碼執行的非同步情況;
前面一篇部落格已經簡單介紹過phxpaxos中Prepare階段的程式碼, 下面簡單的介紹一下Accept階段的程式碼;
phxpaxos\src\algorithm\proposer.cpp
這裡的程式碼是Proposor的邏輯
phxpaxos\src\algorithm\acceptor.cpp
這裡的程式碼是Acceptor的邏輯
下面的圖是Proposor發起Accept請求的操作:
下面的圖是Acceptor收到Accept請求的操作:
下面的圖是Propsor收到Acceptor返回響應的操作:
結束:
微信開源的Paxos庫有很多照顧效能的實現, 後面慢慢講吧;