Redis設計與實現:第十四章 -服務器

參考:《Redis設計與實現》

1、命令請求執行過程

1、客戶端發送命令請求

       當用戶在客戶端輸入一個命令,客戶端會將這個命令轉換爲協議格式,通過連接到服務端的套接字,將協議命令發送給服務端。

過程圖示:
在這裏插入圖片描述
       

2、讀取命令組裝結構

讀取命令操作主要分成下面兩步:

  • 讀取套接字中的格式請求,並將其保存到客戶端狀態的輸入緩衝區裏面。
  • 對輸入緩衝區的命令進行分析,提取命令參數與個數信息保存到argv和argc屬性中

比如說set key value這個命令,提取之後填充到客戶端狀態的參數中的數據結構如下所示:
在這裏插入圖片描述
       

3、查找命令執行對象(cmd)

       在命令表(command table)中查找參數指定的命令,命令表是一個字典,字典的鍵是命令的名字,字典的值就是redisCommand結構。

以下是redisCommand結構的主要屬性:

	typedef struct redisCommand{
		char *name; //命令的名字
		
		redisCommandProc proc;//函數指針,指向命令的實現函數
		
		int arity ;//命令參數的個數,用於檢查命令的請求格式是否正確
		
		char *sflags;//命令的屬性,命令的存在值看後面的描述
	
		int flags;//對sflags標識進行分析得出的二進制標識,由程序自動生成

		long long calls; //服務器總共執行了多少次這個命令

		long long milliseconds;//服務器執行這個命令消耗的總時長
	}

       sflags標識的值,以及意義:
標識| 意義
       命令的大小寫不影響命令表的查詢結果。

       

4、檢查校驗操作

  • 檢查客戶端狀態的cmd指針是否指向NULL,如果是的話說明用戶輸入的命令名字找不到相應的命令實現。則應該返回錯誤
  • 根據客戶端狀態的arity屬性,檢查命令給定的參數個數是否正確。參數不正確時直接返回錯誤
  • 檢查客戶端是否通過身份驗證,沒有通過身份驗證返回錯誤
  • 如果服務器打開了maxmemory功能,在執行命令之前,檢查內存佔用情況,在需要的時候進行內存回收,回收失敗返回錯誤
  • …(具體其他的檢查操作查看原書描述)
           

5、執行命令

       在之前的操作中,服務器已經把執行命令保存到客戶端狀態中,所以執行命令操作其實只是通過指針進行一次函數調用即可。被調用的函數實現指定操作,併產生對應的命令回覆,這些回覆保存在客戶端狀態的輸出(固定)緩衝區中。

       

6、後續操作

在執行完命令之後,服務器還會執行相應的後續操作,包括下面的操作:

  • 如果服務器開啓了慢查詢日誌,那麼慢查詢日誌模塊會檢查是否需要添加一條新的慢查詢日誌。
  • 更新milseconds和calls計數器
  • 如果開啓了AOF持久化功能,持久化模塊會將剛剛執行的命令寫入到AOF文件
  • 如果其他服務器正在複製當前服務器,服務器會將命令發送給其他服務器

7、客戶端接收命令並打印

       客戶端收到命令格式的回覆消息,會將這些命令轉換成可讀格式打印在客戶端。
       

2、ServerCron函數

       因爲ServerCron函數執行的操作比較多,這邊只記錄我覺得稍微重要點的操作,其他的操作直接參考原書

1、管理客戶端資源

ServerCron每次都會調用ClientCron函數,clientCron每次都會對一定數量的客戶端進行檢查:

  • 如果客戶端和服務端連接已經超時,程序會釋放這個客戶端。
  • 如果客戶端上一次請求,輸入緩衝區超過一定長度,服務端會釋放客戶端當前輸入緩衝區,並重新創建一個新的輸入緩衝區,從而防止客戶端的輸入緩衝區消費過多的內存。
           

2、管理數據庫資源

       ServerCron每次都會調用databaseCron函數,對一部分數據庫進行檢查,刪除其中的過期鍵,按照需要對字典進行收縮操作。

       

3、初始化服務器

略,直接參考原文。

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