參考:《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、初始化服務器
略,直接參考原文。