如何用慢查詢找到 Redis 的性能瓶頸?
Redis數據庫是一個基于內存的 key-value存儲系統,現在redis最常用的使用場景就是存儲緩存用的數據,在需要高速讀/寫的場合使用它快速讀/寫,從而緩解應用數據庫的壓力,進而提升應用處理能力。
由于Redis的單線程架構,所以需要每個命令能被快速執行完,否則會存在阻塞Redis的可能,理解Redis單線程命令處理機制是開發和運維Redis的核心之一。
許多數據庫會提供慢查詢日志幫助開發和運維人員定位系統存在的慢操作。所謂慢查詢日志就是系統在命令執行前后計算每條命令的執行時間,當然在數據庫中最常見的就是select這些sql語句了,當超過預設閥值,就將這條命令的相關信息(例如:發生時間,耗時,命令的詳細信息)記錄下來,Redis也提供了類似的功能。
那么如何使用Redis所提供的慢查詢功能呢?Redis主要提供了slowlog-log-slower-than和slowlog-max-len兩個配置參數來提供這項功能。兩項參數分別用來設置慢查詢的閾值以及存放慢查詢的記錄。首先對redis的這兩個配置進行一個說明 :
從字面意思就可以看出,可以通過slowlog-log-slower-than參數設置什么情況下是慢語句,只有redis命令執行時間大于slowlog-log-slower-than的才會定義成慢查詢,才會被slowlog進行記錄。它的單位是微秒(1秒=1000毫秒=1000000微秒),在初始情況下默認值是10000,也就是10ms,假如執行了一條比較慢的命令,如果它的執行時間超過了 10ms ,那么它將被記錄在慢查詢日志中。(如果slowlog-log-slower-than=0會記錄所有的命令,slowlog-log-slower than<0對于任何命令都不會進行記錄)
從字面意思看,slowlog-max-len說明了慢查詢日志最多可以存儲多少條記錄,實際上Redis使用了一個列表來存儲慢查詢日志,slowlog-max-len就是列表的最大長度,它自身是一個先進先出隊列,當slowlog超過設定的最大值后,會將最早的slowlog刪除。簡而言之當一個新的命令滿足慢查詢條件時會被插入到這個列表中,當慢查詢日志列表已處于其最大長度時,最早插入的一個命令將從列表中移出,例如slowlog-max-len設置為 50 ,當有第51條慢查詢插入的話,那么隊頭的第一條數據就出列,第51條慢查詢就會入列。
接下來詳細介紹一下如何配置這兩個參數,有兩種方式進行配置,以下截圖全部使用了redis -5.0.5版本 :
方式一:通過配置redis.conf文件進行配置。
通過修改redis .conf文件之后重啟redis服務 , 配置即可生效 。
方式二:通過CONFIG命令進行動態配置
配置查詢時間超過1毫秒的命令進行記錄
保存500條慢查記錄
通過config get命令確認配置已生效
要注意通過config命令配置的為動態生效 , 一旦服務重啟則會重新恢復為默認設置 , 所以建議在排查問題時通過config這種方式進行配置 , 但是服務穩定后通過修改配置文件方式進行最終確認 (可以通過config rewrite命令持久化到本地文件 , 但要主要啟動redis時要指定redis . conf文件 該命令才可以生效)。
相關的參數已經設置完成了 , 那么如何查看記錄的信息呢 ?要想查看所記錄的日志 , 主要使用 SLOWLOG GET 或者 SLOWLOG GET number 命令,前者將會輸出所有的 slow log ,最大長度取決于 slowlog-max-len 選項的值,而 SLOWLOG GET number 則只打印指定數量的日志。
查看當前日志數量: 使用SHOW LEN命令查看日志數量。
因為我是新安裝的redis , 所以現在還沒有耗時長日志 , 所以條數是 0,如果日志條數過多,還可以使用slowlog reset命令進行日志清空 。
為了方便演示 ,我將所有的執行命令都記錄了下來,以第一條為例,
1、(integer) 1 # 唯一性(unique)的日志標識符
2、(integer) 1562075522 # 被記錄命令的執行時間點,以 UNIX 時間戳格式表示
3、(integer) 93 # 查詢執行時間,以微秒為單位
4、1."CONFIG" # 執行的命令,以數組的形式排列
5、"GET"
6、" " # 這里完整的命令是 CONFIG GET
慢查詢功能可以有效地幫助我們找到Redis可能存在的瓶頸,但在實際使用過程中要注意以下幾點:
- slowlog-max-len配置建議:線上建議調大慢查詢列表,記錄慢查詢時 Redis會對長命令做截斷操作,并不會占用大量內存。增大慢查詢列表可以減緩慢查詢被剔除的可能,例如線上可設置為 2000 以上(5.0.5版本默認為128)。
- slowlog-log-slower-than配置建議:默認值超過10毫秒判定為慢查詢,需要根據Redis并發量調整該值。由于Redis采用單線程響應命令,對于高流量的場景,如果命令執行時間在1毫秒以上,那么Redis最多可支撐OPS不到1000。因此對于高OPS場景的Redis建議設置為1毫秒(OPS指每秒操作次數)。
- 慢查詢只記錄命令執行時間,并不包括命令排隊和網絡傳輸時間。因此客戶端執行命令的時間會大于命令實際執行時間。因為命令執行排隊機制,慢查詢會導致其他命令級聯阻塞,因此當客戶端出現請求超時,需要檢查該時間點是否有對應的慢查詢,從而分析出是否為慢查詢導致的命令級聯阻塞。
- 由于慢查詢日志是一個先進先出的隊列,也就是說如果慢查詢比較多的情況下,可能會丟失部分慢查詢命令,為了防止這種情況發生,可以定期執行slow get命令將慢查詢日志持久化到其他存儲中,然后可以進行相關的監控、告警、分析工作。