Redis 案例實戰分析

【1】案例一現象:
生產系統剛開始運行階段,系統穩定。可是運行了一段時間後,發現部分時間段系統接口響應變慢。查看客戶端日誌常常會出現以下錯誤:java

redis.clients.jedis.exception.JedisConnectionException:java.net.SocketTimeoutException:Read time out
問題定位:執行 slowlog 查看慢查詢日誌,發現大量的 keys 命令操做,keys 命令在大量併發狀況下性能很是差,生產環境,儘可能避免使用 keys,接下來找出使用 keys 的代碼作優化,直到 time out 問題解決。redis

192.168.17.46:6386> slowlog get
 1) 1) (integer) 22
    2) (integer) 1563344158
    3) (integer) 10193
    4) 1) "SET"
       2) "getBatchChapterFiles"
       3) "\x0b\xfa\529:\t489761532B\x02-1J\t48976181... (1293 more bytes)"
 2) 1) (integer) 21
    2) (integer) 1545403066
    3) (integer) 10915
    4) 1) "GET"
       2) "getVolumeChapters#data"

【2】案例二現象:
生產環境長時間的運行後,常常會有接口返回數據失敗的狀況,或者是從監控上發現數據庫壓力某一時間暴增。查看客戶端日誌發現以下錯誤:
redis.clients.jedis.exceptions.JedisConnectionException:Cloud not get a resource from the pool數據庫

在redis日誌裏面發現報錯:
[2489] 02 Jun 10:43:42 # Error allocating resoures for the client服務器

問題定位:執行 client list 命令,發現大量的 client 的 idle 時間特別長。檢查配置發現 timeout 和 tcp-keepalive(心跳檢測) 均爲啓用(均爲0),Redis 服務端沒有有效的機制來確保服務端鏈接是否已經失效。當服務器與客戶端網絡發生閃斷,致使tcp中斷,這種狀況下的 client 將會一直被 redis 服務端所持有,就會出現 idle(空閒)時間特長的 client 鏈接。
解決辦法:設置 timeout 和 tcp-keepalive 來清理失效的鏈接。網絡

redis/bin>redis-cli -h 192.168.17.46 -p 6386 info Clients
# Clients
connected_clients:5000                      ---------------偏大
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

192.168.17.46:6386> CONFIG GET timeout 
1) "timeout"
2) "0"

192.168.17.46:6386> CONFIG GET tcp-keepalive
1) "tcp-keepalive"
2) "0"
192.168.17.46:6386> client list
id=612260747 addr=192.168.17.92:53069 fd=806 name= age=114 idle=21 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
id=612260593 addr=192.168.41.44:38248 fd=381 name= age=131 idle=61 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get

字段定義
addr : 客戶端的地址和端口
fd : 套接字所使用的文件描述符
age : 以秒計算的已鏈接時長
idle : 以秒計算的空閒時長
flags : 客戶端 flag
db : 該客戶端正在使用的數據庫 ID
sub : 已訂閱頻道的數量
psub : 已訂閱模式的數量
multi : 在事務中被執行的命令數量
qbuf : 查詢緩衝區的長度(字節爲單位, 0 表示沒有分配查詢緩衝區)
qbuf-free : 查詢緩衝區剩餘空間的長度(字節爲單位, 0 表示沒有剩餘空間)
obl : 輸出緩衝區的長度(字節爲單位, 0 表示沒有分配輸出緩衝區)
oll : 輸出列表包含的對象數量(當輸出緩衝區沒有剩餘空間時,命令回覆會以字符串對象的形式被入隊到這個隊列裏)
omem : 輸出緩衝區和輸出列表佔用的內存總量
events : 文件描述符事件
cmd : 最近一次執行的命令併發

【3】案例三現象:
Redis 忽然間不能訪問,返回以下錯誤:tcp

redis.client.jedis.exception.JedisDataException:MISCONF Redis is configured to save RDB snapshots,
but is currently not able to persist on disk.Commands that may modify the data set are disabled.
Please check Redis logs for details about the error
問題定位:查看 redis 日誌,發現以下錯誤:Cant save in background:fork:Cannot allocate memory Redis在保存內存的數據到磁盤時,爲了防止主線程假死,會Fork 一個子進程來完成這個保存操做,這個Fork 的子進程須要分配與主進程相同的內存,這時候就至關於須要的內存翻倍了。若是這時候可用內存不足以分配須要的內存,將會致使Fork 子進程失敗而沒法將數據持久化到磁盤。修改Linux內核參數 vm.overcommit_memeory=1(表示內核容許分配全部的物理內存,而無論當前的內存狀態如何) 問題即可解決。ide

192.168.17.46:6386> CONFIG GET logfile
1) "logfile"
2) "/home/redis02/redis/log/6386.log"
相關文章
相關標籤/搜索