咱們都知道Redis的數據都存在內存裏,若是忽然宕機,數據就會所有丟失,所以必須有一種機制來保證Redis的數據不會由於故障而丟失,這種機制就是Redis的持久化機制。html
Redis的持久化機制主要是有兩種,第一種是RDB快照,第二種是AOD日誌。若是咱們的服務器開啓了AOF持久化功能,那麼服務器會優先使用AOF文件來還原數據庫的狀態。只有在AOF持久化功能處於關閉的狀態的時候,服務器才能使用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 900 1 # 900秒內有一個更改就觸發
save 300 10 # 300秒內有10個更改就觸發
save 60 10000 # 60秒內有10000個更改就觸發
複製代碼
優勢:
對數據的完整性要求不高
由於主進程不進行任何的IO操做,因此對數據的大規模恢復有着極高的性能
缺點:
恢復持久化文件:
將備份文件移動至 dir 參數配置持久化文件的目錄下,並將文件名改成 dbfilename 參數配置持久化參數的文件名,而後啓動數據庫便可恢復數據。
若 dump.rdb 文件存在異常,數據恢復將報錯。可以使用命令 redis-check-dump --fix 命令對 dump.rdb 持久化文件進行修復,而後重啓redis服務便可。
以獨立日誌的方式記錄每次寫命令,寫入的內容直接是文本協議格式,重啓時再從新執行AOF文件中的命令達到恢復數據的目的,解決了數據持久化實時性問題。
appendonly no # 默認爲no不開啓,改成yes爲開啓
複製代碼
若是開啓了AOF,默認的文件名是appendonly.aof,路徑與RDB文件同級。
**引入重寫機制背景:**AOF採用文件追加的方式,將致使文件愈來愈大,故新增重寫機制。當AOF文件大小超過所設置的閾值時,Redis將啓動AOF內容壓縮,只保留能夠恢復數據的最小指令集。
**原理:**Redis 提供了 bgrewriteaof 指令用於對 AOF 日誌進行瘦身(重寫)。其原理就是開闢一個子進程對內存進行遍歷轉換成一系列 Redis 的操做指令,序列化到一個新的 AOF 日誌文件中。序列化完畢後再將操做期間發生的增量AOF 日誌追加到這個新的 AOF 日誌文件中,追加完畢後就當即替代舊的 AOF 日誌文件了,瘦身工做就完成了。
AOF的具體工做流程:
命令的實時寫入,調用到命令
全部的寫入命令追加到aof_buf(緩衝區)中
AOF緩衝區根據對應的策略向硬盤作同步操做
隨着AOF文件愈來愈大,須要按期對AOF文件進行重寫,壓縮,父進程執行fork建立子進程,由子進程根據內存快照執行AOF重寫,父進行繼續響應後面的命令,在子進程完成重寫後,父進程再把新增的寫入命令寫入到新的AOF文件中
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緩衝區會根據對應的策略向硬盤作同步操做,那麼具體有哪些同步策略呢?
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_buf中
重寫後的AOF文件爲何能夠變小?
進程內已經超時的數據再也不寫入文件
舊的AOF文件含有無效命令,重寫使用進程內數據直接生成,新的AOF文件只保留最終數據的寫入命令
多條寫命令能夠合併爲一個,爲了防止溢出,以64個元素爲界拆分爲多條
《Redis設計與實現》
《Redis深度歷險:核心原理與應用實踐》
阿提說說