Redis持久化RDB&AOF

RDB快照(Redis DataBase)

RDB是一種快照存儲持久化方式,具體就是將Redis某一時刻的內存數據保存到硬盤的文件當中,默認保存的文件名爲dump.rdb,而在Redis服務器啓動時,會從新加載dump.rdb文件的數據到內存當中恢復數據。redis

開啓RDB持久化方式

開啓RDB持久化方式很簡單,客戶端能夠經過向Redis服務器發送save或bgsave命令讓服務器生成rdb文件,或者經過服務器配置文件指定觸發RDB條件。每次執行都會將全部redis內存快照到一個新的rdb文件裏,並覆蓋原有rdb快照文件。安全

方式一:save命令服務器

# 同步數據到磁盤上
> save

attachments-2021-03-ueDioY3I60418ed328d1a.jpg

當客戶端向服務器發送save命令請求進行持久化時,服務器會阻塞save命令以後的其餘客戶端的請求,直到數據同步完成。 若是數據量太大,同步數據會執行好久,而這期間Redis服務器也沒法接收其餘請求,因此,最好不要在生產環境使用save命令。app

方式二:bgsave命令異步

# 異步保存數據集到磁盤上
> bgsave

attachments-2021-03-vmA48oBx60418edc0b550.jpg

  • 當客戶端發服務發出bgsave命令時,Redis服務器主進程會forks一個子進程來解決數據同步問題,在將數據保存到rdb文件以後,子進程會退出。
  • 因此,與save命令相比,Redis服務器在處理bgsave採用子線程進行IO寫入,而主進程仍然能夠接收其餘請求,但forks子進程是同步的,因此forks子進程時,同樣不能接收其餘請求,這意味着,若是forks一個子進程花費的時間過久(通常是很快的),bgsave命令仍然有阻塞其餘客戶的請求的狀況發生。
  • 咱們能夠控制單個Redis實例的最大內存,來儘量下降Redis在fork時的事件消耗。以及上面提到的自動觸發的頻率減小fork次數,或者使用手動觸發,根據本身的機制來完成持久化。

方式三:經過配置文件自動觸發性能

自動觸發的場景主要是有如下幾點:url

  • 1.根據咱們的 save m n 配置規則自動觸發;
  • 2.從節點全量複製時,主節點發送rdb文件給從節點完成複製操做,主節點會觸發 bgsave;
  • 3.執行 debug reload 時;
  • 4.執行shutdown時,若是沒有開啓aof,也會觸發。

這裏咱們講的是根據配置文件自動觸發:spa

# 時間策略
#關閉RDB只須要將全部的save保存策略註釋掉便可
save 900 1   #900s內若是有1條數據寫入,就產生RDB快照
save 300 10 #300s內有10條數據寫入,就產生RDB快照 
save 60 10000  #60s內若是有10000條數據寫入,就產生RDB快照
# 文件名稱
dbfilename dump.rdb
# 文件保存路徑
dir /var/lib/redis/6379
# 若是持久化出錯,主進程是否中止寫入
stop-writes-on-bgsave-error yes
# 是否壓縮
# 建議沒有必要開啓,畢竟Redis自己就屬於CPU密集型服務器,再開啓壓縮會帶來更多的CPU消耗,相比硬盤成本,CPU更值錢。
rdbcompression no
# 導入時是否檢查
rdbchecksum yes

save和bgsave對比

attachments-2021-03-fYUHd70060418ee5e9417.png

配置文件自動生成rdb文件後臺使用的是bgsave方式。操作系統

RDB文件

前面介紹了三種讓服務器生成rdb文件的方式,不管是由主進程生成仍是子進程來生成,其過程以下:.net

  • 生成臨時rdb文件,並寫入數據。
  • 完成數據寫入,用臨時文件替代正式rdb文件。
  • 刪除原來的db文件。

COW寫時複製(copy-on-write)

fork建立出的子進程,與父進程共享內存空間。也就是說,若是子進程不對內存空間進行寫入操做的話(Redis的子進程只作數據落盤的操做,也不會去寫數據),內存空間中的數據並不會複製給子進程,這樣建立子進程的速度就很快了!(不用複製,直接引用父進程的物理空間,玩的是指針)。

attachments-2021-03-JwXj7f9460418eee92bae.png

當Redis父進程修改數據時,父進程會將原先的數據複製一份生成新的副本,而後修改父進程的指針,指向新的數據,此時父進程修改的新的數據不會影響到子進程。此時子進程的指針仍然指向舊的數據,子進程看到的數據仍是bgsave時候的數據。當下一次執行bgsave時,新fork出來的子進程指針纔會指向此次新的數據。

attachments-2021-03-TbpELAOx60418ef746def.jpg

AOF(append-only file)

與RDB存儲某個時刻的快照不一樣,AOF持久化方式會記錄客戶端對服務器的每一次寫操做命令,並將這些寫操做以追加的方式保存到之後綴爲aof文件中,在Redis服務器重啓時,會加載並運行aof文件的命令,以達到恢復數據的目的。

開啓AOF持久化的方式

方式一:bgrewriteaof命令

> bgrewriteaof

方式二:經過配置文件自動觸發

Redis默認不開啓AOF持久化方式,咱們能夠在配置文件中開啓並進行更加詳細的配置:

#開啓aof
appendonly yes
# 文件名稱
appendfilename "appendonly.aof"
# 同步方式
#appendfsync always #每次有新命令追加到 AOF 文件時就執行一次 fsync ,很是慢,也很是安全。
appendfsync everysec #默認方式,每秒 fsync 一次,足夠快,而且在故障時只會丟失 1 秒鐘的數據。
#appendfsync no  #從不 fsync ,將數據交給操做系統來處理。更快,也更不安全的選擇。

重寫

AOF將客戶端的每個寫操做都追加到aof文件末尾,好比對一個key屢次執行incr命令,這時候,aof保存每一次命令到aof文件中,aof文件會變得很是大。

127.0.0.1:6379> INCR readcount
(integer) 1
127.0.0.1:6379> INCR readcount
(integer) 2
127.0.0.1:6379> INCR readcount
(integer) 3
127.0.0.1:6379> INCR readcount
(integer) 4
127.0.0.1:6379> INCR readcount
(integer) 5

這是一種resp協議格式數據,星號後面的數字表明命令有多少個參數,$號後面的數字表明這個參數有幾個字符

[root@redis 6379]# cat appendonly.aof
*2
$6
SELECT
$1
0
*2
$4
INCR
$9
readcount
*2
$4
INCR
$9
readcount
*2
$4
INCR
$9
readcount
*2
$4
INCR
$9
readcount
*2
$4
INCR
$9
readcount

手動執行重寫命令BGREWRITEAOF:

127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started

重寫後AOF文件裏以下,將多個incr命令進行了合併:

[root@redis 6379]# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$9
readcount
$1
5

重寫配置參數

AOF重寫redis會fork出一個子進程去作(與bgsave命令相似),不會對redis正常命令處理有太多影響:

auto‐aof‐rewrite‐min‐size 64mb #aof文件至少要達到64M纔會自動重寫,文件過小恢復速度原本就 很快,重寫的意義不大
auto‐aof‐rewrite‐percentage 100 #aof文件自上一次重寫後文件大小增加了100%則再次觸發重寫,例如上一次重寫的大小是64M,那麼下一次達到128M再作重寫

AOF重寫流程圖

attachments-2021-03-JIwtkAYi60418f0330074.jpg

  • 在重寫期間,因爲主進程依然在響應命令,爲了保證最終備份的完整性;所以它依然會寫入舊的AOF file中,若是重寫失敗,可以保證數據不丟失。
  • 爲了把重寫期間響應的寫入信息也寫入到新的文件中,所以也會爲子進程保留一個buf,防止新寫的file丟失數據。
  • 重寫是直接把當前內存的數據生成對應命令,並不須要讀取老的AOF文件進行分析、命令合併。
  • 不論是RDB仍是AOF都是先寫入一個臨時文件,而後經過 rename 完成文件的替換工做。

混合持久化

重啓 Redis 時,咱們不多使用 RDB來恢復內存狀態,由於會丟失大量數據。咱們一般使用 AOF 日誌重放,可是重放 AOF 日誌性能相對 RDB來講要慢不少,這樣在 Redis 實例很大的狀況下,啓動須要花費很長的時間。Redis 4.0 爲了解決這個問題,帶來了一個新的持久化選項——混合持久化。經過以下配置能夠開啓混合持久化(前提必須先開啓aof):

aof‐use‐rdb‐preambleyes #開啓混合持久化

若是開啓了混合持久化,AOF在重寫時,再也不是單純將內存數據轉換爲RESP命令寫入AOF文件,而是將重寫這一刻以前的內存作RDB快照處理,而且將RDB快照內容和增量的AOF修改內存數據的命令存在一塊兒,都寫入新的AOF文件,新的文件一開始不叫appendonly.aof,等到重寫完新的AOF文件纔會進行更名,覆蓋原有的AOF文件,完成新舊兩個AOF文件的替換。因而在 Redis 重啓的時候,能夠先加載 RDB 的內容,而後再重放增量 AOF 日誌就能夠徹底替代以前的 AOF 全量文件重放,所以重啓效率大幅獲得提高。

127.0.0.1:6379> set k 1
OK
127.0.0.1:6379> set k 2
OK
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started

查看此時的appendonly.aof文件:此時存放的是RDB的內容

[root@redis 6379]# cat appendonly.aof
REDIS0009�    redis-ver5.0.7�
�edis-bits�@�ctime�%y�_used-mem��
 aof-preamble���k�    readcount��    R��i9$�[root@redis 6379]#

若是新增長了數據:

127.0.0.1:6379> set k 3
OK

那麼新的數據會覺得RESP命令的方式追加在後面:

[root@redis 6379]# cat appendonly.aof
REDIS0009�    redis-ver5.0.7�
�edis-bits@�ctime�%y�_used-mem��
 aof-preamble���k�    readcount��    R��i9$�*2
$6
SELECT
$1
0
*3
$3
set
$1
k
$1
3

混合持久化AOF文件結構以下:

attachments-2021-03-y6VaqWar60418f0ea44d2.jpg

從持久化中恢復數據

數據的備份、持久化作完了,咱們如何從這些持久化文件中恢復數據呢?若是一臺服務器上有既有RDB文件,又有AOF文件,該加載誰呢?

其實想要從這些文件中恢復數據,只須要從新啓動Redis便可。咱們仍是經過圖來了解這個流程:

attachments-2021-03-NK2osdlJ60418f17a40a7.jpg

啓動時會先檢查AOF文件是否存在,若是不存在就嘗試加載RDB。那麼爲何會優先加載AOF呢?由於AOF保存的數據更完整,經過上面的分析咱們知道AOF基本上最多損失1s的數據。

RBD和AOF對比

attachments-2021-03-HY7CZ1Xg60418f1f79024.jpg

另外RBD不支持拉鍊,只有一個dump.rdb文件。

 

相關文章
相關標籤/搜索