一個命令請求從發送到完成的步驟
如下:
1、客戶端將命令請求發送給服務器
- 當用戶在客戶端中鍵入一個命令請求時,客戶端會將這個命令請求轉換成協議格式,然后通過連接到服務器的套接字,將協議格式的命令請求發送給服務器。
2、服務器讀取命令請求,并分析出命令參數
- 讀取套接字中協議格式的命令請求,將其保存到客戶端狀態的輸入緩沖區中
- 對輸入緩沖區中的命令請求進行解析,提取出命令參數以及命令參數的個數,保存到客戶端狀態的argv屬性與argc屬性
- 調用命令執行器,執行指定指令
3、命令執行器根據參數查找命令的實現函數,然后執行實現函數并得到命令回復
- 根據客戶端狀態的argv[0]參數,在命令表中查找參數所指定的命令,并將找到的命令保存到客戶端狀態的cmd屬性里
- 執行預備操作,確保命令可以正確執行(一些檢查操作)
- 將客戶端狀態指針作為參數傳入實現函數,進行執行
- 執行后續工作
- 若開啟了慢查詢日志功能,模塊會檢查是否需要給剛剛執行完的命令添加一條慢查詢日志
- 若開啟了AOF持久化,模塊會將剛剛執行的命令請求寫入到AOF緩沖區中
- 如果有從服務器正在復制當前服務器,將剛剛執行的命令傳播給所有從服務器
4、服務器將命令回復返回給客戶端
- 命令回復一開始保存在客戶端狀態的輸出緩沖區里,并為客戶端的套接字關聯命令回復處理器
- 當客戶端套接字變為可寫狀態時,服務器會執行命令回復處理器,將保存在客戶端輸出緩沖區的命令回復發送給客戶端
- 命令回復發送完畢,回復處理器清空客戶端狀態的輸出緩沖區
- 客戶端結收到協議格式的命令回復后,解析并打印
初始化服務器步驟
1、初始化服務器狀態
創建struct redisServer類型的實例變量,server作為服務器的狀態,并為結構中的各個屬性設置默認值
例如:
設置服務器的運行ID
設置服務器的默認運行頻率
設置服務器的默認配置文件路徑
設置服務器的運行架構
設置服務器的默認端口號
設置服務器的默認RDB持久化條件和AOF持久化條件
初始化服務器的LRU時鐘 創建命令表
2、載入服務器配置
3、初始化服務器數據結構
除了命令表之外,服務器狀態還包含其他數據結構
- server.clients鏈表,記錄了所有與服務器相連的客戶端的狀態結構,鏈表的每個節點都包含了一個redisClient結構實例
- server.db數組,數組中包含了服務器的所有數據庫
- server.pubsub_channels,用于保存頻道訂閱信息的字典
- server.pubsub_patterns,用于保存模式訂閱信息的鏈表
- servber.lua,用于執行Lua腳本的Lua環境
- server.slowlog,用于保存慢查詢日志
之后調用initServer函數,為數據結構分配內存,并且設置初始化值(通過配置文件的參數)
當然該函數還進行了一些更加重要的操作: - 為服務器設置進程信號處理器
- 創建共享對象,之后服務器將通過重用共享對象來避免反復創建相同的對象
- 打開服務器的監聽端口,并為監聽套接字關聯連接應答事件處理器,等待服務器正式運行時接收客戶端的連接
- 創建時間事件
- 若AOF持久化功能開啟,那么打開現有的AOF文件,若文件不存在,新建一個
- 初始化服務器后臺的I/O模塊
4、還原數據庫狀態
- 如果啟用了AOF持久化功能,用AOF文件還原數據庫狀態
- 否則,使用RDB文件還原
5、執行事件循環