1.為什么需要持久化
redis中的數據全部保存在內存中,如果突然宕機,數據就會全部丟失.為了防止這種事情發生,我們需要一種機制保證在宕機發生之后,我們重啟服務內存中的數據還可以恢復,這就是redis的持久化機制.
redis提供了三種持久化機制分別為RDB(Redis DataBase)方式,AOF(Append Only File)方式和混合模式.
2.RDB方式
rdb模式的特點是使用二進制的格式全量的保存redis中的數據,在存儲上非常的緊湊,從而使可以控制文件的大小不至於太大.
1.觸發方式
1.手動觸發:
1.1 save
該命令使用主線程進行快照生成,所以在命令執行期間redis不能處理其他命令,直到rdb過程結束,所以在生產環境中盡量少使用該命令.
1.2 bgsave
bgsave命令執行的時候會fork出子線程,主線程會直接返回,生成rbd快照的工作交由子線程處理,所以該命令只會在fork子線程的時候阻塞,這個過程一般很短,所以如果想要生成rdb快照,可以考慮使用bgsave命令代替save命令,減少阻塞時間.
2.自動觸發
2.1 在redis.conf中配置了save m n 參數.即在m秒內有n次修改則自動生成rdb文件.
2.2 主從復制.當從服務器第一次連接上主服務器時,首先需要一次全量的復制,這時候會在主服務器上觸發rdb生成快照
2.3 在優雅的關閉redis服務的時候,如果沒有開啟其他持久化機制,redis會默認進行bgsave操作.
2.原理
當redis觸發了快照生成操作時,主進程判斷當前是否已經存在正在執行的子進程,如果存在,那么主進程直接返回,如果不存在正在執行的子進程,那么就fork一個新的子進程進行持久化數據,fork過程是阻塞的,fork操作完成后主進程即可執行其他操作;子進程先將數據寫入到臨時的rdb文件中,待快照數據寫入完成后再原子替換舊的rdb文件;同時發送信號給主進程,通知主進程rdb持久化完成,主進程更新相關的統計信息。主線程調用glibc的fork方法fork出子線程,在子線程fork出的一瞬間,主線程和子線程共享內存中的數據,當主線程接收其他命令對數據進行操作的時候,主線程會復制出共享的數據頁面,,然后進行修改,這樣不會對子線程中的內存頁造成影響,子線程中的數據頁中的數據還是剛從主線程中分離出來的樣子,這樣就可以保證子線程生成的rdb文件為主線程fork出子線程的一瞬間的快照.
3.配置
save m n
當m秒之內有n個數據修改操作,則自動生成rdb文件,如果想禁用rdb功能,只需要配置 save "" 即可
rdbcompression yes|no
當進行rdb生成快照時,是否對生成的文件進行壓縮.因為redis時cpu密集型服務,而壓縮文件也會照成大量的cpu消耗,如果redis上的請求較多建議不開啟該操作,
dir path
rdb文件保存的路徑
dbfilename fileName
設置生成的rdb文件的名稱,和上面的dir參數配合使用
stop-writes-on-bgsave-error yes|no
當rdb操作失敗是,主線程是否還可以繼續接收寫相關命令,如果設置為yes,則當rbd失敗時,redis不在接收寫相關的命令
4.優點
1.rdb為全量備份,而且是以二進制的格式保存的,所以rdb文件占用空間會比較小,所以非常適合容災備份.
2.rdb文件中保存的是數據,所以恢復速度也很快.
3.在執行bgsave的時候是由主線程fork出子線程進行快照生成,所以並不會影響主線程執行其他操作,只會在fork出子線程的時候阻塞.
5.缺點
1.rdb中保存的是二進制數據所以無法直接查看文件的內容
2.rdb並不能實時的保存數據,在rdb文件中會丟失執行快照操作的命令之后的其他寫數據操作.
3.rdb文件並不能很好的兼容redis的所有版本,不同版本之間的rdb文件可能並不能通用.
4.aof
原理
和rdb中保存二進制格式的內存中的數據不同,aof模式保存的時redis執行的寫命令,即aof中保存了redis自動開始到當前所有的寫相關的命令,當redis需要恢復數據時,只需要重復執行以下這些命令就可以了.
Redis 會在收到客戶端修改指令后,先進行參數校驗,如果沒問題,就立即將該指令文本存儲到 AOF 日志中,也就是先存到磁盤,然后再執行指令。這樣即使遇到突發宕機,已經存儲到 AOF 日志的指令進行重放一下就可以恢復到宕機前的狀態.
因為aof日志寫入和命令的執行都是主線程完成的,所以開啟aof之后不可避免的將影響主線程執行命令的效率.
當redis將aof日志內容寫入aof文件的時候,其實只是寫入了一個文件的緩沖區中,具體什么時間將緩沖區中的內容真正寫入到磁盤上這個可以選擇由redis觸發或者由系統決定,這個可以配置,詳情可以參考配置小節.
重寫
因為aof文件中記錄的是操作日志,所以aof會在redis運行時間長了之后變的很大.當aof文件過大時會造成aof文件繼續寫入的效率變低,並且如果aof文件很大那么恢復數據的時候也會很慢,為了減小aof文件的大小,redis提供了重寫機制,來減小aof文件的大小.相關配置可以在配置小節中查看.
觸發自動 AOF 重寫條件
1.沒有 BGSAVE 命令在進行。
2.沒有 BGREWRITEAOF 在進行。
3.當前 AOF 文件大小大於 server.aof_rewrite_min_size (默認值為 64 MB)。
4.當前 AOF 文件大小和最后一次 AOF 重寫后的大小之間的比率大於等於指定的增長百分比
AOF重寫機制的實現原理
首先調用 fork 指令,來創建一個子進程,然后子進程根據當前內存中的數據生成對應指令,並記錄在一個臨時 AOF 文件中,不需要依賴原有的 AOF 文件 (即不需要讀取原有的 AOF 文件進行分析或指令合並)主進程會持續將新的變動同時寫入到內存和原有的 AOF 文件中當子進程完成了臨時 AOF 文件的創建后,會發送信號給主進程,此時主進程會往臨時 AOF 文件中同步增量變動最后使用臨時 AOF 文件替換原有的 RDB 文件我們可以通bgrewriteaof 指令來手動觸發 AOF 文件的重寫.AOF重寫日志,不會阻塞線程,AOF日志由主線程寫回磁盤,AOF重寫過程是由后台進程bgrewriteaof來完成的。主線程fork出后台的bgrewriteaof子進程,fork會把主線程的內存拷貝一份bgrewriteaof子進程,這里面就包含了數據庫的最新數據。然后,bgrewriteaof子進程就可以在不影響主線程的情況下,逐一把拷貝的數據寫成操作,記入重寫日志。所以aof在重寫時,在fork進程時是會阻塞住主線程的
配置
appendonly yes|no
當appendonly為yes時redis啟用aof備份
appendfilename filename
指定生成的aof文件的名稱
appendfsync always|everysec|no
什么時候把aof文件緩沖區的內容寫入的磁盤上.因為緩沖區中的內容實際上還沒有寫入到磁盤,如果這個時候宕機,那么數據也會丟失,所以這個時間不應該設置的太長,redis提供了三種方案.第一種時每秒中寫入一次,這個時最常用的,另外一個是每執行一次命令就寫入一次,因為fsync命令非常慢所以這個不推薦使用.還有一個是不主動寫入到磁盤,而是由系統決定什么時候寫入,
auto-aof-rewrite-percentage 100
aof 文件自上一次重寫后文件大小增長了100%,則再次觸發重寫機制,比如說,上次AOF文件容量為100M,這次文件已經到200M了,則自動觸發重寫機制
auto-aof-rewrite-min-size 64mb
aof文件至少要達到64M才會觸發自動重寫,文件太小,恢復速度很快,重寫意義不大
優點
aof默認的保存策略時每秒一次,所以aof的數據安全性要比rdb高.並且aof中記錄的時文本格式的命令,這樣查看起來會比較方便,而且數據恢復的時候也不受redis版本的限制,所有aof文件都是通用的.
缺點
引文aof中記錄的時操作數據的命令,所有aof文件會明顯大過rdb文件,並且在數據恢復的速度上也明顯慢於rdb文件.如果redis開啟了aof因為aof實在主線程中記錄的,所以會影響redis執行命令的效率.
5.混合持久化
重啟 Redis 時,我們很少使用 rdb 來恢復內存狀態,因為會丟失大量數據。我們通常使用 AOF 日志重放,但是重放 AOF 日志性能相對 rdb 來說要慢很多,這樣在 Redis 實例很大的情況下,啟動需要花費很長的時間。Redis 4.0 為了解決這個問題,帶來了一個新的持久化選項——混合持久化。將 rdb 文件的內容和增量的 AOF 日志文件存在一起。這里的 AOF 日志不再是全量的日志,而是自持久化開始到持久化結束的這段時間發生的增量 AOF 日志,通常這部分 AOF 日志很小.於是在 Redis 重啟的時候,可以先加載 rdb 的內容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重啟效率因此大幅得到提升。