RDB快照(Redis DataBase)
RDB是一種快照存儲持久化方式,具體就是將Redis某一時刻的內存數據保存到硬盤的文件當中,默認保存的文件名爲dump.rdb,而在Redis服務器啓動時,會從新加載dump.rdb文件的數據到內存當中恢復數據。redis
開啓RDB持久化方式
開啓RDB持久化方式很簡單,客戶端能夠經過向Redis服務器發送save或bgsave命令讓服務器生成rdb文件,或者經過服務器配置文件指定觸發RDB條件。每次執行都會將全部redis內存快照到一個新的rdb文件裏,並覆蓋原有rdb快照文件。安全
方式一:save命令服務器
# 同步數據到磁盤上 > save
當客戶端向服務器發送save命令請求進行持久化時,服務器會阻塞save命令以後的其餘客戶端的請求,直到數據同步完成。 若是數據量太大,同步數據會執行好久,而這期間Redis服務器也沒法接收其餘請求,因此,最好不要在生產環境使用save命令。app
方式二:bgsave命令異步
# 異步保存數據集到磁盤上 > bgsave
- 當客戶端發服務發出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對比
配置文件自動生成rdb文件後臺使用的是bgsave方式。操作系統
RDB文件
前面介紹了三種讓服務器生成rdb文件的方式,不管是由主進程生成仍是子進程來生成,其過程以下:.net
- 生成臨時rdb文件,並寫入數據。
- 完成數據寫入,用臨時文件替代正式rdb文件。
- 刪除原來的db文件。
COW寫時複製(copy-on-write)
fork建立出的子進程,與父進程共享內存空間。也就是說,若是子進程不對內存空間進行寫入操做的話(Redis的子進程只作數據落盤的操做,也不會去寫數據),內存空間中的數據並不會複製給子進程,這樣建立子進程的速度就很快了!(不用複製,直接引用父進程的物理空間,玩的是指針)。
當Redis父進程修改數據時,父進程會將原先的數據複製一份生成新的副本,而後修改父進程的指針,指向新的數據,此時父進程修改的新的數據不會影響到子進程。此時子進程的指針仍然指向舊的數據,子進程看到的數據仍是bgsave時候的數據。當下一次執行bgsave時,新fork出來的子進程指針纔會指向此次新的數據。
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重寫流程圖
- 在重寫期間,因爲主進程依然在響應命令,爲了保證最終備份的完整性;所以它依然會寫入舊的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文件結構以下:
從持久化中恢復數據
數據的備份、持久化作完了,咱們如何從這些持久化文件中恢復數據呢?若是一臺服務器上有既有RDB文件,又有AOF文件,該加載誰呢?
其實想要從這些文件中恢復數據,只須要從新啓動Redis便可。咱們仍是經過圖來了解這個流程:
啓動時會先檢查AOF文件是否存在,若是不存在就嘗試加載RDB。那麼爲何會優先加載AOF呢?由於AOF保存的數據更完整,經過上面的分析咱們知道AOF基本上最多損失1s的數據。
RBD和AOF對比
另外RBD不支持拉鍊,只有一個dump.rdb文件。