Redis設計與實現:第十三章 - 客戶端

參考:《Redis設計與實現》

1、客戶端定義

       Redis服務器是典型的一對多服務器程序,通過使用由I/O多路複用技術實現文件事件處理器,Redis服務器使用單進程單線程的方式來處理命令請求,並與多個客戶端進行網絡通信。

       對於每個與服務端進行連接的客戶端,服務器都是爲這些客戶端建立對應的redis.h/redisClient結構來保存客戶端當前的狀態信息,以及相關功能需要用到的數據結構。

       Redis服務器狀態結構的clients屬性是一個鏈表,保存了與服務器連接的客戶端的狀態結構。數據結構如下:

	struct redisServer{
		list *clients //一個保存所有客戶端狀態的鏈表
	}

       假設一個服務端與三個客戶端對接,他的數據結構是這樣的:
在這裏插入圖片描述
       

2、客戶端屬性

1、套接字描述符、名字、標誌

數據結構標識:

	typedef struct redisClient{
		int fd;//套接字描述符
		robj *name;//名字
		int flags; //標識
	}

套接字描述符
       僞客戶端的套接字描述符字段值爲-1,僞客戶端的處理命令來源於AOF文件或者Lua腳本,而不是網絡。普通客戶端的套接字標識符爲大於-1的整數

名字
       默認情況下,連接到服務端的客戶端是沒有名字的,但是可以通過設置name字段讓客戶端的身份更明確。

標誌
       客戶端的標誌屬性記錄了客戶端的角色信息

       flags屬性可以是單個標誌,也可以是多個標誌的二進制或。
       

2、命令

       命令參數與執行程序對應數據結構

	typedef struct redisClient{
		robj **argv //字符串數組,用來保存相應的命令內容
		int argc //字符串數組的大小

		struct redisCommand *cmd //命令所對應的redisCommand結構
	}

       服務器將客戶端發送的命令請求存儲到客戶端狀態的query_buf屬性之後,服務器會對命令的內容進行分析,將分析的結果保存到 argv和argc屬性上,具體的如果是像set key value這樣的命令他的存儲如下:
在這裏插入圖片描述

       服務器進行命令的解析時,會從argv[0]獲取值並與命令數據字典dict進行匹配,找到對應的命令信息,存儲到cmd屬性。這個屬性包含給定的參數個數、命令的總執行次數,命令的總耗時等統計信息。服務端通過調用cmd這個參數進行命令的執行。

3、緩衝區

       輸入緩衝區與輸出緩衝區的結構表示:

	typedef struct redisClient{
		sds querybuf; //輸入緩衝區

		//固定大小輸出緩衝區
		char buf[REDIS_REPLY_CHUNK_BYTES]
		int bufpos

		list *reply; //可變大小輸出緩衝區
	}

       輸入緩衝區是保存客戶端輸入的命令信息,所以用sds的結構進行存儲,它的大小會根據內容動態的縮小或者擴大,但是最大大小如果超過1GB,服務端就會關閉這個客戶端。

       每個客戶端都會有兩個輸出緩衝區,一個緩衝區大小是固定的,一個緩衝區大小是可變的。

       固定大小緩衝區,通過buf數組bufpos,兩個屬性組合,buf數組的大小是固定的,bufpos則記錄了buf數組目前已經使用的字節數量。固定大小緩衝區主要用來保存長度較小的回覆。

       當固定大小緩衝區空間使用殆盡或者回復消息過大,則會開始啓用可變長大小的輸出緩衝區,它的數據結構是通過鏈表來連接一個或者多個的字符串對象,具體結構如下:
在這裏插入圖片描述

4、身份驗證

       身份驗證的數據結構是:

	typedef struct redisClient{
		int authenticated;//身份驗證
	}

       如果該字段的值爲0表示客戶端未通過身份驗證,如果該值爲1表示客戶端通過身份驗證。

       

5、時間

ctime: 記錄了創建客戶端的時間,這個時間可以用來計算客戶端和服務端已經連接了多少秒

lastinteraction:記錄客戶端和服務端最後一次進行互動的時間,可以用來計算客戶端空轉時長

obuf_soft_limit_reached_time:記錄輸出緩衝區第一次到達軟性限制的時間。
       

3、客戶端創建與關閉

1、普通客戶端

       通過網絡與服務器連接的普通客戶端,在客戶端使用connect函數連接到服務器的時候,服務器就會調用連接事件處理器爲客戶端創建相應的客戶端狀態,將它添加到clients鏈表的末尾。

       客戶端被服務端關閉有很多種情況,具體查看原書。

服務器會採用兩種模式來限制客戶端緩衝區大小:

  • 硬性限制:如果緩衝區大小超出硬性限制的大小,服務端會主動關閉客戶端
  • 軟性限制:如果客戶端沒有超出硬性限制,但是在配置的軟性限制時長中,持續超出軟性限制大小,則服務端會自動關閉客戶端,否則不關閉

具體的設置可查看原書。

2、Lua腳本的僞客戶端

       服務器會在初始化時,創建負責執行Lua腳本的中包含Redis命令的僞客戶端,將這個僞客戶端關聯到服務器狀態結構中的lua_client屬性中。

       lua_client僞客戶端在服務器運行的整個生命週期都會一直存在,只有服務器被關閉的時候,這個客戶端纔會關閉。

3、AOF的僞客戶端

       服務器在載入AOF文件的時候,會創建用於執行AOF文件的Redis命令僞客戶端,並在載入完成之後,關閉這個僞客戶端。

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