redis是典型的單執行緒架構, 所有的讀寫操作都是在一條主線程中完成的。 當redis用於高併發場景時, 這條執行緒就變成了它的生命線。 如果出現阻塞, 哪怕是很短時間, 對於我們的應用來說都是噩夢。 導致阻塞問題的場景大致分為內在原因和外在原因:
·內在原因包括: 不合理地使用api或資料結構、 cpu飽和、 持久化阻塞等。
·外在原因包括: cpu競爭、 記憶體交換、 網路問題等。
發現阻塞監控系統所監控的關鍵指標有很多, 如命令耗時、 慢查詢、 持久化阻塞、 連線拒絕、 cpu/記憶體/網路/磁碟使用過載等。
內在原因
·api或資料結構使用不合理。
·cpu飽和的問題。
·持久化相關的阻塞。
api或資料結構使用不合理
對於高併發的場景我們應該盡量避免在大物件上執行演算法複雜度超過o(n) 的命令。例如在乙個大的hash物件上執行hgetall命令。
1.發現慢查詢
redis原生提供慢查詢統計功能, 執行slowlog get命令可以獲取最近的n條慢查詢命令, 預設對於執行超過10毫秒的命令都會記錄到乙個定長佇列中, 線上例項建議設定為1毫秒便於及時發現毫秒級以上的命令。
2.如何發現大物件
redis本身提供發現大物件的工具, 對應命令: redis-cli-h-pbigkeys。 內部原理採用分段進行scan操作, 把歷史掃瞄過的最大物件統計出來便於分析優化。
cpu飽和
單執行緒的redis處理命令時只能使用乙個cpu。 而cpu飽和是指redis把單核cpu使用率跑到接近100%。 使用top命令很容易識別出對應redis程序的cpu使用率。 cpu飽和是非常危險的, 將導致redis無法處理更多的命令, 嚴重影響吞吐量和應用方的穩定性。 對於這種情況, 首先判斷當前redis的併發量是否達到極限, 建議使用統計命令redis-cli-h-p–stat獲取當前redis使用情況
持久化阻塞
對於開啟了持久化功能的redis節點, 需要排查是否是持久化導致的阻塞。 持久化引起主線程阻塞的操作主要有: fork阻塞、 aof刷盤阻塞、hugepage寫操作阻塞。
1.fork阻塞
fork操作發生在rdb和aof重寫時, redis主線程呼叫fork操作產生共享記憶體的子程序, 由子程序完成持久化檔案重寫工作。 如果fork操作本身耗時過長, 必然會導致主線程的阻塞。
2.aof刷盤阻塞
當我們開啟aof持久化功能時, 檔案刷盤的方式一般採用每秒一次, 後台執行緒每秒對aof檔案做fsync操作。 當硬碟壓力過大時, fsync操作需要等待, 直到寫入完成。 如果主線程發現距離上一次的fsync成功超過2秒, 為了資料安全性它會阻塞直到後台執行緒執行fsync操作完成。 這種阻塞行為主要是硬碟壓力引起。
3.hugepage寫操作阻塞
子程序在執行重寫期間利用linux寫時複製技術降低記憶體開銷, 因此只有寫操作時redis才複製要修改的記憶體頁。 對於開啟transparent hugepages的作業系統, 每次寫命令引起的複製記憶體頁單位由4k變為2mb, 放大了512倍, 會拖慢寫操作的執行時間, 導致大量寫操作慢查詢。
外在原因
·cpu競爭
·記憶體交換
·網路問題
cpu競爭
·程序競爭: redis是典型的cpu密集型應用, 不建議和其他多核cpu密集型服務部署在一起。 當其他程序過度消耗cpu時, 將嚴重影響redis吞吐量。 可以通過top、 sar等命令定位到cpu消耗的時間點和具體程序, 這個問題比較容易發現, 需要調整服務之間部署結構。
·繫結cpu: 部署redis時為了充分利用多核cpu, 通常一台機器部署多個例項。 常見的一種優化是把redis程序繫結到cpu上, 用於降低cpu頻繁上下文切換的開銷。
記憶體交換
記憶體交換(swap) 對於redis來說是非常致命的, redis保證高效能的乙個重要前提是所有的資料在記憶體中。 如果作業系統把redis使用的部分記憶體換出到硬碟, 由於記憶體與硬碟讀寫速度差幾個數量級, 會導致發生交換後的redis效能急劇下降。
1) 查詢redis程序號
2) 根據程序號查詢記憶體交換資訊
網路問題
網路問題經常是引起redis阻塞的問題點。 常見的網路問題主要有: 連線拒絕、 網路延遲、 網絡卡軟中斷等。
1.連線拒絕
當出現網路閃斷或者連線數溢位時, 客戶端會出現無法連線redis的情況。 我們需要區分這三種情況: 網路閃斷、 redis連線拒絕、 連線溢位。
第一種情況: 網路閃斷。 一般發生在網路割接或者頻寬耗盡的情況, 對於網路閃斷的識別比較困難, 常見的做法可以通過sar-n dev檢視本機歷史流量是否正常, 或者借助外部系統監控工具(如ganglia) 進行識別。 具體問題定位需要更上層的運維支援, 對於重要的redis服務需要充分考慮部署架構的優化, 盡量避免客戶端與redis之間異地跨機房呼叫。
第二種情況: redis連線拒絕。
redis通過maxclients引數控制客戶端最大連線數, 預設10000。 當redis連線數大於maxclients時會拒絕新的連線進入,info stats的rejected_connections統計指標記錄所有被拒絕連線的數量。redis使用多路復用io模型可支撐大量連線, 但是不代表可以無限連線。 客戶端訪問redis時盡量採用nio長連線或者連線池的方式。
第三種情況: 連線溢位。 這是指作業系統或者redis客戶端在連線時的問題。 這個問題的原因比較多, 下面就分別介紹兩種原因: 程序限制、backlog佇列溢位。
(1) 程序限制
客戶端想成功連線上redis服務需要作業系統和redis的限制都通過才可以。作業系統一般會對程序使用的資源做限制, 其中一項是對程序可開啟最大檔案數控制, 通過ulimit-n檢視, 通常預設1024。 由於linux系統對tcp連線也定義為乙個檔案控制代碼, 因此對於支撐大量連線的redis來說需要增大這
個值, 如設定ulimit-n65535, 防止too many open files錯誤。
(2) backlog佇列溢位
系統對於特定埠的tcp連線使用backlog佇列儲存。 redis預設的長度為511, 通過tcp-backlog引數設定。 如果redis用於高併發場景為了防止緩慢連線占用, 可適當增大這個設定, 但必須大於作業系統允許值才能生效。 當redis啟動時如果tcp-backlog設定大於系統允許值將以系統值為準。
2.網路延遲
3.網絡卡軟中斷
linux 編譯安裝 redis6
執行效能測試 centos yum groupinstall development tools y ubuntu apt install build essential wget y axel tar vxzf redis 6.0.5.tar.gz cd redis 6.0.5 make mall...
redis6安裝 centos系統
在centos7.5伺服器上按照官方發布的安裝方式並不能進行正確的安裝,現收集並整理如下安裝方式,親測有效 1.安裝依賴 yum install y cpp binutils glibc glibc kernheaders glibc common glibc devel gcc make tcl2...
redis6集群安裝
建立集群配置檔案redis cluster 7000.conf,埠7000 port 7000 daemonize yes pidfile user local redis redis redis 7000 cluster.pid logfile 7005 cluster.log bind 0.0....