【14-Redis如何處理客戶端連接】

【14-Redis如何處理客戶端連接】

【博文總目錄>>>】|【工程下載>>>】

本文檔提供有關Redis如何處理來自客戶端的信息,從網絡層來看包含以下幾點:連接、超時、緩衝區以及一些其它類似的主題。 這篇文檔所包含的信息 僅僅適用於Redis的2.6或者更高版本。

客戶端的連接的建立

Redis通過在TCP端口上進行監聽,或者Unix socket(如果啓用)的方式來接受客戶端的連接。當一個新的客戶端連接被接受執行以下操作:

  • 當Redis使用非阻塞I/O複用,客戶端socket設置爲非阻塞狀態。

  • socket TCP_NODELAY屬性被設置確保在連接中我們不會延遲。

  • 一個可讀的文件事件被創建,因而當新的數據可以被訪問時,Reids可以更快接收客戶端在socket上的查詢

當客戶端初始化後,Redis檢查我們是否還在它可以同時處理的客戶端的數量限制範圍內(這個是使用 maxclients 配置指令配置的,請參閱本文檔的下一節獲取更多的信息。

如果它因爲當前已經接受了最大數量的客戶端,無法接受當前的客戶端,Redis將嘗試發送一個錯誤給客戶端以便讓其意識到這種情況,並且立即關閉連接。即使連接被Redis立即關閉,錯誤信息也會返回給客戶端,因爲新的socket輸出緩衝區一般情況下都足夠放下錯誤信息,因而客戶端內核將處理連接錯誤。

客戶端按照什麼順序被處理

該順序是由客戶端socket文件描述符的數字大小及核心報告客戶端事件的順序決定的,因此順序可以看成不確定的。 不過Redis給客戶端提供服務時會做以下兩件事:

  • 每次它從客戶端socket讀取新東西的時候它只執行一次 read() 系統調用,以確保當我們有多臺客戶端連接時,並且有一些要求高客戶端以非常快的速率發送查詢時,其它客戶端不會因此而受到懲罰和經歷一個糟糕的延時。(譯者注:意思就是不讀取完整個socket的消息,而是每個socket輪流讀一次)

  • 當系統調用執行完,當前緩衝中的命令不管有多少都會被順序處理。

最大數量的客戶端

在Redis 2.4中,同時處理的最大客戶端數量的限制是硬編碼的。

在Redis 2.6中這個限制是動態的:默認情況下爲10000個客戶端,除非在redis.conf中配置了maxclients配置項。

Redis通過檢查內核中我們可以打開的最多的文件描述符數量,(soft limit被檢查),如果限制小於最大連接客戶端連接數,則加上32(這是Redis儲備給內部使用的文件描述符數量), 接着這個最大連接客戶端的數量將被Redis修改爲系統要求的值,以便符合在當前操作系統限制下的真正能夠處理的客戶端數量

當配置的最大客戶端數目不起作用時,則日誌將在啓動時顯示,如下面這個例子:

$ ./redis-server --maxclients 100000
[41422] 23 Jan 11:28:33.179 # Unable to set the max number of files limit to 100032 (Invalid argument), setting the max clients configuration to 10112.

當Redis配置處理客戶的具體數量時,確認操作系統中每個進程文件描述符的限制也相應地設置成最大值是個好主意。 在Linux下這些限制可以在當前的會話設置,用下面的命令在系統範圍內進行設置:

  • ulimit -Sn 100000 # 這個將只在硬限制足夠大的情況下生效`。
  • sysctl -w fs.file-max=100000`

輸出緩衝限制

Redis需要爲每個客戶端處理可變長度的輸出,因爲簡單的命令也可能產生一個需要傳送給客戶端的巨大的數據量。

也可能只是客戶端以較快的速度發送多個的命令產生的更多的輸出,當客戶端處理新消息的速度比服務端發給給它的速度還慢時,特別是Pub/Sub客戶端更是如此。

這兩個原因將導致客戶端輸出緩衝增長及內存消耗增多。因爲這個原因在默認情況下Redis爲不同類型的客戶端設置了輸出緩衝限制。當限制到達後客戶端的連接將被關閉,同時事件日誌記錄在Redis的日誌文件中。

Redis使用兩種類型的限制:

  • 硬限制是個固定的限制,當大小達到它Redis會以最快的速度關閉掉客戶端的連接。

  • 軟限制依賴於時間,例如每10秒32兆字節意味着加入客戶端擁有比32兆字節還大的輸出緩衝,持續的在10秒內超過的話連接將被關閉。

  • 不同類型的客戶端有着不同的默認限制:

  • 普通客戶端有着默認爲0的限制,這意味着沒有限制,因爲大部分的普通客戶端使用阻塞實現發送單個命令,並且在發送下一個命令前等待答覆以完全讀取,因此去關閉普通客戶端的連接始終是沒必要的。

  • Pub/Sub客戶端有默認的32兆字節的硬限制及每60秒8兆字節的軟限制。

  • 從機有默認的256兆字節的硬限制及每60秒64兆字節的軟限制。

  • 可以在運行時改變這些限制,使用CONFIG SET命令或者修改redis.conf以永久地改變它。見redis.conf中更多的關於如何設置限制的介紹。

搜索緩衝硬限制

每一個客戶端也受到搜索緩衝限制。這是個不可配置的硬限制,當客戶端搜索緩衝(這是個我們用來積累客戶端的命令的緩衝)達到1GB的時候它將關閉連接,這只是個極限限制,用來避免當客戶端或者服務端軟件出錯導致服務器崩潰的情況。

客戶端超時

最近版本的Reids在默認情況下不會在客戶端空閒很久後關閉連接;連接將永久保留。 不過假如你不喜歡這種行爲,你可以設置一個超時時間,這樣當客戶端空閒超過設置的幾秒後,客戶端連接就會被關閉。

你可以在redis.conf中配置這個限制或者簡單的使用CONFIG SET timeout 。 記住這個超時時間只適用於多個客戶端並且它不支持Pub/Sub客戶端, Pub/Sub連接是推送類型的連接,因而客戶端空閒是正常的。

即使在默認情況下連接是不受超時時間限制的,但是有兩種情況設置超時是有意義的:

關鍵任務應用,客戶端軟件可能因爲Redis連接飽和而造成出錯,造成服務中斷。

如果一個客戶端出錯使得服務器因爲空閒連接而飽和,使得無法與服務器交互,此時可以作爲一個檢錯機制去連接服務器。

超時並非非常準確:Redis避免設置計時器或者運行O(N) 算法去輪詢檢測客戶端是否超時, 所以檢查是漸近的一部分一部分完成的。這意味着有可能當超時時間設置爲10秒,客戶端的連接將在稍晚的時候被關閉,例如當很多客戶端在同一時間連接的話,可能12秒才被關閉。

客戶端命令

Redis客戶端命令允許檢查所有連接的客戶端的狀態、關掉指定的客戶端的連接、設置連接的名稱。假如你使用一定規模的Redis的話這是個很強大的排錯工具

CLIENT LIST命令用來獲得連接的客戶端列表及它們的狀態:

redis 127.0.0.1:6379> client list
addr=127.0.0.1:52555 fd=5 name= age=855 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
addr=127.0.0.1:52787 fd=6 name= age=6 idle=5 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping

在上面的示例中兩臺客戶端都連接到了Redis服務器。一部分有趣的字段的含義如下表所示:

  • addr:客戶端地址,也就是客戶端用來連接Redis服務器的IP和遠程端口號

  • fd:客戶端socket文件描述符數目。

  • name:客戶端名稱,由CLIENT SETNAME命令設置。

  • age:連接已經存在了多少秒。

  • idle:連接已經空閒了幾秒。

  • flags:客戶端的類型(N代表普通客戶端, 查看字段完整列表)。

  • omem:客戶端輸出緩衝佔用的內存量。

  • cmd:最後執行的命令。

參考CLIENT LIST文檔,查看完整的字段列表及它們的說明。

當你有了客戶端的列表, 你可以很簡單的使用CLIENT KILL命令帶上客戶端IP作爲參數來關掉連接。

命令CLIENT SETNAME和CLIENT GETNAME可以用於設置和取得連接的名稱。

發佈了534 篇原創文章 · 獲贊 1128 · 訪問量 162萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章