Redis 優化最佳實踐!

點擊上方「民工哥技術之路」,選擇「設爲星標」

回覆「1024」獲取獨家整理的學習資料!

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

由於我之前寫過很多UGC後端服務,在大量場景下用到了Redis,這個過程中也踩過很多坑,所以在使用過程中也總結了一套合理的使用方法。

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

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

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

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

  • 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過程中,遇到更多的問題或者有更好的使用經驗,可以留言一起探討!

作者:Kaito

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

推薦閱讀 點擊標題可跳轉

Linux 日誌切割神器 Logrotate 原理和配置詳解(附多生產實例)

寵粉福利:紅包+送書!先到先得

常見互聯網公司職級和薪資一覽!

就是要讓你搞懂Nginx,這篇就夠了!

MySQL 高頻面試題,都在這了

Shell 命令執行可視化和告警工具

Elasticsearch 最佳實踐!

提升效率!Linux 管理員必用的10個關鍵技巧