Redis持久化機制

關注公衆號:xy的技術圈linux

衆所周知,Redis是一個內存數據庫。但它與其它內存數據庫(如memcache)等有一個很大的區別,就是Redis能夠持久化到磁盤。有了持久化方案,Redis就能夠對數據進行備份、恢復、複製。redis

Redis提供了兩種持久化方案:RDB和AOF。在Redis 4.0中,提供了一個新特性:二者的混合持久化。下面將介紹Redis的各類持久化方案的原理和配置。數據庫

使用info persistence命令能夠查看當前全部有關持久化的信息:安全

1.png

RDB

原理

RDB持久化是經過快照方式來完成的。當達到觸發條件時,Redis會自動將內存全部數據二進制方式生成一份副本並存儲在硬盤上。服務器

在配置文件能夠配置當前配置的備份文件和目錄,使用config命令也能夠查看和設置:markdown

2.png

觸發條件

RDB分爲主動觸發被動觸發app

主動觸發指的是客戶端執行savebgsave命令會進行持久化。函數

執行save會使Redis處於阻塞狀態,不會響應任何其餘客戶端發來的請求,直到RDB快照文件執行完畢,須要謹慎使用。oop

bgsave即background save,後臺保存。當執行bgsave命令時,Redis會fork出一個子進程來執行快照操做。須要注意的是,在fork子進程的過程當中,Redis是阻塞的。而當子進程建立完成後,Redis就能夠繼續響應客戶端的請求了。性能

子進程建立完成之後,返回「Background saving started」。子進程根據主進程的內存副本建立臨時快照文件,當快照文件完成之後對原快照文件進行替換。替換完成後,子進程發送信號給主進程完成快照操做,主進程更新統計信息(info Persistence可查看),子進程退出。

3.png

被動觸發有好幾種狀況,下面分別介紹一下。

save m n規則觸發

在指定的m秒內,Redis中有n個鍵發生改變,則自動觸發bgsave。該規則默認在redis.conf中進行了配置,而且可組合使用,知足其中一個規則,則觸發bgsave

好比save 900 1,代表當900秒內至少有1個鍵發生改變時候,Redis會觸發bgsave操做。

flushall觸發

flushall命令用於清空數據庫,請慎用,當咱們使用了則代表咱們須要對數據進行清空,那Redis固然須要對快照文件也進行清空,因此會觸發bgsave。

shutdown觸發

Redis在關閉前處於安全角度將全部數據所有保存下來,以便下次啓動會恢復。可使用客戶端連入執行shutdown命令,也能夠直接使用腳本關閉Redis,都會在退出前先執行save。

shutdown命令還能夠傳遞一個參數save/nosave。若是使用nosave參數,則不會進行持久化,直接退出。

主從複製觸發

在Redis主從複製中,從節點執行全量複製操做,主節點會執行bgsave命令,並將rdb文件發送給從節點。

數據恢復

當Redis意外崩潰或者關閉再次啓動時,此時AOF持久化未開啓時(默認未開啓),將使用RDB快照文件恢復數據。關掉Redis服務再重啓,會發現日誌裏面有:

DB loaded from disk

配置

4.png

AOF

默認狀況下,Redis是關閉了AOF持久化,開啓AOF經過配置appendonly爲yes開啓,咱們修改配置文件或者在命令行直接使用config set修改,在用config rewrite同步到配置文件。經過客戶端修改好處是不用重啓Redis,AOF持久化直接生效。

5.png

原理

若是說RDB至關於數據庫的定時備份(冷備),那AOF就至關於數據庫的熱備。

經過前面的介紹會發現,若是使用RDB,在乎外狀況下,好比Redis服務忽然宕機,這個時候有些內存裏面的數據還沒來得及刷新進磁盤,就會致使一部分數據丟失。

AOF就是用來解決這個問題的。AOF是Append Only File的縮寫,AOF能夠將Redis執行的每一條寫命令追加到磁盤文件中,在Redis啓動時候優先選擇從AOF文件恢復數據。

由於每一次寫操做,都須要記錄到文件中,因此開啓AOF持久化會對性能有必定的影響,可是大部分狀況下這個影響是能夠接受的,咱們可使用讀寫速率高的硬盤提升AOF性能。與RDB持久化相比,AOF持久化數據丟失更少,其消耗內存更少(RDB方式執行bgsve會有內存拷貝)。

AOF實現本質是基於Redis通信協議,將命令以純文本的方式寫入到文件中。

redis協議:

首先Redis是以行來劃分,每行以\r\n行結束。每一行都有一個消息頭,消息頭共分爲5種分別以下:

+表示一個正確的狀態信息,具體信息是當前行後面的字符。

-表示一個錯誤信息,具體信息是當前行後面的字符。

*表示消息體總共有多少行,不包括當前行,後面是具體的行數。

$表示下一行數據長度,不包括換行符長度\r\n,後面則是對應的長度的數據。

: 表示返回一個數值,後面是相應的數字節符。

6.png

Redis AOF持久化過程

1 追加寫入

Redis將每一條寫命令以Redis通信協議添加至緩衝區aof_buf,這樣的好處在於在大量寫請求狀況下,採用緩衝區暫存一部分命令隨後根據策略一次性寫入磁盤,這樣能夠減小磁盤的I/O次數,提升性能。

2 同步命令到硬盤

當寫命令寫入aof_buf緩衝區後,Redis會將緩衝區的命令寫入到文件,Redis提供了三種同步策略,由配置參數appendfsync決定,下面是每一個策略所對應的含義:

  • no:不使用fsync方法同步,而是交給操做系統write函數去執行同步操做,在linux操做系統中大約每30秒刷一次緩衝。
  • always:表示每次有寫操做都調用fsync方法強制內核將數據寫入到aof文件。
  • everysec:數據將使用調用操做系統write寫入文件,並使用fsync每秒一次從內核刷新到磁盤。 這是折中的方案,兼顧性能和數據安全,因此Redis默認推薦使用該配置

3 文件重寫(bgrewriteaof)

當開啓的AOF時,隨着時間推移,AOF文件會愈來愈大,固然Redis也對AOF文件進行了優化,即觸發AOF文件重寫條件的時候,Redis將使用bgrewriteaof對AOF文件進行重寫。這樣的好處在於減小AOF文件大小,同時有利於數據的恢復。重寫策略

  • 重複或無效的命令不寫入文件
  • 過時的數據再也不寫入文件
  • 多條命令合併寫入(當多個命令能合併一條命令時候會對其優化合並做爲一個命令寫入,例如「RPUSH list1 a; RPUSH list1 b" 合併爲「RPUSH list1 a b」 )

重寫

AOF文件重寫過程與RDB快照bgsave工做過程有點類似,都是經過fork子進程,由子進程完成相應的操做,一樣的在fork子進程簡短的時間內,Redis是阻塞的,過程如圖:

重寫

過程說明:

  1.開始bgrewriteaof,判斷當前有沒有bgsave命令(RDB持久化)/bgrewriteaof在執行,假若有,則這些命令執行完成之後再執行。

  2.主進程fork出子進程,在這一個短暫的時間內,redis是阻塞的。

  3.主進程fork完子進程繼續接受客戶端請求,全部寫命令依然寫入AOF文件緩衝區並根據appendfsync策略同步到磁盤,保證原有AOF文件完整和正確。因爲fork的子進程僅僅只共享主進程fork時的內存,所以Redis使用採用重寫緩衝區(aof_rewrite_buf)機制保存fork以後的客戶端的寫請求,防止新AOF文件生成期間丟失這部分數據。此時,客戶端的寫請求不只僅寫入原來aof_buf緩衝,還寫入重寫緩衝區(aof_rewrite_buf)。

  4.子進程經過內存快照,按照命令重寫策略寫入到新的AOF文件。

  4.1子進程寫完新的AOF文件後,向主進程發信號,父進程更新統計信息。

  4.2主進程把aof_rewrite_buf中的數據寫入到新的AOF文件。

  5.使用新的AOF文件覆蓋舊的AOF文件,標誌AOF重寫完成。

重寫的觸發條件:

AOF文件觸發條件可分爲手動觸發和自動觸發。

手動觸發:客戶端執行bgrewriteaof命令。

自動觸發:自動觸發經過如下兩個配置協做生效:

  • auto-aof-rewrite-min-size: AOF文件最小重寫大小,只有當AOF文件大小大於該值時候纔可能重寫,4.0默認配置64mb。
  • auto-aof-rewrite-percentage:當前AOF文件大小和最後一次重寫後的大小之間的比率等於或者等於指定的增加百分比,如100表明當前AOF文件是上次重寫的兩倍時候才重寫。 

Redis開啓在AOF功能開啓的狀況下,會維持如下三個變量

  • 記錄當前AOF文件大小的變量aof_current_size。
  • 記錄最後一次AOF重寫以後,AOF文件大小的變量aof_rewrite_base_size。
  • 增加百分比變量aof_rewrite_perc。

每次當serverCron(服務器週期性操做函數)函數執行時,它會檢查如下條件是否所有知足,若是所有知足的話,就觸發自動的AOF重寫操做:

  • 沒有BGSAVE命令(RDB持久化)/AOF持久化在執行;
  • 沒有BGREWRITEAOF在進行;
  • 當前AOF文件大小要大於server.aof_rewrite_min_size的值;
  • 當前AOF文件大小和最後一次重寫後的大小之間的比率等於或者大於指定的增加百分比(auto-aof-rewrite-percentage參數)

數據恢復

當AOF開啓時候,Redis數據恢復優先選用AOF進行數據恢復。關掉Redis服務再重啓,會發現日誌裏面有:

DB loaded from append only file

配置

7.png

RDB與AOF對比

RDB的優勢:

RDB文件體積小,所以在傳輸速度上較快,適合災難恢復。RDB使Redis性能更高,子進程處理保存工做。在恢復大數據集時比AOF恢復速度快。

AOF的優勢:

數據更完整和安全,秒級數據丟失(取決於appendfsync策略)。兼容性高,由於是基於Redis通信協議造成的明文文件,因此容易閱讀,且任何版本的Redis都兼容。

混合持久化

混合持久化是Redis 4.0纔有的功能。

混合持久化一樣也是經過bgrewriteaof完成的,不一樣的是當開啓混合持久化時,fork出的子進程先將共享的內存副本以RDB方式寫入AOF文件,而後在將重寫緩衝區的增量命令以AOF方式寫入到文件,寫入完成後通知主進程更新統計信息,並將新的AOF文件替換舊的的AOF文件。

簡單的說:新的AOF文件前半段是RDB格式的全量數據,後半段是AOF格式的增量數據

數據恢復

使用混合持久化後,Redis依然優先加載AOF文件。可能有兩種狀況:

  • AOF文件開頭是RDB的格式,先加載RDB部分的內容,再加載剩餘的AOF
  • AOF文件開頭不是RDB的格式,直接加載整個AOF文件

配置

4.0版本的混合持久化默認關閉的,經過aof-use-rdb-preamble配置參數控制,yes則表示開啓,no表示禁用,默認是no,可經過config set修改。

混合模式能夠結合AOF和RDB的優勢,可以快速加載的同時避免丟失過多的數據。

認真寫文章,用心作分享。

我的網站:yasinshaw.com

公衆號:xy的技術圈

相關文章
相關標籤/搜索