6.824 Fault-tolerant key/value storage system v1.0(四)( Brief description of code architecture)

一、概述

  在這篇博文中將整理一下到 Lab 3B 爲止的系統結構,並在後續的博文中開啓對於整個系統關鍵技術點實現思路的記述。


二、系統介紹

2.1 概述

  該服務爲通過 Get/Put/Append 方法調用該服務的客戶端提供 強一致性保障 ,這裏所說的強一致性是指如果客戶端一次調用一個方法,那這個方法的調用應該跟調用僅有一個副本的系統一樣,並且每個調用都應該能觀察到前面的調用序列對狀態的修改結果。而對於併發調用,返回值和最終狀態必須與前面所說的客戶端一次調用一個方法即按順序操作的結果相同。


2.2 支持操作

  該服務支持三種操作:Put(Key、Value)、Append(Key、Value) 和 Get(Key),可以認爲它維護了一個簡單的鍵/值對數據庫。

  • Put() 替換數據庫中特定鍵的值;
  • Append(key, arg) 將arg附加到鍵的值,附加到不存在的鍵的行爲類似 Put() ;
  • Get() 獲取鍵的當前值;

三、系統整體結構

3.1 系統整體結構示意圖

在這裏插入圖片描述


3.2 系統結構劃分

  當前系統的整體結構基本如上圖所示,從最底層看起目前的系統可以大致分爲以下這五個部分:

  1. Client :外部調用服務的客戶端,對於服務的調用方式目前僅基於 Method Call;
  2. Clerk :可以簡單理解爲接待員,它處於 Client 和 Server 的中間層,主要職能是接收來自 Client 的請求後,通過管理與 KV Server 之間的 RPC 交互完成對 KV Server 中數據的修改或查詢操作,且每個 Clerk 僅對應一個 Client;
  3. KV Server :Key/Value 數據庫服務器,且每個 Server 對應一個底層的 Raft Peer,但需要注意的是 Clerk 與 KV Server 非一一對應的關係,Clerk 僅會將對數據的操作發送給 Leader Raft Peer;
  4. Raft Protocol :提供基於 Raft 算法的數據一致性保障;
  5. LabRPC :因爲目前暫時使用的還是 Lab 提供的 PRC 框架,因此所有節點之間的 RPC 通訊目前均基於 LabRPC;

3.3 系統各部分之間的關聯

   首先因爲 LabRPC 部分算是系統中的一個通信模塊,主要用於通信且不包含業務和算法邏輯,所以在分析各部分關聯時我們先將其剔除掉,直接看剩下的四個部分。

  • 首先, Client 和 Clerk 是一一對應的關係,對於 ClientClerk 之間的調用目前主要是通過 方法的調用 來完成的,是 Lab 中爲了便於測試而提供的默認調用方式,而這種實現方式的限制很多,不僅不能夠通過網絡來進行調用服務,更別說支持其它語言對該服務的調用了。因此在後期可以將其擴展爲基於 gRPC gateway 的方式來支持外部通過 HTTP JSON 對服務進行調用,以此來增強服務的靈活性和跨語言調用性。
  • 其次, Clerk 和 KV Server 之間爲調用時一一對應的關係,即每個 Clerk 保存了當前集羣中所有 KV Server 的信息,但 Clerk 在調用時僅會調用一個 KV Server 。對於 ClerkKV Server 之間的調用主要是通過 RPC 來完成的,Clerk 在發送完 RPC 後一般會阻塞等待 KV Server 的迴應後再進行其它的操作。目前項目中使用的是 Lab 提供的 LabRPC,後期優化時可將其替換爲 gRPC + Protobuf 來進一步提升系統的性能和服務的規範性。
  • 再其次,KV Server 和 Raft Peer 之間又是一一對應的關係,每個 KV Server 唯一對應底層的一個 Raft Peer ,系統通過底層的 Raft Protocol 來保障集羣服務器中數據的一致性。而對於 KV ServerRaft Peer 之間的通信是通過 方法調用通道 兩種方式進行的。方法調用主要用於 KV Server 創建並初始化 Raft Peer 。Raft Peer 會通過通道將可應用的數據和 快照 發送給 KV Server,而 KV Server 會通過通道通知 Raft Peer 進行數據日誌的壓縮;
  • 最後,Raft Peer 之間是完全通過 PRC 來進行通訊的,這裏需要注意 KV Server 互相之間是完全隔離的,兩個 KV Server 之間只能通過底層的 Raft Protocol 實現數據的通信,而針對任意一個 KV Server 中數據的讀取或修改操作都會被實時的同步到所有的 KV Server 中(這裏只是便於理解,系統中僅 Leader Raft Peer 纔有權限進行寫數據的操作,所以數據同步的方向永遠是從 Leader 到 Follower),以此來保障整個集羣中數據的一致性;

3.4 系統各部分之間調用的細節

在這裏插入圖片描述

   上面我們已經概述了系統各部分之間的調用方式,但是比較不好理解的就是 Clerk 對 KV Server 的調用,在上面我們說過每個 Clerk 都會保存集羣中所有 KV Server 的信息,但是在真正進行調用的時候是隻會調用唯一的一個 KV Server,那系統是怎麼來判斷到底應該調用哪個 KV Server 的呢?

   首先 Client 會將對數據操作的請求發送給 Clerk ,Clerk 接收到請求後會將其封裝爲一個 RPC,然後從自己所保存的所有 KV Server 中隨機挑選一個進行發送(優化後可首先嚐試上一次成功執行操作的 KV Server),當這個隨機挑選的 KV Server 接收到該 RPC 後會通過方法調用來獲取它底層所對應的 Raft Peer 的當前狀態(是否爲 Leader),如果底層 Raft Peer 當前的狀態是 Leader 則 KV Server 會一直等待底層的 Raft Protocol 完成對本次操作的集羣同步,並在接收到 ApplyMsg 後實際執行該數據操作,最後返回結果給 Clerk (這期間 Clerk 是一直處於阻塞等待的)。而如果底層 Raft Peer 當前的狀態非 Leader ,那 KV Server 會直接返回消息表示其不是 Leader ,而 Clerk 在接收到這條回覆後會再選取其它的 KV Server 進行嘗試直至操作被成功執行。

  下圖是上述的整個流程的流程圖,這裏爲了降低理解的難度已經刪去了很多關鍵的技術點和需要考慮的複雜因素,在後面的博文裏會逐步將整個請求處理的流程補充起來。


kvserver

四、系統源碼

https://github.com/TIYangFan/DistributedSystemBaseGolang ( 如果可以幫到你,Please Star ^ _ ^ ~ )


五、內容總結

  在這篇博文中對該系統的整體結構進行了分析,並分析了幾個重點模塊之間的調用方式。

  最後談下爲什麼突然又開始寫 Raft 相關的博文,這主要是因爲當時在做 Lab 3B 時遇到了瓶頸,總是存在少數的用例無法通過的情況,然後爲了換一下心情,所以後面的一週裏我基本都在學習 Zab 協議的一些內容,並進行 Zookeeper 的一些源碼分析,前兩天再回去重新整理項目代碼的時候在自己的不懈努力下終於通過了 Lab 3B 的全部測試用例,所以趁着思路還比較清晰會在最近的一段時間將到 Lab 3 爲止的系統實現整理一下,也便於以後的重構和優化擴展。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章