SequoiaDB 巨杉數據庫是一款金融級分佈式關係型數據庫,堅持從零開始打造分佈式開源數據庫引擎。「內核筆記系列」旨在分享交流 SequoiaDB 巨杉數據庫引擎的設計思路和代碼解析,幫助社區用戶深刻理解 SequoiaDB 的實現原理,共建開源開放的數據庫技術生態。數據庫
01 基本概念
會話與鏈接是兩個容易混淆的概念。會話(Session) 指是通訊雙方從開始通訊到通訊結束期間的一個上下文(Context)。這個上下文是一段位於服務器端的內存,記錄了本次鏈接的客戶端機器,經過哪一個應用程序和哪一個用戶登陸等信息。而鏈接是指從客戶端到數據庫實例的一條物理路徑。鏈接能夠在網絡上創建,也能夠在本機經過IPC機制創建。一般會在客戶端進程與一個專用服務器或一個調度器之間創建鏈接。服務器
分佈式數據庫 SequoiaDB 的集羣一般由數據節點、協調節點和編目節點組成,集羣內的不一樣節點間存在多種類型的鏈接。所以 SequoiaDB 中存在多種會話,且不一樣的會話對應不一樣的服務。會話的主要任務是處理通訊的對端發來的請求。
集羣中典型的會話結構以下圖。
協調節點監聽客戶端發起的鏈接請求,鏈接創建後建立一個 coord session,即協調節點會話,以後便由這個會話處理對應的客戶端發起的全部請求。coord session 在接收到客戶端發來的處理請求後,會結合編目信息進行分析,確認須要下發到哪些節點去執行,可能會發送給編目節點、一個或多個數據節點。數據節點在接收到協調節點發來的消息時,會建立一個 shard session 來處理請求,執行指定的操做,並返回數據。網絡
SequoiaDB 集羣內的節點間存在多個通訊通道,不一樣類型的節點提供不一樣的服務。爲了保證這些服務各自可以正常工做,SequoiaDB 的節點提供了多個通訊平面。簡單來講,一個通訊平面對應一個服務端口,不一樣的端口提供不一樣類型的服務,這也是爲何在安裝 SequoiaDB 時,要求預留必定範圍內的端口號的緣由。
SequoiaDB 中當前提供了以下幾個通訊平面:
local 平面(local service): 使用節點配置文件中指定的基礎服務端口號 svcnamesession
repl 平面(repl service): 使用端口號svcname+1數據結構
shard 平面(shard service): 使用端口號svcname+2框架
cat 平面(cat service): 使用端口號svcname+3異步
rest 平面(rest service): 使用端口號svcname+4分佈式
om 平面(om service): 使用端口號svcname+5函數
本地會話在直連節點(即配置 svcname)時建立。直連的含義相對寬泛,指的是鏈接任意節點的本地服務端口。客戶端鏈接到協調節點時,會在協調節點上建立本地會話。當本地端口上的監聽接收到新的鏈接請求時,會建立一個新的會話(內存結構)及一個服務線程(執行單元),並將它們綁定(attach)起來。後續客戶端將會直接與這個新的服務線程進行交互。
代碼導讀
SequoiaDB 中各種型的會話繼承關係以下圖所示。
從圖中能夠看到,本地會話、增量/全量同步會話、複製會話等,都是繼承自同一個基類 _ISession。下面將會結合組網對其中幾個關鍵的會話進行介紹,主要是會話創建/銷燬的時機、會話的結構、操做等。
本地會話對應數據結構是類 _pmdLocalSession,線程的主函數是 _pmdLocalSession::run(),會話線程啓動後,就在這個函數裏循環,接收及處理消息,直到會話須要結束時退出該循環。
本地會話能綁定不一樣的 processor 以執行不一樣的處理流程。對於協調節點,綁定的是 _pmdCoordProcessor。對於編目節點和數據節點,綁定的是 _pmdDataProcessor。對於協調節點,會先調用 _pmdCoordProcessor 的接口進行消息處理,在沒法識別請求類型時,則會再次調用 _pmdDataProcessor 的接口進行處理。
05 同步(或複製)會話 Repl Session
分區組內的節點之間,經過同步動做來保證數據的一致性。同步分爲兩種,一種是正常運行狀態下的增量同步,一種是異常狀況下的全量同步。同步是經過對應的同步會話與同步線程來處理的,它涉及到兩個節點,在數據生產方稱爲源端,在數據消費方稱爲目標端。因爲只有數據節點和編目節點上會進行數據複製,因此只有在這兩種類型的節點上,才存在同步會話。
1)增量同步會話
增量同步會話分爲增量同步源端會話和目標端會話,且存在於複製組正常運行期間。在數據節點和編目節點的啓動過程當中,主節點或從節點都會開啓增量同步的監聽。同時,它也會主動啓動一個增量複製目標端會話,並向它選定的源端發送同步請求。源端節點上會被動建立一個增量同步源端會話,這兩個會話後續會開始進行交互,以完成數據同步。
2)全量同步會話
全量同步會話存在於全量同步期間,在集羣正常運行期間及全量同步完成後不存在。與增量同步會話同樣,全量同步會話也分爲源端和目標端。
須要全量同步的場景有三種:
-
備節點的重放速度跟不上主節點,主節點上覆制日誌繞接,致使備節點還未獲取到的複製日誌被覆蓋,備節點沒法繼續增量同步
-
節點異常重啓,啓動後節點根據讀取到的異常啓動狀態決定全量同步
-
節點正常中止後正常重啓,但中止時間較長,期間其它節點上的日誌已經發生了繞接
而不管是上述哪一種狀況,都會先發生增量複製會話。當這些緣由致使增量同步沒法繼續進行的時候,目標節點上會主動建立一個全量同步會話(以及對應的線程),並退出當前的增量複製線程。當全量同步會話啓動時,會向源端發送一個全量同步開始的消息。此時源端上會被動建立一個全量同步源端會話。至此,全量同步的會話建立完成,後續這兩個會話之間會開始進行交互,完成數據同步。
代碼導讀
- 四種會話對應的類爲: _clsReplSrcSession, _clsReplDstSession, _clsFSSrcSession, _clsFSDstSession。
- 同步相關的會話都是異步會話,上述四種會話使用同一個會話管理器:_clsReplSessionMgr 來進行管理。
- 異步會話響應的消息類型及對應的處理函數,通常在對應的類中經過 OBJ_MSG_MAP 等宏進行定義,請參考代碼。
用戶可經過 db.snapshot ( SDB_SNAP_SESSIONS ) 命令列出當前數據庫節點中的全部會話,或經過 db.snapshot ( SDB_SNAP_SESSIONS_CURRENT ) 命令列出當前數據庫節點中的當前會話。
代碼導讀
session 的導出動做在類 _monSessionFetcher 類中實現,並在 init() 函數中準備數據。用戶可選擇查看當前會話 (使用當前線程的 eduCB 接口導出) 或全部會話 (使用 _pmdEDUMgr的接口導出)。 在準備好數據後,由上層統一的 context 框架調用該類的 fetch 接口獲取數據。