每天在用Redis,持久化方案你又知道哪些?

前言

  • 文章首發於微信公衆號【碼猿技術專欄】:每天用Redis,持久化方案有哪些你知道嗎?
  • Redis目前已經成爲主流的內存數據庫了,可是大部分人僅僅是停留在會用的階段,你真的瞭解Redis內部的工做原理嗎?
  • 今天這篇文章將爲你們介紹Redis持久化的兩種方案,文章將會從如下五個方面介紹:
    1. 什麼是RDB,RDB如何實現持久化?
    2. 什麼是AOF,AOF如何實現持久化?
    3. AOF和RDB的區別。
    4. 如何重啓恢復數據?
    5. 持久化性能問題和解決方案

RDB

  • RDB持久化是把當前進程數據生成快照保存到硬盤的過程, 觸發RDB持久化過程分爲手動觸發和自動觸發。
  • RDB完成後會自動生成一個文件,保存在dir配置的指定目錄下,文件名是dbfileName指定。
  • Redis默認會採用LZF算法對生成的RDB文件作壓縮處理,壓縮後的文件遠遠小於內存大小,默認開啓。

手動觸發

  • 手動觸發的命令有savebgsave
  • save:該命令會阻塞Redis服務器,直到RDB的過程完成,已經被廢棄,所以線上不建議使用。
  • bgsave:每次進行RDB過程都會fork一個子進程,由子進程完成RDB的操做,所以阻塞只會發生在fork階段,通常時間很短。

自動觸發

  • 除了手動觸發RDB,Redis服務器內部還有以下幾個場景可以自動觸發RDB:
    1. 根據咱們的 save m n 配置規則自動觸發。
    2. 若是從節點執行全量複製操做, 主節點自動執行bgsave生成RDB文件併發送給從節點。
    3. 執行debug reload命令從新加載Redis時, 也會自動觸發save操做。
    4. 默認狀況下執行shutdown命令時, 若是沒有開啓AOF持久化功能則自動執行bgsave

RDB執行流程

  • RDB的主流方式就是bgsave,經過下圖咱們來看看RDB的執行流程:
  • RDB執行流程
  • 經過上圖能夠很清楚RDB的執行流程,以下:
    1. 執行bgsave命令後,會先判斷是否存在AOF或者RDB的子進程,若是存在,直接返回。
    2. 父進程fork操做建立一個子進程,fork操做中父進程會被阻塞。
    3. fork完成後,子進程開始根據父進程的內存生成臨時快照文件,完成後對原有的RDB文件進行替換。執行lastsave命令能夠查看最近一次的RDB時間。
    4. 子進程完成後發送信號給父進程,父進程更新統計信息。

RDB的優勢

  • RDB是一個緊湊壓縮的二進制文件, 表明Redis在某個時間點上的數據快照。 很是適用於備份, 全量複製等場景。 好比每6小時執行bgsave備份,並把RDB文件拷貝到遠程機器或者文件系統中,用於災難恢復。
  • Redis加載RDB恢復數據遠遠快於AOF的方式。

RDB的缺點

  • RDB方式數據沒辦法作到實時持久化/秒級持久化。 由於bgsave每次運行都要執行fork操做建立子進程,屬於重量級操做,頻繁執行成本太高。
  • RDB文件使用特定二進制格式保存, Redis版本演進過程當中有多個格式的RDB版本, 存在老版本Redis服務沒法兼容新版RDB格式的問題。

AOF

  • AOF(append only file) 持久化: 以獨立日誌的方式記錄每次寫命令,重啓時再從新執行AOF文件中的命令達到恢復數據的目的。 AOF的主要做用是解決了數據持久化的實時性, 目前已是Redis持久化的主流方式

如何開啓AOF

  • 開啓AOF功能須要設置配置:appendonly yes, 默認不開啓。 AOF文件名經過appendfilename配置設置, 默認文件名是appendonly.aof。 保存路徑同RDB持久化方式一致,經過dir配置指定。

AOF總體的執行流程

  • AOF執行的流程大體分爲命令寫入文件同步文件重寫重啓加載四個步驟,以下圖:
  • AOF執行流程
  • 從上圖大體瞭解了AOF的執行流程,下面一一分析上述的四個步驟。

命令寫入

  • AOF命令寫入的內容直接是文本協議格式。 例如set hello world這條命 令, 在AOF緩衝區會追加以下文本:
*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n
  • 命令寫入是直接寫入到AOF的緩衝區中,至於爲何?緣由很簡單,Redis使用單線程響應命令,若是每次寫AOF文件命令都直接追加到硬盤, 那麼性能徹底取決於當前硬盤負載。先寫入緩衝區aof_buf中, 還有另外一個好處, Redis能夠提供多種緩衝區 同步硬盤的策略,在性能和安全性方面作出平衡。

文件同步

  • Redis提供了多種AOF緩衝區同步文件策略, 由參數appendfsync控制,以下:
    • 配置爲always時, 每次寫入都要同步AOF文件, 在通常的SATA硬盤上,Redis只能支持大約幾百TPS寫入, 顯然跟Redis高性能特性背道而馳,不建議配置。
    • 配置爲no,因爲操做系統每次同步AOF文件的週期不可控,並且會加大每次同步硬盤的數據量,雖然提高了性能,但數據安全性沒法保證。
    • 配置爲everysec(默認的配置),是建議的同步策略, 也是默認配置,作到兼顧性能和數據安全性。理論上只有在系統忽然宕機的狀況下丟失1秒的數據(固然,這是不太準確的)。

文件重寫機制

  • 隨着命令不斷寫入AOF, 文件會愈來愈大, 爲了解決這個問題, Redis引入AOF重寫機制壓縮文件體積。 AOF文件重寫是把Redis進程內的數據轉化爲寫命令同步到新AOF文件的過程。
  • 爲何要文件重寫呢? 由於文件重寫可以使得AOF文件的體積變得更小,從而使得能夠更快的被Redis加載。
  • 重寫過程分爲手動觸發和自動觸發。
    • 手動觸發直接使用bgrewriteaof命令。
    • 根據auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage參數肯定自動觸發時機。
  • auto-aof-rewrite-min-size:表示運行AOF重寫時文件最小體積, 默認爲64MB。
  • auto-aof-rewrite-percentage:表明當前AOF文件空間(aof_current_size) 和上一次重寫後AOF文件空間(aof_base_size) 的比值。
  • 自動觸發時機至關於aof_current_size>auto-aof-rewrite-minsize&&(aof_current_size-aof_base_size) /aof_base_size>=auto-aof-rewritepercentage。其中aof_current_sizeaof_base_size能夠在info Persistence統計信息中查看。
  • 那麼文件重寫後的AOF文件爲何會變小呢? 有以下幾個緣由:
    1. 進程內已經超時的數據將不會再次寫入AOF文件中。
    2. 舊的AOF文件含有無效命令,如del key1hdel key2等。重寫使用進程內數據直接生成,這樣新的AOF文件只保留最終數據的寫入命令。
    3. 多條寫命令能夠合併爲一個, 如:lpush list alpush list blpush listc能夠轉化爲:lpush list a b c。爲了防止單條命令過大形成客戶端緩衝區溢出,對於listsethashzset等類型操做,以64個元素爲界拆分爲多條。
  • 介紹了文件重寫的系列知識,下面來看看Redis內部是如何進行文件重寫的,以下圖: 文件重寫
  • 看完上圖,大體瞭解了文件重寫的流程,對於重寫的流程,補充以下:
    1. 重寫期間,主線程並無阻塞,而是在執行其餘的操做命令,依然會向舊的AOF文件寫入數據,這樣可以保證備份的最終完整性,若是數據重寫失敗,也能保證數據不會丟失。
    2. 爲了把重寫期間響應的寫入信息也寫入到新的文件中,所以也會爲子進程保留一個緩衝區,防止新寫的文件丟失數據。
    3. 重寫是直接把當前內存的數據生成對應命令,並不須要讀取老的AOF文件進行分析、命令合併。
    4. AOF文件直接採用的文本協議,主要是兼容性好、追加方便、可讀性高可認爲修改修復。
    5. 不管是RDB仍是AOF都是先寫入一個臨時文件,而後經過重命名完成文件的替換。

AOF的優勢

  • 使用 AOF 持久化會讓 Redis 變得很是耐久:你能夠設置不一樣的 fsync 策略,好比無 fsync ,每秒鐘一次 fsync ,或者每次執行寫入命令時 fsync 。 AOF 的默認策略爲每秒鐘 fsync 一次,在這種配置下,Redis 仍然能夠保持良好的性能,而且就算髮生故障停機,也最多隻會丟失一秒鐘的數據( fsync 會在後臺線程執行,因此主線程能夠繼續努力地處理命令請求)。

AOF的缺點

  • 對於相同的數據集來講,AOF 文件的體積一般要大於 RDB 文件的體積。根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB。 在通常狀況下, 每秒 fsync 的性能依然很是高, 而關閉 fsync 可讓 AOF 的速度和 RDB 同樣快, 即便在高負荷之下也是如此。不過在處理巨大的寫入載入時,RDB 能夠提供更有保證的最大延遲時間。
  • 數據恢復速度相對於RDB比較慢。

AOF和RDB的區別

  • RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操做過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功後,再替換以前的文件,用二進制壓縮存儲。
  • AOF持久化以日誌的形式記錄服務器所處理的每個寫、刪除操做,查詢操做不會記錄,以文本的方式記錄,能夠打開文件看到詳細的操做記錄。

重啓加載

  • 不管是RDB仍是AOF均可用於服務器重啓時的數據恢復,執行流程以下圖:
  • 重啓加載流程
  • 上圖很清晰的分析了Redis啓動恢復數據的流程,先檢查AOF文件是否開啓,文件是否存在,再檢查RDB是否開啓,文件是否存在。

性能問題與解決方案

  • 經過上面的分析,咱們都知道RDB的快照、AOF的重寫都須要fork,這是一個重量級操做,會對Redis形成阻塞。所以爲了避免影響Redis主進程響應,咱們須要儘量下降阻塞。
  • 那麼如何減小fork操做的阻塞呢?
    1. 優先使用物理機或者高效支持fork操做的虛擬化技術。
    2. 控制Redis實例最大可用內存, fork耗時跟內存量成正比, 線上建議每一個Redis實例內存控制在10GB之內。
    3. 合理配置Linux內存分配策略,避免物理內存不足致使fork失敗。
    4. 下降fork操做的頻率,如適度放寬AOF自動觸發時機,避免沒必要要的全量複製等。

總結

  • 本文介紹了Redis持久化的兩種不一樣的策略,大部份內容是運維人員須要掌握的,固然做爲後端人員也是須要了解一下,畢竟小公司都是一人搞全棧,哈哈。
  • 若是以爲陳某寫的不錯,有所收穫的話,關注分享一波,你的關注將是陳某寫做的最大動力,謝謝支持!!!
相關文章
相關標籤/搜索