一. 概述 Redis伺服器是可以與多個客戶端建立網路連接,每個客戶端可以向伺服器發送命令請求,而伺服器則接收並處理客戶端發送的命令請求,並向客戶端返回命令回覆。通過使用I/O多路復用技術實現的文件事件處理器,Redis伺服器使用單進程單線程的方式來處理命令請求,並與多個客戶端進行網路通信。 1.1 ...
一. 概述
Redis伺服器是可以與多個客戶端建立網路連接,每個客戶端可以向伺服器發送命令請求,而伺服器則接收並處理客戶端發送的命令請求,並向客戶端返回命令回覆。通過使用I/O多路復用技術實現的文件事件處理器,Redis伺服器使用單進程單線程的方式來處理命令請求,並與多個客戶端進行網路通信。
1.1 偽客戶端和普通客戶端
對於每個與伺服器進行連接的客戶端,伺服器都為這些客戶端建立了相應的redis.h/redisClient結構(客戶端狀態),這個結構保存了客戶端當前的狀態信息。根據客戶端類型的不同,分為偽客戶端和普通客戶端。偽客戶端處理的命令請求來源於AOF文件或者Lua腳本,而不是網路,這種客戶端不需要套接字連接。普通客戶端使用套接字與伺服器進行通信,下麵腳本顯示了全部的普通客戶端:
127.0.0.1:6379> client list id=2 addr=127.0.0.1:45090 fd=8 name= age=95 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client id=3 addr=127.0.0.1:45092 fd=9 name= age=3 idle=3 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=command
上面腳本,當fd為-1時,就是一個偽客戶端。普通客戶端的fd都大於0。name代表客戶端名稱,預設為空,可以用client setname命令來設置一個客戶端的名字,例如給當前客戶端設置名稱,以下腳本:
127.0.0.1:6379> client setname client1 OK 127.0.0.1:6379> client list id=2 addr=127.0.0.1:45090 fd=8 name=client1 age=414 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0
events=r cmd=client id=3 addr=127.0.0.1:45092 fd=9 name= age=322 idle=322 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0
events=r cmd=command
1.2 flags標誌
flags記錄了客戶端的角色(role),以及客戶端目前所處的狀態,flags屬性的值可以是單個標誌,也可以是多個標誌的二進位。客戶端 flag 可以由以下部分組成:
屬性值 |
描述 |
O |
客戶端是 MONITOR 模式下的附屬節點(slave) |
S |
客戶端是一般模式下(normal)的附屬節點 |
M |
客戶端是主節點(master) |
x |
客戶端正在執行事務 |
b |
客戶端正在等待阻塞事件 |
i |
客戶端正在等待 VM I/O 操作(已廢棄 |
c |
在將回覆完整地寫出之後,關閉鏈接 |
u |
客戶端未被阻塞(unblocked) |
N |
未設置任何 flag |
r |
客戶端套接字(在事件 loop 中)是可讀的(readable) |
w |
客戶端套接字(在事件 loop 中)是可寫的(writeable) |
1.3 輸入緩衝區qbuf 與輸出緩衝區 obl
(1)客戶端狀態的輸入緩衝區用於保存客戶端發送的命令請求,如set key value, 輸入緩衝區的大小會根據輸入內容動態地縮小或擴大,但它的最大空間不超過1GB,否則伺服器將關閉這個客戶端。
(2)當服務端執行命令回覆,會被保存在客戶端狀態的輸出緩衝區中,每個客戶端都有兩個輸出緩衝區可用,一個緩衝區大小是固定的,另一個緩衝區的大小是可變的。固定大小的緩衝區用於保存回覆信息長度比較小的,比如OK,簡短的字元串值,整數值,錯誤回覆等。可變大小的緩衝區用於保存長度比較大的,比如一個非常長的字元串值,或一個由很多項組成的列表,或一個包含了很多元素的集合等。 固定大小的緩衝區預設為16kb。可變大小緩衝區不能超過伺服器設置的硬性限制值,本篇最後client-output-buffer-limit時有講。 omem表示輸出緩存的記憶體占用量。
1.4 身份驗證
客戶端狀態的authenticated屬性用於記錄客戶端是否通過了身份驗證,當redisClinet結構下的authenticated屬性為值0時,代表客戶端未通過身份驗證,安裝redis服務後,預設是沒有密碼,也就是不需要身份驗證,通過設置config set requirepass xxx 來設置密碼。通過auth xx來驗證密碼是否正確。下麵腳本是設置密碼和驗證密碼是否正確:
127.0.0.1:6379> config set requirepass 123456 OK 127.0.0.1:6379> auth 123456 OK
當沒有通過驗證時,使用ping命令顯示信息如下, 退出客戶端,重啟登錄使用-a 參數輸入密碼,再次使用ping命令,驗證成功,如下腳本:
127.0.0.1:6379> ping (error) NOAUTH Authentication required. [root@xuegod64 ~]# redis-cli -a 123456 127.0.0.1:6379> ping PONG
1.5 時間
客戶端還有幾個和時間有關的屬性,一是age屬性,它記錄了創建客戶端的時間,這個時間可以用來計算客戶端與伺服器已經連接了多少秒。二是idle空轉時間,即客戶端與伺服器最後一次進行互動以來,已經過去了多少秒。
1.6 客戶端的創建與關閉
如果客戶端是通過網路連接與伺服器進行連接的普通客戶端,那麼在客戶端使用connect函數連接到伺服器時,伺服器就會調用連接事件處理器(上篇簡單講到的文件事件處理器),為客戶端創建相應的客戶端狀態,並將這個新狀態添加到伺服器狀態結構reddisServer結構的clients數組鏈表的末尾。對於關閉普通客戶端,人為可以使用clinet kill命令,來關閉,如下腳本所示:
127.0.0.1:6379> client list id=4 addr=127.0.0.1:45094 fd=8 name= age=6141 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client id=6 addr=127.0.0.1:45098 fd=9 name= age=5966 idle=22 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client 127.0.0.1:6379> client kill id 6 (integer) 1 127.0.0.1:6379> client list id=4 addr=127.0.0.1:45094 fd=8 name= age=6179 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
如果用戶為伺服器設置了timeout選項,那麼當客戶端的空轉時間(idle)超過timeout選項設置的值時,客戶端將關閉。如果輸入緩衝區占用空間超過1GB時,客戶端將關閉。
對於輸出緩衝區的大小,達到限制時,客戶端也將關閉。為了避免客戶端的回覆過大,占用過多的伺服器資源,伺服器會時刻檢查客戶端的輸出緩衝區的大小,併在緩衝區的大小超出範圍時,執行相應的限制操作。伺服器使用兩種模式來限制客戶端輸出緩衝區的大小:
(1) 硬性限制(hard limit):如果輸出緩衝區的大小超過了硬性限制所設置的大小,那麼伺服器立即關閉客戶端。
(2) 軟性限制(soft limit): 如果輸出緩衝區的大小超出了軟性限制所設置的大小,並且占用的時長大於> 設置的總時長,那麼伺服器將關閉客戶端。
使用client-output-buffer-limit選項可以為普通客戶端,從伺服器客戶端,執行發佈訂閱功能的客戶端分別設置不同的軟性限制和硬性限制,預設設置如下:
1) "client-output-buffer-limit" 2) "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"
normal是普通客戶端:軟性限制和硬性限制都沒有限制。
slave是從伺服器客戶端:硬性限制是268435456, 軟性限制是67108864 並且時長為60秒。
pubsub是發佈訂閱功能的客戶端: 硬性限制是33554432, 軟性限制是8388608並且時長為60秒。
1.7 偽客戶端的創建與關閉
對於Lua腳本的偽客戶端,在伺服器初始化時創建,這個偽客戶端在伺服器運行的整個生命期中會一直存在,只有伺服器關閉時,這個客戶端才會被關閉。
對於AOF文件的偽客戶端,伺服器在載入AOF文件時,會創建偽客戶端,併在載入完成之後,關閉這個偽客戶端。