Redis學習六(Redis 阻塞的原因及其排查方向).


一、慢查詢

因為 Redis 是單線程的,大量的慢查詢可能會導致 redis-server 阻塞,可以通過 slowlog get n 獲取慢日志,查看詳情情況。

二、bigkey 大對象

bigkey 大對象可能會導致的問題包括:

  • 內存空間不均勻(平衡),例如在 Redis Cluster 中,bigkey 會造成節點的內存空間使用不均勻。
  • 超時阻塞:由於Redis 單線程的特性,操作 bigkey 比較耗時,也就意味着阻塞 Redis 的可能性增大。
  • 網絡阻塞:每次獲取 bigkey 產生的網絡流量較大,假設一個 bigkey 為 1MB,每次訪問量為 1000,那么每秒產生 1000MB 的流量,對於普通的千兆網卡(按照字節算是128MB/s)的服務器簡直是滅頂之災。

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 內存交換的檢查方法:

  1. 識別 redis 進程號

redis-cli info server | grep process_id

  1. 根據進程號查詢內存交換信息

cat /proc/{process_id}/smaps | grep Swap

如果交換量都是 0KB 或者個別 4KB,是正常現象。

預防內存交換:

  1. 保證機器充足的可用內存;
  2. 確保所有 redis 示例設置最大可用內存(maxmemory),防止極端情況下 redis 內存不可控的增長;
  3. 降低系統使用 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 觸發保護機制主要有兩種情況:

  1. client buffer 的大小達到了 soft limit 並持續了 soft seconds 時間,將立即斷開和客戶端的連接。
  2. 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秒采樣一次


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM