天天看點

天天用Redis,持久化方案有哪些你知道嗎?

雲栖号資訊:【 點選檢視更多行業資訊

在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!

Redis目前已經成為主流的記憶體資料庫了,但是大部分人僅僅是停留在會用的階段,你真的了解Redis内部的工作原理嗎?

RDB

  • RDB持久化是把目前程序資料生成快照儲存到硬碟的過程, 觸發RDB持久化過程分為手動觸發和自動觸發。
  • RDB完成後會自動生成一個檔案,儲存在dir配置的指定目錄下,檔案名是dbfileName指定。
  • Redis預設會采用LZF算法對生成的RDB檔案做壓縮處理,壓縮後的檔案遠遠小于記憶體大小,預設開啟。

手動觸發

  • 手動觸發的指令有save和bgsave。
  • 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的執行流程:

天天用Redis,持久化方案有哪些你知道嗎?
  • 通過上圖可以很清楚RDB的執行流程,如下:

1.執行bgsave指令後,會先判斷是否存在AOF或者RDB的子程序,如果存在,直接傳回。

2.父程序fork操作建立一個子程序,fork操作中父程序會被阻塞。

3.fork完成後,子程序開始根據父程序的記憶體生成臨時快照檔案,完成後對原有的RDB檔案進行替換。

4.執行lastsave指令可以檢視最近一次的RDB時間。子程序完成後發送信号給父程序,父程序更新統計資訊。

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執行的流程大緻分為指令寫入、檔案同步、檔案重寫、重新開機加載四個步驟,如下圖:

天天用Redis,持久化方案有哪些你知道嗎?

從上圖大緻了解了AOF的執行流程,下面一一分析上述的四個步驟。

指令寫入

AOF指令寫入的内容直接是文本協定格式。 例如set hello world這條指令, 在AOF緩沖區會追加如下文本:

天天用Redis,持久化方案有哪些你知道嗎?

指令寫入是直接寫入到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-size和auto-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_size和aof_base_size可以在info Persistence統計資訊中檢視。那麼檔案重寫後的AOF檔案為什麼會變小呢? 有如下幾個原因:

程序内已經逾時的資料将不會再次寫入AOF檔案中。

舊的AOF檔案含有無效指令,如del key1、 hdel key2等。重寫使用程序内資料直接生成,這樣新的AOF檔案隻保留最終資料的寫入指令。

多條寫指令可以合并為一個, 如:lpush list a、 lpush list b、lpush listc可以轉化為:lpush list a b c。為了防止單條指令過大造成用戶端緩沖區溢出,對于list、 set、 hash、 zset等類型操作,以64個元素為界拆分為多條。

介紹了檔案重寫的系列知識,下面來看看Redis内部是如何進行檔案重寫的,如下圖:

天天用Redis,持久化方案有哪些你知道嗎?

看完上圖,大緻了解了檔案重寫的流程,對于重寫的流程,補充如下:

重寫期間,主線程并沒有阻塞,而是在執行其他的操作指令,依然會向舊的AOF檔案寫入資料,這樣能夠保證備份的最終完整性,如果資料重寫失敗,也能保證資料不會丢失。

為了把重寫期間響應的寫入資訊也寫入到新的檔案中,是以也會為子程序保留一個緩沖區,防止新寫的檔案丢失資料。

重寫是直接把目前記憶體的資料生成對應指令,并不需要讀取老的AOF檔案進行分析、指令合并。

AOF檔案直接采用的文本協定,主要是相容性好、追加友善、可讀性高可認為修改修複。無論是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,持久化方案有哪些你知道嗎?

上圖很清晰的分析了Redis啟動恢複資料的流程,先檢查AOF檔案是否開啟,檔案是否存在,再檢查RDB是否開啟,檔案是否存在。

性能問題與解決方案

通過上面的分析,我們都知道RDB的快照、AOF的重寫都需要fork,這是一個重量級操作,會對Redis造成阻塞。是以為了不影響Redis主程序響應,我們需要盡可能降低阻塞。那麼如何減少fork操作的阻塞呢?

1.優先使用實體機或者高效支援fork操作的虛拟化技術。

2.控制Redis執行個體最大可用記憶體, fork耗時跟記憶體量成正比, 線上建議每個Redis執行個體記憶體控制在10GB以内。

3.合理配置Linux記憶體配置設定政策,避免實體記憶體不足導緻fork失敗。

4.降低fork操作的頻率,如适度放寬AOF自動觸發時機,避免不必要的全量複制等。

總結

本文介紹了Redis持久化的兩種不同的政策,大部分内容是運維人員需要掌握的,當然作為後端人員也是需要了解一下,畢竟小公司都是一人搞全棧,哈哈。

【雲栖号線上課堂】每天都有産品技術專家分享!

課程位址:

https://yqh.aliyun.com/live

立即加入社群,與專家面對面,及時了解課程最新動态!

【雲栖号線上課堂 社群】

https://c.tb.cn/F3.Z8gvnK

原文釋出時間:2020-04-20

本文作者:不才陳某

本文來自:“

掘金

”,了解相關資訊可以關注“掘金”