Redis持久化(RDB與AOF)

​ 咱們都知道Redis的數據都存在內存裏,若是忽然宕機,數據就會所有丟失,所以必須有一種機制來保證Redis的數據不會由於故障而丟失,這種機制就是Redis的持久化機制。html

​ Redis的持久化機制主要是有兩種,第一種是RDB快照,第二種是AOD日誌。若是咱們的服務器開啓了AOF持久化功能,那麼服務器會優先使用AOF文件來還原數據庫的狀態。只有在AOF持久化功能處於關閉的狀態的時候,服務器才能使用RDB文件來還原數據庫狀態。面試

服務器載入文件時的判斷流程

RDB持久化

​ RDB持久化是經過快照來實現的,在指定的時間間隔內將內存的數據集快照寫入磁盤,恢復的時候就是將快照文件讀取到內存中。redis

​ 但是咱們知道Redis是單線程的,內存快照又要要求Redis進行文件IO操做,但是文件IO操做時不能使用多路複用API,這意味着咱們單線程要處理服務器上的請求,還有處理文件IO操做,顯然是會拖垮服務器請求的性能。數據庫

​ 咱們是如何解決的呢,這用到了COW(Copy On Write)來實現持久化。這樣有一篇關於COW比較詳細。(COW奶牛!Copy On Write機制瞭解一下緩存

​ Redis會單首創建(Fork)一個子進程來進行持久化,會先將數據寫入到一個臨時文件中,待持久化過程都結束了,再用這個臨時文件替換上次持久化好的文件。整個過程當中,主進程是不進行任何IO操做。這就確保了極高的性能,若是須要進行大規模數據的恢復,且對於數據恢復的完整性不是很是敏感,那麼RDB方式比AOF方式更加的高效。RDB的缺點就是最後一次持久化後的數據可能丟失。(默認的RDB文件爲dump.rdb)安全

持久化快照保存過程

​ 子進程作數據持久化,它不會修改現有的內存數據結構,它只是對數據結構進行遍歷讀取,而後序列化寫到磁盤中。可是父進程不同,它必須持續服務客戶端請求,而後對內存數據結構進行不間斷的修改。那咱們不可能對同一片內存進行操做,因此用到了寫入時複製。bash

​ 數據段是由不少操做系統的頁面組合而成,當父進程對其中一個頁面的數據進行修改時,會將被共享內存複製一份分離出來,而後對這個複製的頁面進行修改。這時子進程相應的頁面是沒有變化的,仍是進程產生時那一瞬間的數據。因此才被稱爲快照的緣由。(具體流程對應上圖操做)服務器

觸發條件

咱們上面也提到了RDB的操做,那麼何時會觸發呢?數據結構

指令觸發:併發

  • SAVE:馬上redis數據持久化,其餘所有阻塞
  • BGSAVE:redis會在後臺異步進行快照操做,同時還可響應客戶端的請求,可用命令 lastsave 獲取最後一次成功執行快照的時間
  • FLUSHALL:清空命令也會觸發持久化操做,但dump.rdb文件中是空的,無心義
  • SHUTDOWN :關閉數據庫命令也會觸發redis持久化操做 ,前提是沒有開啓AOF持久化
  • DEBUG RELAOD:用該命令從新加載Redis時,也會自動觸發save操做

配置文件觸發:

  • 在咱們的Redis文件的redis.conf文件中能夠設置save 指定在 seconds 秒內有 changes 次跟新操做,就進行一次持久化。(用的也是BGSAVE)
#默認的配置以下:
save 900 1  # 900秒內有一個更改就觸發
save 300 10 # 300秒內有10個更改就觸發
save 60 10000 # 60秒內有10000個更改就觸發
複製代碼
  • 若是從節點執行全量複製操做,主節點自動執行BGSAVE 生成RDB文件併發送給從節點

優缺點

優勢:

  • 對數據的完整性要求不高

  • 由於主進程不進行任何的IO操做,因此對數據的大規模恢復有着極高的性能

缺點:

  • fork進程的時候,會佔用必定的內存空間
  • 須要必定的時間間隔來進行操做,若是redis意外宕機了,那麼最後一次修改的數據就沒有了

恢復持久化文件:

​ 將備份文件移動至 dir 參數配置持久化文件的目錄下,並將文件名改成 dbfilename 參數配置持久化參數的文件名,而後啓動數據庫便可恢復數據。

​ 若 dump.rdb 文件存在異常,數據恢復將報錯。可以使用命令 redis-check-dump --fix 命令對 dump.rdb 持久化文件進行修復,而後重啓redis服務便可。

AOF(Append-Only-File)持久化

​ 以獨立日誌的方式記錄每次寫命令,寫入的內容直接是文本協議格式,重啓時再從新執行AOF文件中的命令達到恢復數據的目的,解決了數據持久化實時性問題。

appendonly no # 默認爲no不開啓,改成yes爲開啓
複製代碼

若是開啓了AOF,默認的文件名是appendonly.aof,路徑與RDB文件同級。

ReWrite重寫機制

**引入重寫機制背景:**AOF採用文件追加的方式,將致使文件愈來愈大,故新增重寫機制。當AOF文件大小超過所設置的閾值時,Redis將啓動AOF內容壓縮,只保留能夠恢復數據的最小指令集。

**原理:**Redis 提供了 bgrewriteaof 指令用於對 AOF 日誌進行瘦身(重寫)。其原理就是開闢一個子進程對內存進行遍歷轉換成一系列 Redis 的操做指令,序列化到一個新的 AOF 日誌文件中。序列化完畢後再將操做期間發生的增量AOF 日誌追加到這個新的 AOF 日誌文件中,追加完畢後就當即替代舊的 AOF 日誌文件了,瘦身工做就完成了。

AOF的具體工做流程:

  1. 命令的實時寫入,調用到命令

  2. 全部的寫入命令追加到aof_buf(緩衝區)中

  3. AOF緩衝區根據對應的策略向硬盤作同步操做

  4. 隨着AOF文件愈來愈大,須要按期對AOF文件進行重寫,壓縮,父進程執行fork建立子進程,由子進程根據內存快照執行AOF重寫,父進行繼續響應後面的命令,在子進程完成重寫後,父進程再把新增的寫入命令寫入到新的AOF文件中

  5. Redis服務重啓,加載AOF文件進行數據恢復

觸發機制

主動觸發:

使用bgrewriteaof命令

被動觸發:

配置文件設置,有兩個參數

# 重寫時,是否可使用appendfsync(接受客戶端的操做),默認爲no,保證數據安全性
no-appendfsync-on-rewrite no

#redis會記錄上次重寫AOF文件的大小,當AOF文件增長至上次重寫文件的100%倍,且大小大於64MB時,觸發AOF重寫
#auto-aof-rewrite-percentage 用於設置相對於上次AOF文件百分比
auto-aof-rewrite-percentage 100
#auto-aof-rewrite-min-size 用於設置另外一基準值
auto-aof-rewrite-min-size 64mb
複製代碼

優缺點

優勢:

  • 若是每一次都修改都同步的話,能夠更好的保持數據完整性
  • 若是每秒都同步一次的話,若是發生宕機什麼的話,最多可能丟失一秒的數據
  • 若是從不一樣步的話,具備效率最高的特色

缺點:

  • 相對於數據文件來講,AOF遠遠大於RDB,修復的速度也比RDB慢
  • AOF運行效率也比RDB慢,因此咱們Redis默認的配置就是RDB持久化

fsync同步策略

上面咱們也說到了AOF緩衝區會根據對應的策略向硬盤作同步操做,那麼具體有哪些同步策略呢?

AOF緩衝區同步策略,經過參數appendfsync控制,具體有三個配值

選項的值 說明 其餘
always 命令寫入aof_buf後調用系統fsync操做同步到AOF文件,fsync完成後線程返回 每次寫入都要同步AOF文件,在通常的SATA硬盤很難達到高性能
everysec 命令寫入aof_buf後調用系統write操做,write完成後線程返回。fsync同步操做由線程每秒調用一次(建議策略) 默認同步策略
no 命令寫入aof_buf後調用系統write操做,不對AOF文件作fsync同步,同步硬盤操做由操做系統負責,一般同步週期最長30秒 操做系統每次同步AOF文件的週期不可控,並且會加大每次同步硬盤的數據量,雖然提高了性能,但數據安全性沒法保證

**補充:**若是同時開啓了RDB和AOF的話,咱們是優先加載AOF。由於AOF保存的數據更加完整,最多也就損失1s的數據。

關於AOF的面試題

AOF爲何直接採用文本協議格式?

  • 文本協議具備良好的兼容性

  • 開啓AOF後,全部寫入命令都包含追加操做,直接採用協議格式,避免二次處理開銷

  • 文本協議具備可讀性,方便直接修改和處理

AOF 爲何把命令追加到aof_buf中

  • 寫入緩存區aof_buf中,能提升性能,而且Redis提供了多種緩存區同步硬盤策略

重寫後的AOF文件爲何能夠變小?

  • 進程內已經超時的數據再也不寫入文件

  • 舊的AOF文件含有無效命令,重寫使用進程內數據直接生成,新的AOF文件只保留最終數據的寫入命令

  • 多條寫命令能夠合併爲一個,爲了防止溢出,以64個元素爲界拆分爲多條

參考資料

《Redis設計與實現》

《Redis深度歷險:核心原理與應用實踐》

Redis之Redis持久化

Redis如何作持久化

阿提說說

相關文章
相關標籤/搜索