Redis:22---客户端API:client、monitor)
?
一、client list
client list命令能列出與Redis服務(wù)端相連的所有客戶端連接信息。例如下面代碼是在一個Redis實例上執(zhí)行client list的結(jié)果,其中每一行代表一個客戶端信息:
?
下面將選擇幾個重要的屬性進行說明,其余通過表格的形式進行展示
①標識:id、addr、fd、name
這四個屬性屬于客戶端的標識:
id:客戶端連接的唯一標識,這個id是隨著Redis的連接自增的,重啟 Redis后會重置為0
addr:客戶端連接的ip和端口
fd:socket的文件描述符,與lsof命令結(jié)果中的fd是同一個,如果fd=-1代表當(dāng)前客戶端不是外部客戶端,而是Redis內(nèi)部的偽裝客戶端
name:客戶端的名字,后面的client setName和client getName兩個命令會對其進行說明
②輸入緩沖區(qū):qbuf、qbuf-free
Redis為每個客戶端分配了輸入緩沖區(qū),它的作用是:將客戶端發(fā)送的命令臨時保存,同時Redis從會輸入緩沖區(qū)拉取命令并執(zhí)行,輸入緩沖區(qū)為客 戶端發(fā)送命令到Redis執(zhí)行命令提供了緩沖功能,如下圖所示
client list中qbuf和qbuf-free:
這兩個屬性分別代表這個緩沖區(qū)的總?cè)萘亢褪S嗳萘?/p>
Redis沒有提供相應(yīng)的配置來規(guī)定每個緩沖區(qū)的大小,輸入緩沖區(qū)會根據(jù)輸入內(nèi)容大小的不同動態(tài)調(diào)整,只是要求每個客戶端緩沖區(qū)的大小不能超過1G,超過后客戶端將被關(guān)閉
下面是Redis源碼中對于輸入緩沖區(qū)的硬編碼:
輸入緩沖使用不當(dāng)會產(chǎn)生兩個問題:
一旦某個客戶端的輸入緩沖區(qū)超過1G,客戶端將會被關(guān)閉
輸入緩沖區(qū)不受maxmemory控制,假設(shè)一個Redis實例設(shè)置了maxmemory為4G,已經(jīng)存儲了2G數(shù)據(jù),但是如果此時輸入緩沖區(qū)使用了3G,已經(jīng)超過maxmemory限制,可能會產(chǎn)生數(shù)據(jù)丟失、鍵值淘汰、OOM等情況(如下圖所示)
上圖的執(zhí)行效果如下:
上面已經(jīng)看到,輸入緩沖區(qū)使用不當(dāng)造成的危害非常大,那么造成輸入緩沖區(qū)過大的原因有哪些?
輸入緩沖區(qū)過大主要是因為Redis的處理速度跟不上輸入緩沖區(qū)的輸入速度,并且每次進入輸入緩沖區(qū)的命令包含了大量 bigkey,從而造成了輸入緩沖區(qū)過大的情況
還有一種情況就是Redis發(fā)生了阻塞,短期內(nèi)不能處理命令,造成客戶端輸入的命令積壓在了輸入緩沖區(qū), 造成了輸入緩沖區(qū)過大
那么如何快速發(fā)現(xiàn)和監(jiān)控呢?監(jiān)控輸入緩沖區(qū)異常的方法有兩種:
通過定期執(zhí)行client list命令,收集qbuf和qbuf-free找到異常的連接記錄 并分析,最終找到可能出問題的客戶端。
通過info命令的info clients模塊,找到最大的輸入緩沖區(qū),例如下面命令中的其中client_recent_max_input_buffer代表最大的輸入緩沖區(qū),例如可以設(shè)置超過10M就進行報警
上面兩種方法各有自己的優(yōu)劣勢,下圖對兩種方法進行了對比:
運維提示:輸入緩沖區(qū)問題出現(xiàn)概率比較低,但是也要做好防范,在開發(fā)中要減少bigkey、減少Redis阻塞、合理的監(jiān)控報警
③輸出緩沖區(qū):obl、oll、omem
Redis為每個客戶端分配了輸出緩沖區(qū),它的作用是:保存命令執(zhí)行的結(jié) 果返回給客戶端,為Redis和客戶端交互返回結(jié)果提供緩沖
與輸入緩沖區(qū)不同的是:
輸出緩沖區(qū)的容量可以通過參數(shù)client-outputbuffer-limit來進行設(shè)置
并且輸出緩沖區(qū)做得更加細致,按照客戶端的不同分為三種:普通客戶端、發(fā)布訂閱客戶端、slave客戶端。如下圖所示
client-output-buffer-limit格式如下。參數(shù)意義為:
<class>:客戶端類型,分為三種。a)normal:普通客戶端;b) slave:slave客戶端,用于復(fù)制;c)pubsub:發(fā)布訂閱客戶端
<hard limit>:如果客戶端使用的輸出緩沖區(qū)大于該值,客戶端會被立即關(guān)閉
<soft limit>和<soft seconds>:如果客戶端使用的輸出緩沖區(qū)超過了并且持續(xù)了秒,客戶端會被立即關(guān)閉
Redis的默認配置是:
和輸入緩沖區(qū)相同的是,輸出緩沖區(qū)也不會受到maxmemory的限制,如果使用不當(dāng)同樣會造成maxmemory用滿產(chǎn)生的數(shù)據(jù)丟失、鍵值淘汰、OOM等情況
實際上輸出緩沖區(qū)由兩部分組成:
固定緩沖區(qū)(16KB):返回比較小的執(zhí)行結(jié)果
動態(tài)緩沖區(qū):返回比較大的結(jié)果。例如大的字符串、hgetall、smembers命令的結(jié)果等,通過Redis源碼中redis.h的redisClient結(jié)構(gòu)體(Redis3.2版本變?yōu)镃lient)可以看到兩個緩沖區(qū)的實現(xiàn)細節(jié):
固定緩沖區(qū)使用的是字節(jié)數(shù)組,動態(tài)緩沖區(qū)使用的是列表。當(dāng)固定緩沖區(qū)存滿后會將Redis新的返回結(jié)果存放在動態(tài)緩沖區(qū)的隊列中,隊列中的每個對象就是每個返回結(jié)果,如下圖所示:
obl、oll、omem:
client list中的obl代表固定緩沖區(qū)的長度,oll代表動態(tài)緩沖區(qū)列表的長度,omem代表使用的字節(jié)數(shù)
例如下面代表當(dāng)前客戶端的固定緩沖區(qū)的長度為0,動態(tài)緩沖區(qū)有4869個對象,兩個部分共使用了133081288字節(jié)=126M 內(nèi)存:
監(jiān)控輸出緩沖區(qū)的方法依然有兩種:
①通過定期執(zhí)行client list命令,收集obl、oll、omem找到異常的連接記錄 并分析,最終找到可能出問題的客戶端
②通過info命令的info clients模塊,找到輸出緩沖區(qū)列表最大對象數(shù),例如(其中,client_longest_output_list代表輸出緩沖區(qū)列表最大對象數(shù)):
這兩種統(tǒng)計方法的優(yōu)劣勢和輸入緩沖區(qū)是一樣的,這里就不再贅述了
相比于輸入緩沖區(qū),輸出緩沖區(qū)出現(xiàn)異常的概率相對會比較大,那么如何預(yù)防呢?方法如下:
進行上述監(jiān)控,設(shè)置閥值,超過閥值及時處理
適當(dāng)增大slave的輸出緩沖區(qū)的,如果master節(jié)點寫入較大,slave客戶 端的輸出緩沖區(qū)可能會比較大,一旦slave客戶端連接因為輸出緩沖區(qū)溢出 被kill,會造成復(fù)制重連
限制容易讓輸出緩沖區(qū)增大的命令,例如,高并發(fā)下的monitor命令就 是一個危險的命令
及時監(jiān)控內(nèi)存,一旦發(fā)現(xiàn)內(nèi)存抖動頻繁,可能就是輸出緩沖區(qū)過大
限制普通客戶端輸出緩沖區(qū)的,把錯誤扼殺在搖籃中,例如可以進行如下設(shè)置:
④客戶端的存活狀態(tài)(age、idle)
client list中的age和idle分別代表:當(dāng)前客戶端已經(jīng)連接的時間、最近一次的空閑時間:
例如下面這條記錄代表當(dāng)期客戶端連接Redis的時間為304秒,其中空閑了0秒:
例如下面這條記錄代表當(dāng)期客戶端連接Redis的時間為8888581秒,其中空閑了8888581秒。實際上這種就屬于不太正常的情況,當(dāng)age等于idle時, 說明連接一直處于空閑狀態(tài)
演示案例
為了更加直觀地描述age和idle,下面用一個例子進行說明:
下面對代碼中的每一步進行分析,用client list命令來觀察age和idle參數(shù)的相應(yīng)變化(備注:為了與redis-cli的客戶端區(qū)分,本次測試客戶端IP地址:10.7.40.98)
1)在執(zhí)行代碼之前,client list只有一個客戶端,也就是當(dāng)前的rediscli,下面為了節(jié)省篇幅忽略掉這個客戶端。
2)使用Jedis生成了一個新的連接,并執(zhí)行g(shù)et操作,可以看到IP地址為 10.7.40.98的客戶端,最后執(zhí)行的命令是get,age和idle分別是1秒和0秒
3)休息10秒,此時Jedis客戶端并沒有關(guān)閉,所以age和idle一直在遞 增:
4)執(zhí)行新的操作ping,發(fā)現(xiàn)執(zhí)行后age依然在增加,而idle從0計算,也 就是不再閑置
5)休息5秒,觀察age和idle增加:
6)關(guān)閉Jedis,Jedis連接已經(jīng)消失:
⑤客戶端類型(flag)
client list中的flag是用于標識當(dāng)前客戶端的類型
例如flag=S代表當(dāng)前客 戶端是slave客戶端、flag=N代表當(dāng)前是普通客戶端,flag=O代表當(dāng)前客戶端 正在執(zhí)行monitor命令。下圖列出了11種客戶端類型:
序號 客戶端類型 說明 l N 普通客戶端 2 M 當(dāng)前客戶端是master節(jié)點 3 s 當(dāng)前客戶端是slave節(jié)點 4 o 當(dāng)前客戶端正在執(zhí)行monitor命令 5 x 當(dāng)前客戶端正在執(zhí)行事務(wù) 6 b 當(dāng)前客戶端正在等得阻塞事件 7 i 當(dāng)前客戶端正在等待VM IO,但是此狀態(tài)目前已經(jīng)廢棄不用 8 d 一個受監(jiān)視的鍵已被修改,EXEC命令將失敷 9 u 客戶端未被阻察 10 c 回復(fù)完整輸出后,關(guān)閉連接 11 A 盡可能快地關(guān)閉連接?
二、client setName和client getName
client setName xxclient setName
client setName用于給客戶端設(shè)置名字,這樣比較容易標識出客戶端的來源。例如將當(dāng)前客戶端命名為test_client,可以執(zhí)行如下操作:
此時再執(zhí)行client list命令,就可以看到當(dāng)前客戶端的name屬性為test_client:
client getName
client getName如果想直接查看當(dāng)前客戶端的name,可以使用client getName命令
第一次進入客戶端時,客戶端是沒有名字的,因此名字為空
更改名字之后,就可以看到更改后的名字了。例如:
client getName和setName命令可以做為標識客戶端來源的一種方式,但是通常來講,在Redis只有一個應(yīng)用方使用的情況下,IP和端口作為標識會更加清晰。當(dāng)多個應(yīng)用方共同使用一個Redis,那么此時client setName可以作為標識客戶端的一個依據(jù)
三、client kill
client kill ip:port此命令用于殺掉指定IP地址和端口的客戶端
由于一些原因(例如設(shè)置timeout=0時產(chǎn)生的長時間idle的客戶端),需要手動殺掉客戶端連接時,可以使用client kill命令
演示案例
例如左側(cè)為一個客戶端(127.0.0.1:34658),右側(cè)為一個客戶端(127.0.0.1:34660)
如果想殺掉127.0.0.1:34656的客戶端,可以執(zhí)行:
執(zhí)行命令后,client list結(jié)果只剩下了127.0.0.1:34658自己這個客戶端:
四、client pause
client pause timeout(毫秒)client pause命令用于阻塞客戶端timeout毫秒數(shù),在此期間客戶端連接將被阻塞。如下圖所示:
演示案例
例如在一個客戶端執(zhí)行下面的命令,在之后的10000毫秒內(nèi)的其他客戶端連接都會被阻塞
過一會后在另一個客戶端執(zhí)行ping命令,發(fā)現(xiàn)整個ping命令執(zhí)行了2.40秒(手動執(zhí)行redis-cli,只為了演示,不代表真實執(zhí)行時間):
該命令可以在如下場景起到作用:
client pause只對普通和發(fā)布訂閱客戶端有效,對于主從復(fù)制(從節(jié)點內(nèi)部偽裝了一個客戶端)是無效的,也就是此期間主從復(fù)制是正常進行的, 所以此命令可以用來讓主從復(fù)制保持一致
client pause可以用一種可控的方式將客戶端連接從一個Redis節(jié)點切換到另一個Redis節(jié)點
需要注意的是在生產(chǎn)環(huán)境中,暫停客戶端成本非常高
五、monitor
monitor命令用于監(jiān)控Redis正在執(zhí)行的命令?
演示案例
如下圖所示:
我們打開了兩個redis-cli,右側(cè)先執(zhí)行monitor命令,左側(cè)再執(zhí)行其他命令
可以看到monitor命令能夠監(jiān)聽其他客戶端正在執(zhí)行的命令,并記錄了詳細的時間戳
注意事項:monitor的作用很明顯,如果開發(fā)和運維人員想監(jiān)聽Redis正在執(zhí)行的命令,就可以用monitor命令,但事實并非如此美好,每個客戶端都有自己的輸出緩沖區(qū),既然monitor能監(jiān)聽到所有的命令,一旦Redis的并發(fā)量過大, monitor客戶端的輸出緩沖會暴漲,可能瞬間會占用大量內(nèi)存。
總結(jié)
以上是生活随笔為你收集整理的Redis:22---客户端API:client、monitor)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++(STL):16---deque之
- 下一篇: 给数据减肥 让MySQL数据库跑的更快