D炸天的Redis,該如何監(jiān)控?
本文重點(diǎn)講述Redis的哪些metrics需要重要監(jiān)控(篇幅有限,不能涵蓋所有),以及我們?nèi)绾潍@取這些metrics數(shù)據(jù)。從而確保對我們應(yīng)用至關(guān)重要的Redis是否健康運(yùn)行,以及當(dāng)出現(xiàn)問題時(shí)能及時(shí)通知我們。
吞吐量
吞吐量包括Redis實(shí)例歷史總吞吐量,以及每秒鐘的吞吐量??梢酝ㄟ^命令info stats中的幾個(gè)得到我們要監(jiān)控的吞吐量:
- # 從Rdis上一次啟動以來總計(jì)處理的命令數(shù)
- total_commands_processed:2255
- # 當(dāng)前Redis實(shí)例的OPS
- instantaneous_ops_per_sec:12
- # 網(wǎng)絡(luò)總?cè)肓?nbsp;
- total_net_input_bytes:34312
- # 網(wǎng)絡(luò)總出量
- total_net_output_bytes:78215
- # 每秒輸入量,單位是kb/s
- instantaneous_input_kbps:1.20
- # 每秒輸出量,單位是kb/s
- instantaneous_output_kbps:2.62
內(nèi)存利用率
Redis高性能保障的一個(gè)重要資源就是足夠的內(nèi)存。Used memory表示Redis已經(jīng)分配的總內(nèi)存大小。我們可以通過info memory命令獲取所有內(nèi)存利用了相關(guān)數(shù)據(jù),其結(jié)果如下:
- 127.0.0.1:6379> info memory
- # Memory
- used_memory:1007888
- used_memory_human:984.27K
- used_memory_rss:581632
- used_memory_rss_human:568.00K
- used_memory_peak:1026064
- used_memory_peak_human:1002.02K
- total_system_memory:8589934592
- total_system_memory_human:8.00G
- used_memory_lua:37888
- used_memory_lua_human:37.00K
- maxmemory:0
- maxmemory_human:0B
- maxmemory_policy:noeviction
- mem_fragmentation_ratio:0.58
- mem_allocator:libc
需要注意的是,如果我們沒有配置maxmemory(可以通過config get/set maxmemory查詢并在不重啟Redis實(shí)例的前提下設(shè)置),那么Redis可能會耗盡服務(wù)器所有可用內(nèi)存,從而可能導(dǎo)致swap甚至被系統(tǒng)kill掉。
所以建議方案是配置maxmemory,并且配置maxmemory-policy(不要是默認(rèn)的noviction)。即使這樣還不夠,因?yàn)槿绻l(fā)比較大的話,緩存逐除策略可能會忙不過來,從而依然會有無法操作Redis的錯(cuò)誤。所以強(qiáng)烈建議:在配置maxmemory-policy和maxmemory雙策略的前提下,對used_memory進(jìn)行監(jiān)控,建議是maxmemory的90%。例如maxmemory為10G,那么當(dāng)used_memory達(dá)到9G的時(shí)候,進(jìn)行相關(guān)預(yù)警,從而準(zhǔn)備擴(kuò)容。
緩存命中率
緩存命中率表示緩存的使用效率,很明顯,它通過公式:HitRate = keyspace_hits / (keyspace_hits + keyspace_misses) 計(jì)算得到。在info stats中恰好有這些數(shù)據(jù):
- keyspace_hits:17
- keyspace_misses:1
緩存命中率建議不需要低于90%,越高越好。這個(gè)命中率越低,表示越多對緩存中沒有的KEY進(jìn)行了訪問??赡苁沁@些KEY已經(jīng)過期、已經(jīng)被刪除、已經(jīng)被evict、或者壓根兒不存在的KEY非法訪問等原因。
緩存命中率越低,或?qū)е略蕉嗟恼埱蟠┩窻edis從MySQL(或者其他速度遠(yuǎn)比Redis慢的存儲服務(wù))獲取數(shù)據(jù),從而導(dǎo)致越多的請求有更大的延遲,導(dǎo)致API耗時(shí)增加,影響用戶體驗(yàn)。
如果是內(nèi)存不足,那么需要擴(kuò)容。例如info stats中的evicted_keys不為0,或者used_memory達(dá)到了內(nèi)存上限。如果是用法問題,那么需要優(yōu)化代碼。
客戶端連接數(shù)
這個(gè)值可以通過info clients中的字段connected_clients獲取,它會受到操作系統(tǒng)ulimit和redis的maxclients配置的限制。如果Rdis客戶端中報(bào)出獲取不到連接數(shù)的錯(cuò)誤(異常信息:ERR max number of clients reached),需要排查這兩個(gè)地方是否限制了客戶端連接數(shù)。當(dāng)然,也可能還有其他其他原因,比如客戶端BUG導(dǎo)致連接沒有釋放等。
慢日志
Redis和其他關(guān)系型數(shù)據(jù)庫一樣,也有命令執(zhí)行的慢日志。慢日志收集的閾值可通過config set slowlog-log-slower-than配置,單位是微妙。默認(rèn)是10000微秒,即10ms,筆者認(rèn)為這個(gè)默認(rèn)值設(shè)置的太大,建議將其調(diào)整到1ms。因?yàn)檫@個(gè)慢日志統(tǒng)計(jì)的時(shí)間只是命令執(zhí)行的時(shí)間,不包括客戶端到服務(wù)端的時(shí)間,以及命令在服務(wù)端隊(duì)列中的等待時(shí)間。以Rdis的性能來說,正常的執(zhí)行時(shí)間一般在10微秒級別(單實(shí)例OPS可以達(dá)到10W)。所以,設(shè)置slowlog-log-slower-than為1000,即1毫秒已經(jīng)綽綽有余:
- redis> slowlog get
- 1) 1) (integer) 21 # Unique ID
- 2) (integer) 1439419285 # Unix timestamp
- 3) (integer) 19125 # Execution time in microseconds
- 4) 1) "keys" # Command
- ... ...
另外,可以通過命令slowlog reset清理掉所有保存的慢日志。
說明:Redis4.0或者更高的版本多了兩個(gè)額外的字段:客戶端IP端口以及客戶端名稱。客戶端名稱可以通過命令:client setname 進(jìn)行自定義設(shè)置。
延遲監(jiān)控
任何環(huán)境都會存在延遲,關(guān)鍵是看延遲是否在我們能接受的范圍內(nèi)。一些影響會比較大的高延遲,可能會有很多的原因,例如:網(wǎng)絡(luò)原因、計(jì)算密集型命令、時(shí)間復(fù)雜度為O(n)的命令、系統(tǒng)內(nèi)存不夠發(fā)生SWAP等。
Redis提供了非常多的工具來定位這些延遲問題。
- slowlog
即慢日志,前面已經(jīng)有詳細(xì)的說明,這是非常重要的監(jiān)控項(xiàng)。Redis是單線程處理命令,所以如果有執(zhí)行時(shí)間比較長的命令,就會導(dǎo)致其他命令阻塞。
- latency monitor
latency monitoring是從Redis2.8.13開始引入的新特性,用來幫組定位延遲問題,它能夠記錄Redis產(chǎn)生延遲問題的可能原因。需要通過如下命令來開啟這個(gè)特性,當(dāng)然,也可以在redis.conf中配置:
- config set latency-monitor-threshold ms
接下來可以通過如下命令檢查是否開啟成功:
- redis> latency latest
- 1) 1) "command" # Event name
- 2) (integer) 1539479413 # Unix timestamp
- 3) (integer) 381 # Latency of latest event
- 4) (integer) 6802 # All time maximum latency
- # 還可以查看引起延遲的歷史命令:
- redis> latency history command
- # 延遲診斷
- redis> latency doctor
- intrinsic latency
Redis服務(wù)內(nèi)部延遲。通過執(zhí)行命令:src/redis-cli --intrinsic-latency sec得到延遲統(tǒng)計(jì)數(shù)據(jù),它的結(jié)果可以用來衡量Redis服務(wù)內(nèi)部延遲時(shí)間。這個(gè)命令的總運(yùn)行時(shí)間由最后一個(gè)參數(shù)sec決定。通過這個(gè)命令,我們能判定搭建的Redis服務(wù)性能是否正常。命令使用參考:
- afeideMBP:redis-3.2.11 litian$ src/redis-cli --intrinsic-latency 5
- Max latency so far: 1 microseconds.
- Max latency so far: 4 microseconds.
- Max latency so far: 11 microseconds.
- Max latency so far: 17 microseconds.
- Max latency so far: 115 microseconds.
- Max latency so far: 648 microseconds.
- 99087235 total runs (avg latency: 0.0505 microseconds / 50.46 nanoseconds per run).
- Worst run took 12842x longer than the average latency.
- network latency
前面使用--intrinsic-latency可以檢查Redis內(nèi)部延遲情況,但是因?yàn)镽edis是遠(yuǎn)程緩存服務(wù),命令執(zhí)行時(shí)從客戶端到服務(wù)端的時(shí)間延遲并沒有得到統(tǒng)計(jì)。而且相比起內(nèi)部延遲,Redis客戶端到服務(wù)端的網(wǎng)絡(luò)延遲影響更大,不確定因素也更多,比如網(wǎng)絡(luò)抖動等。Redis也提供了相關(guān)命令來統(tǒng)計(jì)網(wǎng)絡(luò)延遲情況,這個(gè)命令的本質(zhì)就是通過ping你的Redis服務(wù)端來衡量響應(yīng)時(shí)間。使用方法如下:
- afeideMBP:redis-3.2.11 litian$ src/redis-cli --latency -h 127.0.1.168 -p 6379
- min: 0, max: 1, avg: 0.18 (174 samples)
注意:這個(gè)命令會一直運(yùn)行下去,除非你主動終止它。
cachecloud
通過上文我們可知,大部分的metrics都可以通過info命令得到,毫不夸張的說,info命令是窺探Redis最好的方法。所以,要監(jiān)控要Redis,我們一定要熟悉info結(jié)果中每個(gè)字段的含義,然后結(jié)合自己的業(yè)務(wù)有針對性的定制化最適合我們業(yè)務(wù)的監(jiān)控方案。但是info命令只是一個(gè)單機(jī)版的命令,而一般我們的生產(chǎn)環(huán)境是redis集群。那么我們需要一個(gè)專業(yè)的監(jiān)控服務(wù)來將整個(gè)redis集群的metric聚合起來方便我們查看,筆者在這里強(qiáng)烈推薦cachecloud。GIthub地址為:https://github.com/sohutv/cachecloud,用過的都說好,嘿嘿~