天天用Redis,持久化方案你又知道哪些?
來源 |碼猿技術專欄
責編 | Carol
頭圖 | CSDN 下載自視覺中國
Redis目前已經成為主流的內存數據庫了,但是大部分人僅僅是停留在會用的階段,你真的了解Redis內部的工作原理嗎?
今天這篇文章將為大家介紹Redis持久化的兩種方案,文章將會從以下五個方面介紹:
什么是RDB,RDB如何實現持久化?
什么是AOF,AOF如何實現持久化?
AOF和RDB的區別。
如何重啟恢復數據?
持久化性能問題和解決方案
RDB
RDB持久化是把當前進程數據生成快照保存到硬盤的過程, 觸發RDB持久化過程分為手動觸發和自動觸發。
RDB完成后會自動生成一個文件,保存在dir配置的指定目錄下,文件名是dbfileName指定。
Redis默認會采用LZF算法對生成的RDB文件做壓縮處理,壓縮后的文件遠遠小于內存大小,默認開啟。
手動觸發
手動觸發的命令有save和bgsave。
save:該命令會阻塞Redis服務器,直到RDB的過程完成,已經被廢棄,因此線上不建議使用。
bgsave:每次進行RDB過程都會fork一個子進程,由子進程完成RDB的操作,因此阻塞只會發生在fork階段,一般時間很短。
自動觸發
除了手動觸發RDB,Redis服務器內部還有如下幾個場景能夠自動觸發RDB:
根據我們的?save m n?配置規則自動觸發。
如果從節點執行全量復制操作, 主節點自動執行bgsave生成RDB文件并發送給從節點。
執行debug reload命令重新加載Redis時, 也會自動觸發save操作。
默認情況下執行shutdown命令時, 如果沒有開啟AOF持久化功能則自動執行bgsave。
RDB執行流程
RDB的主流方式就是bgsave,通過下圖我們來看看RDB的執行流程:
?
通過上圖可以很清楚RDB的執行流程,如下:
執行bgsave命令后,會先判斷是否存在AOF或者RDB的子進程,如果存在,直接返回。
父進程fork操作創建一個子進程,fork操作中父進程會被阻塞。
fork完成后,子進程開始根據父進程的內存生成臨時快照文件,完成后對原有的RDB文件進行替換。執行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執行的流程大致分為命令寫入、文件同步、文件重寫、重啟加載四個步驟,如下圖:
從上圖大致了解了AOF的執行流程,下面一一分析上述的四個步驟。
命令寫入
AOF命令寫入的內容直接是文本協議格式。例如set hello world這條命 令, 在AOF緩沖區會追加如下文本:
命令寫入是直接寫入到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內部是如何進行文件重寫的,如下圖:
看完上圖,大致了解了文件重寫的流程,對于重寫的流程,補充如下:
重寫期間,主線程并沒有阻塞,而是在執行其他的操作命令,依然會向舊的AOF文件寫入數據,這樣能夠保證備份的最終完整性,如果數據重寫失敗,也能保證數據不會丟失。
為了把重寫期間響應的寫入信息也寫入到新的文件中,因此也會為子進程保留一個緩沖區,防止新寫的文件丟失數據。
重寫是直接把當前內存的數據生成對應命令,并不需要讀取老的AOF文件進行分析、命令合并。
AOF文件直接采用的文本協議,主要是兼容性好、追加方便、可讀性高可認為修改修復。
無論是RDB還是AOF都是先寫入一個臨時文件,然后通過重命名完成文件的替換。
使用 AOF 持久化會讓 Redis 變得非常耐久:你可以設置不同的 fsync 策略,比如無 fsync ,每秒鐘一次 fsync ,或者每次執行寫入命令時 fsync 。AOF 的默認策略為每秒鐘 fsync 一次,在這種配置下,Redis 仍然可以保持良好的性能,并且就算發生故障停機,也最多只會丟失一秒鐘的數據( fsync 會在后臺線程執行,所以主線程可以繼續努力地處理命令請求)。
對于相同的數據集來說,AOF 文件的體積通常要大于 RDB 文件的體積。根據所使用的 fsync 策略,AOF 的速度可能會慢于 RDB。在一般情況下, 每秒 fsync 的性能依然非常高, 而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間。
數據恢復速度相對于RDB比較慢。
優先使用物理機或者高效支持fork操作的虛擬化技術。
控制Redis實例最大可用內存, fork耗時跟內存量成正比, 線上建議每個Redis實例內存控制在10GB以內。
合理配置Linux內存分配策略,避免物理內存不足導致fork失敗。
降低fork操作的頻率,如適度放寬AOF自動觸發時機,避免不必要的全量復制等。
如何保證 HBase 服務的高可用?看看這份 HBase 可用性分析與高可用實踐吧!
一文帶你認識keepalived,再帶你通關LVS+Keepalived!
那個分分鐘處理 10 億節點圖計算的 Plato,現在怎么樣了?
“谷歌殺手”發明者,科學天才 Wolfram
數據庫激蕩 40 年,深入解析 PostgreSQL、NewSQL 演進歷程
超詳細!一文告訴你 SparkStreaming 如何整合 Kafka !附代碼可實踐
5分鐘!就能學會以太坊 JSON API 基礎知識!
真香,朕在看了!
AOF的優點
AOF的缺點
AOF和RDB的區別
RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操作過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功后,再替換之前的文件,用二進制壓縮存儲。
AOF持久化以日志的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。
重啟加載
無論是RDB還是AOF都可用于服務器重啟時的數據恢復,執行流程如下圖:
上圖很清晰的分析了Redis啟動恢復數據的流程,先檢查AOF文件是否開啟,文件是否存在,再檢查RDB是否開啟,文件是否存在。
性能問題與解決方案
通過上面的分析,我們都知道RDB的快照、AOF的重寫都需要fork,這是一個重量級操作,會對Redis造成阻塞。因此為了不影響Redis主進程響應,我們需要盡可能降低阻塞。
那么如何減少fork操作的阻塞呢?
總結
本文介紹了Redis持久化的兩種不同的策略,大部分內容是運維人員需要掌握的,當然作為后端人員也是需要了解一下,畢竟小公司都是一人搞全棧,哈哈。
推薦閱讀
總結
以上是生活随笔為你收集整理的天天用Redis,持久化方案你又知道哪些?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 音视频应用驶入快车道 开发者如何快速追赶
- 下一篇: 针对提高48V 配电性能的诸多思考!