Raft唯讀操作實現要點

2021-09-11 16:24:01 字數 1627 閱讀 9891

leader直連

follower**

客戶端可以鏈結任意節點,客戶端的指令會被follower**到leader來執行。

唯讀操作也必須經過majority確認

唯讀操作一般只需要讀取當前節點的狀態機就可以了。但是存在網路分割槽的情況會導致當前的節點資料嚴重落伍。被分割槽隔離開來的leader和follower全然不知整個集群已經經過了新一輪的選舉,自己的資料已經嚴重落伍了。所以不論客戶端連線的是follower還是leader,都不能直接讀取狀態機來處理唯讀操作。

raft對唯讀操作的處理辦法是

唯讀請求最終也必須依靠leader來執行,如果是follower接收請求的,那麼必須**

記錄下當前日誌的commitindex => readindex

執行讀操作前要向集群廣播一次心跳,並得到majority的反饋

通過查詢狀態機來執行讀操作並返回客戶端最終結果。

在步驟1到步驟2之間,如果leader剛剛當選,還必須等待no-op操作同步完成。

上面的步驟看起來很複雜,其中最重要的就是心跳廣播,這是為了確認當前集群沒有被網路分割槽。

唯讀操作沒那麼快

因為唯讀操作也要經過一次rpc,所以它並沒有我們想想的那麼快,它可能和寫操作效能差不多。所以並不能通過擴充套件節點數量來得到整體集群讀效能的提公升,甚至不公升反降。

折中的方案就是單獨提供乙個特殊的唯讀指令,在一致性要求不高的場合使用這個特殊指令。這樣就可以通過擴充套件集群數量來提公升讀效能。但是在遇到網路分割槽時會導致資料陳舊的問題,要看業務場景是否可以容忍。

唯讀操作的進一步優化

標準的強一致唯讀操作是完全是在leader端進行的。這裡可以做一步改進讓唯讀操作主要在follower端進行。

follower接收到唯讀指令後,向leader索要當前的readindex值。

follower端通過查詢自身的狀態機來執行讀操作並返回客戶端最終結果。

leader向follower返回readindex也不是簡單的直接返回,而是需要重複前面的標準步驟1~步驟3,來確認網路沒有分割槽。這還是一次rpc操作,無法省略。但是毫無疑問,它分擔了leader的壓力,可以讓leader有更多的資源來處理自身的讀寫操作。

唯讀操作的終極優化

前面提到的方法無法避免額外的rpc操作來確認網路沒有被分割槽,所以效能沒有非常明顯的得到優化。 raft的**中提到了另一種可以大幅提公升唯讀操作效能的優化方案,同時還告誡讀者不到萬不得已不要使用。

因為這個額外的rpc操作只是為了確認網路沒有被分割槽,當前節點有無被孤立,新的leader是否有產生。而新leader的產生是需要經歷一次完整的選舉過程的,這個選舉過程有一定的時間才能完成。所以這個分割槽的狀態是可以被快取一小段時間的。這段時間內不可能出現leader的變更。

leader收到majority的心跳響應後,在接下來的一小段時間裡不必去廣播心跳來確認分割槽情況,而可以直接查詢當前節點的狀態機返回客戶端結果。

之所以作者不推薦折中方案是考慮到時鐘漂移。比如乙個定時任務在系統非常繁忙的時候是不能得到準時執行的,會產生偏差,偏差的時間取決於系統的繁忙程度、full gc是否正在進行、虛擬機器是否正在遷移等特殊情況。

Raft的PreVote實現機制

raft的prevote實現機制 在basic raft演算法中,當乙個follower與其他節點網路隔離,如下圖所示 follower 2在electiontimeout沒收到心跳之後,會發起選舉,並轉為candidate。每次發起選舉時,會把term加一。由於網路隔離,它既不會被選成leader...

怎麼實現唯讀屬性

方法一 物件私有化 usr bin env python coding utf 8 author jia shilin class person object def init self,x self.age 20 def get age self return self.age a person ...

DOM操作要點

1 能放到dom操作之外的操作就放到外面,dom操作要盡量少.2 大範圍操作先把容器隱藏,在其中操作完成後,再顯示 這是乙個我剛接觸前端時遇到的乙個優化辦法,當時很不理解為什麼display none之後操作就算是效能優化了.但是資料證明如此渲染確實快了很多,這個的原理要涉及到瀏覽器載入和渲染的原理...