這篇文章給大家分享的是有關(guān)redis處理客戶端連接的方法的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。
旌德網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,旌德網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為旌德上千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站建設(shè)要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的旌德做網(wǎng)站的公司定做!
Redis如何處理客戶端連接 本文主要介紹了 Redis 處理客戶端連接的一些內(nèi)部實(shí)現(xiàn)機(jī)制,包括連接處理、超時(shí)、緩沖區(qū)等一系列內(nèi)容。下面創(chuàng)新互聯(lián)小編來講解下Redis如何處理客戶端連接?
Redis如何處理客戶端連接
Redis 通過監(jiān)聽一個(gè) TCP 端口或者 Unix socket 的方式來接收來自客戶端的連接,當(dāng)一個(gè)連接建立后,Redis 內(nèi)部會(huì)進(jìn)行以下一些操作:
首先,客戶端 socket 會(huì)被設(shè)置為非阻塞模式,因?yàn)?Redis 在網(wǎng)絡(luò)事件處理上采用的是非阻塞多路復(fù)用模型。
然后為這個(gè)socket 設(shè)置 TCP_NODELAY 屬性,禁用 Nagle 算法
然后創(chuàng)建一個(gè) readable 的文件事件用于監(jiān)聽這個(gè)客戶端 socket 的數(shù)據(jù)發(fā)送
當(dāng)客戶端連接被初始化后,Redis 會(huì)查看目前的連接數(shù),然后對(duì)比配置好的 maxclients 值,如果目前連接數(shù)已經(jīng)達(dá)到最大連接數(shù) maxclients 了,那么說明這個(gè)連接不能再接收,Redis 會(huì)直接返回客戶端一個(gè)連接錯(cuò)誤,并馬上關(guān)閉掉這個(gè)連接。
服務(wù)端處理順序
如果有多個(gè)客戶端連接上 Redis,并且都向 Redis 發(fā)送命令,那么 Redis 服務(wù)端會(huì)先處理哪個(gè)客戶端的請(qǐng)求呢?答案其實(shí)并不確定,主要與兩個(gè)因素有關(guān),一是客戶端對(duì)應(yīng)的 socket 對(duì)應(yīng)的數(shù)字的大小,二是 kernal 報(bào)告各個(gè)客戶端事件的先后順序。
Redis 處理一個(gè)客戶端傳來數(shù)據(jù)的步驟如下:
它對(duì)觸發(fā)事件的 socket 調(diào)用一次 read(),只讀一次(而不是把這個(gè) socket 上的消息讀完為止),是為了防止由于某個(gè)別客戶端持續(xù)發(fā)送太多命令,導(dǎo)致其它客戶端的請(qǐng)求長時(shí)間得不到處理的情況。
當(dāng)然,當(dāng)這一次 read() 調(diào)用完成后,它里面無論包含多少個(gè)命令,都會(huì)被一次性順序地執(zhí)行。這樣就保證了對(duì)各個(gè)客戶端命令的公平對(duì)待。
關(guān)于最大連接數(shù) maxclients
在 Redis2.4 中,最大連接數(shù)是被直接硬編碼在代碼里面的,而在2.6版本中這個(gè)值變成可配置的。maxclients 的默認(rèn)值是 10000,你也可以在 redis.conf 中對(duì)這個(gè)值進(jìn)行修改。
當(dāng)然,這個(gè)值只是 Redis 一廂情愿的值,Redis 還會(huì)照顧到系統(tǒng)本身對(duì)進(jìn)程使用的文件描述符數(shù)量的限制。在啟動(dòng)時(shí) Redis 會(huì)檢查系統(tǒng)的 soft limit,以查看打開文件描述符的個(gè)數(shù)上限。如果系統(tǒng)設(shè)置的數(shù)字,小于咱們希望的最大連接數(shù)加32,那么這個(gè) maxclients 的設(shè)置將不起作用,Redis 會(huì)按系統(tǒng)要求的來設(shè)置這個(gè)值。(加32是因?yàn)?Redis 內(nèi)部會(huì)使用最多32個(gè)文件描述符,所以連接能使用的相當(dāng)于所有能用的描述符號(hào)減32)。
當(dāng)上面說的這種情況發(fā)生時(shí)(maxclients 設(shè)置后不起作用的情況),Redis 的啟動(dòng)過程中將會(huì)有相應(yīng)的日志記錄。比如下面命令希望設(shè)置最大客戶端數(shù)量為100000,所以 Redis 需要 100000+32 個(gè)文件描述符,而系統(tǒng)的最大文件描述符號(hào)設(shè)置為10144,所以 Redis 只能將 maxclients 設(shè)置為 10144 – 32 = 10112。
$ ./redis-server --maxclients 100000
Redis如何處理客戶端連接
[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.
所以說當(dāng)你想設(shè)置 maxclients 值時(shí),最好順便修改一下你的系統(tǒng)設(shè)置,當(dāng)然,養(yǎng)成看日志的好習(xí)慣也能發(fā)現(xiàn)這個(gè)問題。
具體的設(shè)置方法就看你個(gè)人的需求了,你可以只修改此次會(huì)話的限制,也可以直接通過sysctl 修改系統(tǒng)的默認(rèn)設(shè)置。如:
ulimit -Sn 100000 # This will only work if hard limit is big enough.
sysctl -w fs.file-max=100000
輸出緩沖區(qū)大小限制
對(duì)于 Redis 的輸出(也就是命令的返回值)來說,其大小經(jīng)常是不可控的,可能是一個(gè)簡單的命令,能夠產(chǎn)生體積龐大的返回?cái)?shù)據(jù)。另外也有可能因?yàn)閳?zhí)行命令太多,產(chǎn)生的返回?cái)?shù)據(jù)的速率超過了往客戶端發(fā)送的速率,這時(shí)也會(huì)產(chǎn)生消息堆積,從而造成輸出緩沖區(qū)越來越大,占用過多內(nèi)存,甚至導(dǎo)致系統(tǒng)崩潰。
所以 Redis 設(shè)置了一些保護(hù)機(jī)制來避免這種情況的出現(xiàn),這些機(jī)制作用于不同種類的客戶端,有不同的輸出緩沖區(qū)大小限制,限制方式有兩種:
一種是大小限制,當(dāng)某一個(gè)客戶端的緩沖區(qū)超過某一大小時(shí),直接關(guān)閉掉這個(gè)客戶端連接
另一種是當(dāng)某一個(gè)客戶端的緩沖區(qū)持續(xù)一段時(shí)間占用空間過大時(shí),也直接關(guān)閉掉客戶端連接
對(duì)于不同客戶端的策略如下:
對(duì)普通客戶端來說,限制為0,也就是不限制,因?yàn)槠胀蛻舳送ǔ2捎米枞降南?yīng)答模式,如:發(fā)送請(qǐng)求,等待返回,再發(fā)請(qǐng)求,再等待返回。這種模式通常不會(huì)導(dǎo)致輸出緩沖區(qū)的堆積膨脹。
對(duì)于 Pub/Sub 客戶端來說,大小限制是32m,當(dāng)輸出緩沖區(qū)超過32m時(shí),會(huì)關(guān)閉連接。持續(xù)性限制是,當(dāng)客戶端緩沖區(qū)大小持續(xù)60秒超過8m,也會(huì)導(dǎo)致連接關(guān)閉。
而對(duì)于 Slave 客戶端來說,大小限制是256m,持續(xù)性限制是當(dāng)客戶端緩沖區(qū)大小持續(xù)60秒超過64m時(shí),關(guān)閉連接。
上面三種規(guī)則都是可配置的??梢酝ㄟ^ CONFIG SET 命令或者修改 redis.conf 文件來配置。
輸入緩沖區(qū)大小限制
Redis 對(duì)輸入緩沖區(qū)大小的限制比較暴力,當(dāng)客戶端傳輸?shù)恼?qǐng)求大小超過1G時(shí),服務(wù)端會(huì)直接關(guān)閉連接。這種方式可以有效防止一些客戶端或服務(wù)端 bug 導(dǎo)致的輸入緩沖區(qū)過大的問題。
Client 超時(shí)
對(duì)當(dāng)前的 Redis 版本來說,服務(wù)端默認(rèn)是不會(huì)關(guān)閉長期空閑的客戶端的。但是你可以修改默認(rèn)配置來設(shè)置你希望的超時(shí)時(shí)間。比如客戶端超過多長時(shí)間無交互,就直接關(guān)閉。同理,這也可以通過 CONFIG SET 命令或者修改 redis.conf 文件來配置。
值得注意的是,超時(shí)時(shí)間的設(shè)置,只對(duì)普通客戶端起作用,對(duì) Pub/Sub 客戶端來說,長期空閑狀態(tài)是正常的。
另外,實(shí)際的超時(shí)時(shí)間可能不會(huì)像設(shè)定的那樣精確,這是因?yàn)?Redis 并不會(huì)采用計(jì)時(shí)器或者輪訓(xùn)遍歷的方法來檢測(cè)客戶端超時(shí),而是通過一種漸近式的方式來完成,每次檢查一部分。所以導(dǎo)致的結(jié)果就是,可能你設(shè)置的超時(shí)時(shí)間是10s,但是真實(shí)執(zhí)行的時(shí)間是超時(shí)12s后客戶端才被關(guān)閉。
CLIENT 命令
Redis 的 CLIENT 命令能夠?qū)崿F(xiàn)三種功能:檢查連接的狀態(tài),殺掉某個(gè)連接以及為連接設(shè)置名字。
CLIENT LIST 命令能夠獲取當(dāng)前所有客戶端的狀態(tài),使用方法如下:
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 有兩個(gè)客戶端連接,每一行表示一個(gè)連接的各項(xiàng)信息:
addr: 客戶端的TCP地址,包括IP和端口
fd: 客戶端連接 socket 對(duì)應(yīng)的文件描述符句柄號(hào)
name: 連接的名字,默認(rèn)為空,可以通過 CLIENT SETNAME 設(shè)置
age: 客戶端存活的秒數(shù)
idle: 客戶端空閑的秒數(shù)
flags: 客戶端的類型 (N 表示普通客戶端,更多類型見 http://redis.io/commands/client-list)
omem: 輸出緩沖區(qū)的大小
cmd: 最后執(zhí)行的命令名稱
你可以查看 CLIENT LIST 的文檔來具體查看所有輸出的含義。
當(dāng)你通過上面命令獲取到客戶端列表后,就可以通過 CLIENT KILL 命令來殺死指定的連接了。CLIENT KILL 的參數(shù)就是上面的 addr 值。
如上面提到的 CLIENT SETNAME 和 CLIENT GETNAME 可以用來為一個(gè)連接設(shè)置一個(gè)名字。
感謝各位的閱讀!關(guān)于“Redis處理客戶端連接的方法”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!