《Redis設計與實現》學習筆記-客戶端

Redis通過一個redisClient結構體來保存客戶端當前的狀態信息和執行相關功能時需要用到的數據結構,包括:

  • 套接字描述符
  • 名字
  • flags屬性
  • 輸入緩衝區
  • 輸出緩衝區
  • 當前要執行的命令與命令參數
  • 身份驗證標識
  • 時間

套接字描述符

 fd屬性保存客戶端正在使用的套接字描述符。如果客戶端是僞客戶端該屬性值爲-1,如果是普通客戶端它是一個大於-1的整數。redis在加載AOF文件或執行Lua腳本時會創建一個僞客戶端(Fake Client)。

名字

默認情況下客戶端是沒有名字的,當客戶端執行了CLIENT setname命令之後,服務器會給該客戶端設置名字,並把名字保存在redisClient結構體的name屬性中。

標誌

flags屬性,記錄了客戶端的角色,以及客戶端所處的狀態,flags可以表示單個標誌,也可以表示多個標誌比如flags= flag1 | flag2 | ...。該屬性有下列枚舉值:

  • REDIS_MASTER,主從服務器進行復制操作時,主服務器會成爲從服務器的客戶端,從服務器也會成爲主服務器的客戶端,該狀態表示客戶端代表的是一個主服務器。
  • REDIS_SLAVE,和REDIS_MASTER相對應,該狀態表示客戶端代表的是一個從服務器。
  • REDIS_PRE_PSYNC,表示客戶端是一個低於2.8的從服務器,主服務器不能使用PSYNC與這個從服務器進行同步。
  • REDIS_LUA_CLIENT,表示客戶端是一個專門處理LUA腳本的僞客戶端。
  • REDIS_MONITOR,客戶端正在執行MONITOR命令
  • REDIS_UNIX_SOCKET,服務器使用UNIX套接字來連接客戶端。
  • REDIS_BLOCKED,客戶端被BRPOP、BLPOP等命令阻塞。
  • REDIS_UNBLOCKED,客戶端已經從REDIS_BLOCKED狀態脫離。
  • REDIS_MULTI,客戶端正在執行事務。
  • REDIS_DIRTY_CAS,表示事務正在使用WATCH命令監視的數據庫鍵已經被修改。
  • REDIS_DIRTY_EXEC,事務在命令入隊時出現了錯誤,REDIS_DIRTY_CAS和REDIS_DIRTY_EXEC表示事務的安全性已經被破壞,事務會執行失敗。
  • REDIS_CLOSE_ASAP,輸出緩衝區超出了服務器允許的範圍,服務器在下一次執行serverCron函數時會關閉這個客戶端。
  • REDIS_CLOSE_AFTER_REPLY,有用戶對該客戶端執行了CLIENT KILL命令。
  • REDIS_ASKING,客戶端向集羣節點發送了ASKING命令。
  • REDIS_FORCE_AOF,強制服務器將當前命令寫入AOF文件。
  • REDIS_FORCE_REPL,強制主服務器將當前執行的命令複製給所有從服務器。
  • REDIS_MASTER_FORCE_REPLY,從服務器向主服務器發送REPLICATION ACK命令前,主服務器對應的客戶端需要打開該標識。

輸入緩衝區

querybuf屬性,sds類型。緩存客戶端的命令,緩衝區的大小根據內容的大小動態的擴大或縮小,但是最大大小不能超過1G,否則服務器會關閉客戶端。
輸出緩衝區

緩存服務器給客戶端的回覆,每個客戶端有兩個緩衝區,一個固定長度(默認16K),用來存儲長度較小的回覆,一個動態長度,用來回復長度比較大的命令,但是爲了避免緩衝區過來佔用太多資源,服務器使用兩種模式來限制緩衝區大小:
1、硬性限制:當緩衝區大小超出硬性限制大小之後,服務器馬上關閉客戶端。
2、軟性限制:當緩衝區大小超出軟性限制大小之後,但沒有超出硬性限制,服務器通過obuf_soft_limit_reached_time屬性紀錄客戶端達到軟性限制的起始時間,之後服務器會持續監視客戶端,如果輸出緩衝區一直超出軟性限制,並且持續時間超過服務器設定的時長,那麼服務器將關閉客戶端;相反地如果輸出緩衝區在指定時間內不再超出軟性限制,那麼客戶端不會被關閉,並且obuf_soft_limit_reached_time屬性值也會被清零。client-output-buffer-limit選項可以爲普通客戶端、從服務器客戶端、執行發佈與訂閱功能的客戶端設置不同的軟性限制和硬性限制,該選項格式爲client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>,以下是三個設置示例:
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
分別說明,對普通客戶端不限制輸出緩衝區大小;從服務器客戶端硬性顯示爲256M,軟性限制爲64M,軟性限制時長60s;發佈訂閱客戶端硬性限制32M,軟性限制8M,軟性限制時長60s。

當前要執行的命令與命令參數

服務端對輸入緩存區中的命令進行解析之後,把命令參數和命令參數個數分別保存在redisClient結構體的argv屬性和argc屬性。redisCommand結構對應命令,在redisCommand中會記錄該命令執行的總次數和總時長,redisClient結構體中包含了一個redisCommand類型的屬性cmd。在服務器維護了一個hash表保存所有命令,key爲命令名,value爲redisCommand結構。

身份驗證標識

authenticated屬性記錄客戶端是否通過了身份驗證,0位通過,1已通過。當客戶端未通過驗證時服務器會拒絕該客戶端除AUTH命令外的任何其它命令。

時間

客戶端還保存幾個跟時間相關的屬性。

ctime:客戶端創建的時間。

lastinteraction:客戶端最後一次與服務器互動的時間。

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

關閉普通客戶端
客戶端狀態會消耗服務端的內存資源和句柄資源,所以服務器在下列條件會關閉客戶端:

  • 客戶端進程退出或被殺死。
  • 客戶端向服務器發送了不符合格式的命令。
  • 客戶端稱爲CLIENT KILL命令的目標。
  • 用戶爲服務器設置了timeout選項,那麼當客戶端的空轉時長超過timeout時,客戶端會被關閉,不過也有例外,比如當客戶端被BLPOP等命令阻塞或正在執行發佈訂閱命令,這時即使空轉時間超過了timeout也不會關閉連接。
  • 客戶端發送的命令請求的大小超出了輸入緩衝區大小(默認1G)。
  • 客戶端的命令回覆大小超過了輸出緩衝區的硬性限制,或者超出軟性限制達到一定的時長。

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