一、慢查詢
因為 Redis 是單線程的,大量的慢查詢可能會導緻 redis-server 阻塞,可以通過 slowlog get n 擷取慢日志,檢視詳情情況。
二、bigkey 大對象
bigkey 大對象可能會導緻的問題包括:
- 記憶體空間不均勻(平衡),例如在 Redis Cluster 中,bigkey 會造成節點的記憶體空間使用不均勻。
- 逾時阻塞:由于Redis 單線程的特性,操作 bigkey 比較耗時,也就意味着阻塞 Redis 的可能性增大。
- 網絡阻塞:每次擷取 bigkey 産生的網絡流量較大,假設一個 bigkey 為 1MB,每次通路量為 1000,那麼每秒産生 1000MB 的流量,對于普通的千兆網卡(按照位元組算是128MB/s)的伺服器簡直是滅頂之災。
Redis學習六(Redis 阻塞的原因及其排查方向).
bigkey 的存在并不是完全緻命的,如果這個 bigkey 存在但是幾乎不被通路,那麼隻有記憶體空間不均勻的問題存在,相對于另外兩個問題沒有那麼重要緊急,但是如果 bigkey 是一個熱點key(頻繁通路),那麼其帶來的危害不可想象,是以在實際開發和運維時一定要密切關注 bigkey 的存在。
可以通過 redis-cli -h {ip} -p {port} bigkeys 發現大對象。
三、swap
因為 Redis 的資料放在記憶體中,是以存放資料量的多少取決于記憶體的多少。
如果一個 Redis 執行個體的記憶體使用率超過可用最大記憶體(used_memory > 可用最大記憶體),那麼作業系統開始進行記憶體和 swap 空間交換,把記憶體中舊的或不再使用的内容寫入硬碟上(硬碟上的這塊空間叫 Swap 分區),以便騰出新的實體記憶體給新頁使用。
在硬碟上進行讀寫操作要比記憶體上慢了近5個數量級 —— 記憶體是 0.1μs 機關、硬碟是 10ms。如果 Redis 程序上發生記憶體交換,那麼 Redis 和 依賴 Redis 上資料的應用會受到嚴重的性能影響。
檢視 used_memory 名額可知道 Redis 正在使用的記憶體情況,識别 Redis 記憶體交換的檢查方法:
- 識别 redis 程序号
redis-cli info server | grep process_id
- 根據程序号查詢記憶體交換資訊
cat /proc/{process_id}/smaps | grep Swap
如果交換量都是 0KB 或者個别 4KB,是正常現象。
預防記憶體交換:
- 保證機器充足的可用記憶體;
- 確定所有 redis 示例設定最大可用記憶體(maxmemory),防止極端情況下 redis 記憶體不可控的增長;
- 降低系統使用 swap 優先級,如 echo 10>/proc/sys/vm/swappiness。
四、fork 子程序
在 RDB 生成和 AOF 重寫時,會 fork 一個子程序完成持久化工作,當 fork 操作執行太過耗時也會造成阻塞,阻塞原因是該操作會複制父程序的空間記憶體表,即 fork 操作耗時跟記憶體量(資料集)關系較大。
fork 操作是重量級操作,會複制父程序的空間記憶體表(理論上需要複制與父程序同樣的記憶體,但是 linux 有寫時複制機制,父子程序貢獻相同的實體記憶體頁,實際會小很多,10G 大概隻需要 20MB)。
fork 耗時應該在 20ms/GB;應該嚴格控制每個執行個體可使用的最大記憶體 10GB 以内(複制空間記憶體表);降低 fork 操作執行頻率,适當放寬 AOF 重寫觸發時機。
使用 info stats 指令擷取 lastest_fork_usec 名額,表示 redis 最近一次 fork 操作耗時。
五、AOF 刷盤阻塞
開啟 AOF,檔案刷盤一般每秒一次,硬碟壓力過大時,fsync 需要等待寫入完成。
檢視 redis 日志或 info persistence 統計中的 aof_delayed_fsync 名額。
六、Redis 輸入緩沖區可能導緻的阻塞
輸入緩沖區:redis 為每個用戶端配置設定了輸入緩沖區,其會将用戶端發送指令臨時儲存,然後取出來執行。 qbuf 表示總容量(0 表示沒有配置設定查詢緩沖區),qbuf-free 表示剩餘容量(0 表示沒有剩餘空間);大小不能超過 1G,當大小超過 1G 時會将用戶端自動關閉,輸入緩沖區不受 maxmemory 限制。
當大量的 key 進入輸入緩沖區且無法被消費時,即可造成 redis 阻塞;通過 client list 指令可定位發生阻塞的用戶端;通過 info clients 指令的 blocked_clients 參數可以檢視到目前阻塞的指令。
七、Redis 輸出緩沖區可能導緻的阻塞
輸出緩沖區(client output buffer):是 redis-server 端實作的一個讀取緩沖區,redis-server 在接收到用戶端的請求後,把擷取結果寫入到 client buffer 中,而不是直接發送給用戶端。進而可以繼續處理用戶端的其他請求,這樣異步處理方式使 redis-server 不會因為網絡原因阻塞其他請求的處理。
redis client buffer 的配置參數為 "client-output-buffer-limit",預設值為:
127.0.0.1:6379> CONFIG GET "*output*"
1) "client-output-buffer-limit"
2) "normal 0 0 0 slave 0 0 0 pubsub 0 0 0"
- class :用戶端種類,normal、slave、pubsub
- normal:普通的用戶端
- slave: 從庫的複制用戶端
- pub/sub: 釋出與訂閱的用戶端
- hard limit: 緩沖區大小的硬性限制。
- soft limit: 緩沖去大小的軟性限制。
- soft seconds: 緩沖區大小達到了(超過)soft limit 值的持續時間。
client-output-buffer-limit 參數限制配置設定的緩沖區的大小,防止記憶體無節制的配置設定。參數的預設值都為 0,意思是不做任何限制。
redis server 觸發保護機制主要有兩種情況:
- client buffer 的大小達到了 soft limit 并持續了 soft seconds 時間,将立即斷開和用戶端的連接配接。
- client buffer 的大小達到了 hard limit,server 也會立即斷開和用戶端的連接配接。
八、網絡問題
1. 連接配接拒絕
- 網絡閃斷:一般在網絡割接或帶寬耗盡的情況;
- redis 連接配接拒絕:連接配接數大于 maxclients 時拒絕新的連接配接進入,可以關注 info stats 的 rejected_connections 名額;
- 連接配接溢出:
- 程序限制:程序可打開最大檔案數控制 —— ulimit -n,通常 1024,大量連接配接的 redis 需要增大該值;
- backlog 隊列溢出:系統對于特定端口 tcp 連接配接使用 backlog 隊列儲存,redis 預設 511,系統 backlog 預設 128,線上可使用 cron 定時執行 netstat -s | grep overflowed 統計;
2. 網絡延遲
測量機器之間的網絡延遲
redis-cli -h {ip} -p {port} –latency
redis-cli -h {ip} -p {port} –latency-history 預設15秒完成一行統計,-i控制采樣時間
redis-cli -h {ip} -p {port} –latency-dist 統計圖展示,每1秒采樣一次