Redis 持久化有哪幾種方式,怎么選?
前言
大家好,我是程序員田螺。今天給大家分享一道經典面試題:Redis 持久化有哪幾種方式,怎么選?
- AOF持久化
- RDB持久化
- AOF和RDB如何選擇
1 AOF 持久化
Redis是基于內存的,如果Redis服務器掛了,數據就會丟失。為了避免數據丟失了,Redis提供了兩種持久化方式,RDB和AOF。我們先來介紹AOF。
AOF(append only file) 持久化,采用日志的形式來記錄每個寫操作,追加到AOF文件的末尾。Redis默認情況是不開啟AOF的。重啟時再重新執行AOF文件中的命令來恢復數據。它主要解決數據持久化的實時性問題。
AOF是執行完命令后才記錄日志的。為什么不先記錄日志再執行命令呢?這是因為Redis在向AOF記錄日志時,不會先對這些命令進行語法檢查,如果先記錄日志再執行命令,日志中可能記錄了錯誤的命令,Redis使用日志回復數據時,可能會出錯。
正是因為執行完命令后才記錄日志,所以不會阻塞當前的寫操作。但是會存在兩個風險:
- 更執行完命令還沒記錄日志時,宕機了會導致數據丟失
- AOF不會阻塞當前命令,但是可能會阻塞下一個操作。
這兩個風險最好的解決方案是折中妙用AOF機制的三種寫回策略 appendfsync:
- always,同步寫回,每個子命令執行完,都立即將日志寫回磁盤。
- everysec,每個命令執行完,只是先把日志寫到AOF內存緩沖區,每隔一秒同步到磁盤。
- no:只是先把日志寫到AOF內存緩沖區,有操作系統去決定何時寫入磁盤。
always同步寫回,可以基本保證數據不丟失,no策略則性能高但是數據可能會丟失,一般可以考慮折中選擇everysec。
如果接受的命令越來越多,AOF文件也會越來越大,文件過大還是會帶來性能問題。日志文件過大怎么辦呢?AOF重寫機制!就是隨著時間推移,AOF文件會有一些冗余的命令如:無效命令、過期數據的命令等等,AOF重寫機制就是把它們合并為一個命令(類似批處理命令),從而達到精簡壓縮空間的目的。
AOF重寫會阻塞嘛?AOF日志是由主線程會寫的,而重寫則不一樣,重寫過程是由后臺子進程bgrewriteaof完成。
- AOF的優點:數據的一致性和完整性更高,秒級數據丟失。
- 缺點:相同的數據集,AOF文件體積大于RDB文件。數據恢復也比較慢。
2 RDB持久化
因為AOF持久化方式,如果操作日志非常多的話,Redis恢復就很慢。有沒有在宕機快速恢復的方法呢,有的,RDB!
RDB,就是把內存數據以快照的形式保存到磁盤上。和AOF相比,它記錄的是某一時刻的數據,,并不是操作。
什么是快照?可以這樣理解,給當前時刻的數據,拍一張照片,然后保存下來。
RDB持久化,是指在指定的時間間隔內,執行指定次數的寫操作,將內存中的數據集快照寫入磁盤中,它是Redis默認的持久化方式。執行完操作后,在指定目錄下會生成一個dump.rdb文件,Redis 重啟的時候,通過加載dump.rdb文件來恢復數據。RDB觸發機制主要有以下幾種:
圖片
RDB通過bgsave命令的執行全量快照,可以避免阻塞主線程。basave命令會fork一個子進程,然后該子進程會負責創建RDB文件,而服務器進程會繼續處理命令請求
快照時,數據能修改嘛? Redis接住操作系統的寫時復制技術(copy-on-write,COW),在執行快照的同時,正常處理寫操作。
雖然bgsave執行不會阻塞主線程,但是頻繁執行全量快照也會帶來性能開銷。比如bgsave子進程需要通過fork操作從主線程創建出來,創建后不會阻塞主線程,但是創建過程是會阻塞主線程的。可以做增量快照。
- RDB的優點:與AOF相比,恢復大數據集的時候會更快,它適合大規模的數據恢復場景,如備份,全量復制等
- 缺點:沒辦法做到實時持久化/秒級持久化。
Redis4.0開始支持RDB和AOF的混合持久化,就是內存快照以一定頻率執行,兩次快照之間,再使用AOF記錄這期間的所有命令操作。
3 如何選擇RDB和AOF
- 如果數據不能丟失,RDB和AOF混用
- 如果只作為緩存使用,可以承受幾分鐘的數據丟失的話,可以只使用RDB。
- 如果只使用AOF,優先使用everysec的寫回策略。