Redis 最佳實踐!業務和運維層面優化

做者:Kaito
出處:kaito-kidd.com/2020/07/04/redis-best-practices/

這篇文章咱們就來總結一下,在使用Redis時的最佳實踐方式,主要包含兩個層面:業務層面、運維層面。redis

因爲我以前寫過不少UGC後端服務,在大量場景下用到了Redis,這個過程當中也踩過不少坑,因此在使用過程當中也總結了一套合理的使用方法。後端

後來作基礎架構,開發Codis、Redis相關的中間件,在這個階段關注領域從使用層面下沉到Redis的開發和運維,更多聚焦在Redis的內部實現和運維過程當中產生的各類問題,在這塊也積累了一些經驗。緩存

下面就針對這兩塊,分享一下我認爲比較合理的Redis使用和運維方法,不必定最全面,也可能與你使用Redis的方法不一樣,但如下這些方法都是我在踩坑以後總結的實際經驗,供你參考。關注公衆號Java技術棧回覆redis獲取系列Redis教程。網絡

業務層面主要是開發人員須要關注,也就是開發人員在寫業務代碼時,如何合理地使用Redis。開發人員須要對Redis有基本的瞭解,才能在合適的業務場景使用Redis,從而避免業務層面致使的延遲問題。架構

在開發過程當中,業務層面的優化建議以下:app

  • key的長度儘可能要短,在數據量很是大時,過長的key名會佔用更多的內存
  • 必定避免存儲過大的數據(大value),過大的數據在分配內存和釋放內存時耗時嚴重,會阻塞主線程
  • Redis 4.0以上建議開啓lazy-free機制,釋放大value時異步操做,不阻塞主線程
  • 建議設置過時時間,把Redis當作緩存使用,尤爲在數量很大的時,不設置過時時間會致使內存的無限增加
  • 不使用複雜度太高的命令,例如SORT、SINTER、SINTERSTORE、ZUNIONSTORE、ZINTERSTORE,使用這些命令耗時較久,會阻塞主線程
  • 查詢數據時,一次儘可能獲取較少的數據,在不肯定容器元素個數的狀況下,避免使用LRANGE key 0 -1,ZRANGE key 0 -1這類操做,應該設置具體查詢的元素個數,推薦一次查詢100個如下元素
  • 寫入數據時,一次儘可能寫入較少的數據,例如HSET key value1 value2 value3...,-控制一次寫入元素的數量,推薦在100如下,大數據量分多個批次寫入
  • 批量操做數據時,用MGET/MSET替換GET/SET、HMGET/MHSET替換HGET/HSET,減小請求來回的網絡IO次數,下降延遲,對於沒有批量操做的命令,推薦使用pipeline,一次性發送多個命令到服務端
  • 禁止使用KEYS命令,須要掃描實例時,建議使用SCAN,線上操做必定要控制掃描的頻率,避免對Redis產生性能抖動
  • 避免某個時間點集中過時大量的key,集中過時時推薦增長一個隨機時間,把過時時間打散,下降集中過時key時Redis的壓力,避免阻塞主線程
  • 根據業務場景,選擇合適的淘汰策略,一般隨機過時要比LRU過時淘汰數據更快
  • 使用鏈接池訪問Redis,並配置合理的鏈接池參數,避免短鏈接,TCP三次握手和四次揮手的耗時也很高
  • 只使用db0,不推薦使用多個db,使用多個db會增長Redis的負擔,每次訪問不一樣的db都須要執行SELECT命令,若是業務線不一樣,建議拆分多個實例,還能提升單個實例的性能
  • 讀的請求量很大時,推薦使用讀寫分離,前提是能夠容忍從節數據更新不及時的問題
  • 寫請求量很大時,推薦使用集羣,部署多個實例分攤寫壓力

運維層面運維

目的是合理規劃Redis的部署和保障Redis的穩定運行,主要優化以下:異步

  • 不一樣業務線部署不一樣的實例,各自獨立,避免混用,推薦不一樣業務線使用不一樣的機器,根據業務重要程度劃分不一樣的分組來部署,避免某一個業務線出現問題影響其餘業務線
  • 保證機器有足夠的CPU、內存、帶寬、磁盤資源,防止負載太高影響Redis性能
  • 以master-slave集羣方式部署實例,並分佈在不一樣機器上,避免單點,slave必須設置爲readonly
  • master和slave節點所在機器,各自獨立,不要交叉部署實例,一般備份工做會在slave上作,作備份時會消耗機器資源,交叉部署會影響到master的性能
  • 推薦部署哨兵節點增長可用性,節點數量至少3個,並分佈在不一樣機器上,實現故障自動故障轉移
  • 提早作好容量規劃,一臺機器部署實例的內存上限,最好是機器內存的一半,主從全量同步時會佔用最多額外一倍的內存空間,防止網絡大面積故障引起全部master-slave的全量同步致使機器內存被吃光
  • 作好機器的CPU、內存、帶寬、磁盤監控,在資源不足時及時報警處理,Redis使用Swap後性能急劇降低,網絡帶寬負載太高訪問延遲明顯增大,磁盤IO太高時開啓AOF會拖慢Redis的性能
  • 設置最大鏈接數上限,防止過多的客戶端鏈接致使服務負載太高
  • 單個實例的使用內存建議控制在20G如下,過大的實例會致使備份時間久、資源消耗多,主從全量同步數據時間阻塞時間更長
  • 設置合理的slowlog閾值,推薦10毫秒,並對其進行監控,產生過多的慢日誌須要及時報警 設置合理的複製緩衝區repl-backlog大小,適當調大repl-backlog能夠下降主從全量複製的機率
  • 設置合理的slave節點client-output-buffer-limit大小,對於寫入量很大的實例,適當調大能夠避免主從複製中斷問題
  • 備份時推薦在slave節點上作,不影響master性能
  • 不開啓AOF或開啓AOF配置爲每秒刷盤,避免磁盤IO消耗下降Redis性能
  • 當實例設置了內存上限,須要調大內存上限時,先調整slave再調整master,不然會致使主從節點數據不一致
  • 對Redis增長監控,監控採集info信息時,使用長鏈接,頻繁的短鏈接也會影響Redis性能,redis性能監控指標,參考這個文章
  • 線上掃描整個實例數時,記得設置休眠時間,避免掃描時QPS突增對Redis產生性能抖動
  • 作好Redis的運行時監控,尤爲是expired_keys、evicted_keys、latest_fork_usec指標,短期內這些指標值突增可能會阻塞整個實例,引起性能問題

以上就是我在使用Redis和開發Redis相關中間件時,總結出來Redis推薦的實踐方法,以上提出的這些方面,都或多或少在實際使用中遇到過。性能

可見,要想穩定發揮Redis的高性能,須要在各個方面作好工做,但凡某一個方面出現問題,必然會影響到Redis的性能,這對咱們使用和運維提出了更高的要求。大數據

若是你在使用Redis過程當中,遇到更多的問題或者有更好的使用經驗,能夠留言一塊兒探討!

image