本文主要講了 Redis 的持久化相關功能,持久化一直是影響 Redis 性能的高發地,也是面試中常常被問到的。包括 RDB 相關的特定和優缺點,AOF 的優缺點,事實上,因爲 RDB 的數據實時性問題,目前用 AOF 比較多了。而持久化恢復也是優先 AOF。ios
RDB 是舊的模式,如今基本上都使用 AOF。固然,兩個都會一塊兒說到。面試
Redis 會壓縮 RDB 文件,使用 LZF 算法,讓最終的 RDB 文件遠小於內存大小,默認開啓。但會消耗 CPU。redis
因爲 RDB 的數據實時性問題,AOF(append only file) 是目前 Redis 持久化的主流方式。算法
緩衝區同步策略,由參數 appendfsync 控制,一共3種:緩存
AOF 和 RDB 文件均可以用於服務器重啓時的數據恢復,具體流程以下圖:安全
從圖中能夠看出優先加載 AOF,當沒有 AOF 時才加載 RDB。當 AOF 或者 RDB 存在錯誤,則加載失敗。性能優化
Redis 持久化是影響 Redis 性能的高發地,也是面試中常問的問題。服務器
當 Redis 作 RDB 或者 AOF 重寫時,必然要進行 fork 操做,對於 OS 來講,fork 都是一個重量級操做。並且,fork 還會拷貝一些數據,雖然不會拷貝主進程全部的物理空間,但會複製主進程的空間內存頁表。對於 10GB 的 Redis 進程,須要複製大約 20MB 的內存頁表,所以 fork 操做耗時跟進程總內存量息息相關,再加上,若是使用虛擬化技術,例如 Xen 虛擬機,fork 會更加耗時。架構
一個正常的 fork 耗時大概在 20毫秒左右。爲何呢,假設一個 Redis 實例的 OPS 在 5 萬以上,若是 fork 操做耗時在秒級,那麼僵拖慢幾萬條命令的執行,對生產環境影響明顯。併發
咱們能夠在 Info stats 統計中查詢 latestforkusec 指標獲取最近一次 fork 操做耗時,單位微秒。
如何優化:
一、優先使用物理機或者高效支持 fork 的虛擬化技術,避免使用 Xen。 二、控制 redis 實例最大內存,儘可能控制在 10GB 之內。 三、合理配置 Linux 內存分配策略,避免內存不足致使 fork 失敗。 四、下降 fork 的頻率,如適度放寬 AOF 自動觸發時機,避免沒必要要的全量複製。
fork 完畢以後,會建立子進程,子進程負責 RDB 或者 AOF 重寫,這部分過程主要涉及到 CPU,內存,硬盤三個地方的優化。
一、CPU 寫入文件的過程是 CPU 密集的過程,一般子進程對單核 CPU 利用率接近 90%。 如何優化呢?既然是 CPU 密集型操做,就不要綁定單核 CPU,由於這樣會和父 CPU 進行競爭。同時,不要和其餘 CPU 密集型服務不是在一個機器上。若是部署了多個 Redis 實例,盡力保證統一時刻只有一個子進程執行重寫工做。
二、內存 子進程經過 fork 操做產生,佔用內存大小等同於父進程,理論上須要兩倍的內存完成持久化操做,但 Linux 有 copy on write 機制,父子進程會共享相同的物理內存頁,當父進程處理寫操做時,會把要修改的頁建立對應的副本,而子進程在 fork 操做過程當中,共享整個父進程內存快照。 即——若是重寫過程當中存在內存修改操做,父進程負責建立所修改內存頁的副本。這裏就是內存消耗的地方。 如何優化呢?儘可能保證同一時刻只有一個子進程在工做;避免大量寫入時作重寫操做。
三、硬盤 硬盤開銷分析:子進程主要職責是將 RDB 或者 AOF 文件寫入硬盤進行持久化,勢必對硬盤形成壓力,可經過工具例如 iostat,iotop 等,分析硬盤負載狀況。
如何優化:
不要和其餘高硬盤負載的服務放在一臺機器上,例如 MQ,存儲。
AOF 重寫時會消耗大量硬盤 IO,能夠開啓配置 no-appendfsync-on-rewrite,默認關閉。表示在 AOF 重寫期間不作 fsync 操做。
當開啓 AOF 的 Redis 在高併發場景下,若是使用普通機械硬盤,每秒的寫速率是 100MB左右,這時,Redis 的性能瓶頸在硬盤上,建議使用 SSD。
對於單機配置多個 Redis 實例的狀況,能夠配置不一樣實例分盤存儲 AOF 文件,分攤硬盤壓力。
當開啓 AOF 持久化時,經常使用的同步硬盤的策略是「每秒同步」 everysec,用於平衡性能和數據安全性,對於這種方式,redis 使用另外一條線程每秒執行 fsync 同步硬盤,當系統資源繁忙時,將形成 Redis 主線程阻塞。
流程圖以下:
經過上圖能夠發現:everysec 配置最多可能丟失 2 秒數據,不是 1 秒;若是系統 fsync 緩慢,將會致使 Redis 主線程阻塞影響效率。
問題定位:
Redis 單線程架構沒法充分利用多核CPU,一般的作法是一臺機器上部署多個實例,當多個實例開啓 AOF 後,彼此之間就會產生CPU 和 IO 的競爭。
如何解決這個問題呢?
讓全部實例的 AOF 串行執行。
咱們經過 info Persistence 中關於 AOF 的信息寫出 Shell 腳本,而後串行執行實例的 AOF 持久化。
整個過程如圖:
經過不斷判斷 AOF 的狀態,手動執行 AOF 重寫,保證 AOF 不會存在競爭。具體的 Shell 編寫以及 info 信息判斷,能夠查看下圖:
本文主要講了 Redis 的持久化相關功能,持久化一直是影響 Redis 性能的高發地,也是面試中常常被問到的。包括 RDB 相關的特定和優缺點,AOF 的優缺點,事實上,因爲 RDB 的數據實時性問題,目前用 AOF 比較多了。而持久化恢復也是優先 AOF。
關於持久化的問題排查,就很麻煩了,但無非幾個方面,fork 耗時,子進程的 CPU,內存,硬盤開銷,AOF 的同步阻塞,單機多實例部署。這些優化,能夠經過前面寫的分析進行排查。