什么叫持久化?
將數據(如內存中的對象)保存到可永久保存的存儲設備中。
持久化的主要應用是將內存中的對象存儲在數據庫中,或者存儲在磁盤文件中、 XML 數據文件中等等。
redis支持兩種方式的持久化,RDB和AOF。前者會根據指定的規則,“定時”將內存中的數據存儲在硬盤上,后者在每次執行命令時將命令本身記錄下來。
RDB:
以下情況會對數據進行快照:
????(1) 根據配置規則進行自動快照;
????????????在redis.conf文件中配置如下參數:
? ? ? ? ? ? ? ? save 900 1(900秒內有一個或一個以上的鍵值被更改則進行快照)
????? ? ????????save 300 10
? ? ????? ? ????save 60 10000
? ? ? ? ? ? ? ? save ""(禁用RDB)
????(2) 用戶執行SAVE或BGSAVE命令;
????????????當執行SAVE命令時,Redis主進程會進行快照操作,在快照執行的過程中會阻塞所有來自客戶端的請求。線上慎用此命令。需要手動執行快照時,推薦使用BGSAVE命令。BGSAVE會fork出一個子進程,子進程調用rdbSave方法,保存完畢之后,向主進程發送信號,通知保存已完成。可以通過LASTSAVE命令獲取最后一次成功執行快照的時間,返回結果是Unix時間戳。
????????????SAVE為同步操作,BGSAVE為異步操作。
????(3) 執行FLUSHALL命令;
????????????當執行FLUSHALL命令時,Redi會清空數據庫中所有數據,只要自動快照條件不為空(save ""),Redis就會執行一次快照操作。
????(4) 執行復制時;
????????????主從模式,從數據庫啟動時,主數據庫會執行一次快照操作,即使沒有設置rdb持久化,也會執行。
????(5) 執行SHUTDOWN命令;
????????????在持久化被打開的情況下,執行SHUDOWN會執行一次快照操作。
原理:
? ? Redis默認會將快照文件存儲在Redis當前進程目錄中的dump.rdb文件中,可以通過配置dir和dbfilename兩個參數指定快照文件存儲路徑和文件名。快照過程如下:
? ? (1) Redis使用fork函數復制一份當前主進程的副本(子進程);
? ? (2) 主進程繼續接收并處理客戶端發來的請求,而子線程開始將內存中的數據寫入硬盤中的臨時文件;
? ? (3) 當子進程寫入完所有數據后會用該臨時文件替換舊的RDB文件。
? ? RDB文件是經過壓縮的二進制格式,可以配置rdbcompression參數禁用。
? ? 通過RDB方式實現持久化,一旦Redis異常退出,就會失去最后一次快照以后更改的數據。
AOF:
? ? AOF可以將Redis執行的每一條寫命令追加到硬盤文件中。
? ? 默認情況下Redis沒有開啟AOF方式的持久化,可以通過appendonly參數啟用:appendonly yes。文件存儲的路徑與RDB文件位置相同,通過dir參數設置,默認文件名是appendonly.aof,可以通過appendfilename參數修改:appendfilename?appendonly.aof。
? ? 設置同步方式:
? ? ? ? (1)?appendfsync always # 每次有數據修改發生時都會寫入AOF文件(安全但是費時)。
? ? ? ? (2) appendfsync everysec # 每秒鐘同步一次,該策略為AOF的缺省策略。
? ? ? ? (3) appendfsync no # 從不同步。高效但是數據不會被持久化。
? ? ?重寫:
? ? ? ????? 隨著執行的命令越來越多,AOF文件大小也會越來越大。每達到一定條件或者手動執行BGREWRITEAOF,Redis會對AOF文件進行自動重寫,重寫后的新文件包含了重寫前最小的命令集合,設置條件如下:
? ??????????auto-aof-rewrite-percentage 100 #參數是當前AOF文件大小超過上一次重寫時的AOF文件大小的百分之X時會再次進行重寫。
????????????auto-aof-rewrite-min-size 64mb #允許重寫的最小aof文件大小,避免了達到約定百分比但尺寸仍然很小的情況還要重寫
? ??????????no-appendfsync-on-rewrite yes #在日志重寫時,不進行命令追加操作,而只是將其放在緩沖區里,避免與命令的追加造成DISK IO上的沖突
? ??????????AOF 重寫和 RDB 創建快照一樣,都巧妙地利用了寫時復制機制。
????????????以下是 AOF 重寫的執行步驟:
??????????????(1) ?Redis 執行 fork() ,現在同時擁有父進程和子進程。
? ? ? ? ? ? ? (2) 子進程開始將新 AOF 文件的內容寫入到臨時文件。
? ? ? ? ? ? ? (3) 對于所有新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有 AOF 文件的末尾: 這樣即使在重寫的中途發生停機,現有的 AOF 文件也還是安全的。
? ? ? ? ? ? ? (4) 當子進程完成重寫工作時,它給父進程發送一個信號,父進程在接收到信號之后,將內存緩存中的所有數據追加到新 AOF 文件的末尾。
? ? ? ? ? ? ? (5) Redis 原子地用新文件替換舊文件,之后所有命令都會直接追加到新 AOF 文件的末尾。
RDB和AOF文件損壞如何修復?
? ??????如果aof或rdb文件語法有誤,可以使用如下兩條命令來修復。
????????aof修復命令:redis-check-aof --fix appendonlly.aof
????????rdb修復命令:redis-check-rdb --fix dump.rdb
怎樣從 RDB 方式切換為 AOF 方式?
? ??????在不重啟的情況下,從 RDB 切換到 AOF :
? ? ? ? ? ? (1) 為最新的 dump.rdb 文件創建一個備份、將備份放到一個安全的地方。
? ? ? ? ? ? (2) 執行以下兩條命令:
????????????????redis-cli config set appendonly yes
????????????????redis-cli config set save “”
? ? ? ? ? ? (3) 確保寫命令會被正確地追加到 AOF 文件的末尾。執行的第一條命令開啟了 AOF 功能:Redis 會阻塞直到初始 AOF 文件創建完成為止,之后 Redis 會繼續處理命令請求,并開始將寫入命令追加到 AOF 文件末尾。
? ? ? ? ? ? (4) 執行的第二條命令用于關閉 RDB 功能。這一步是可選的,如果你愿意的話,也可以同時使用 RDB 和 AOF 這兩種持久化功能。
????????PS:別忘了在 redis.conf 中打開 AOF 功能!否則服務器重啟后,之前通過 CONFIG SET 命令設置的配置就會被遺忘,程序會按原來的配置來啟動服務器。
RDB 和 AOF 之間的相互作用
? ?????? BGSAVE 執行的過程中, 不可以執行 BGREWRITEAOF 。 反過來說, 在 BGREWRITEAOF 執行的過程中, 也不可以執行 BGSAVE 。
這可以防止兩個 Redis 后臺進程同時對磁盤進行大量的 I/O 操作。
如果 BGSAVE 正在執行, 并且用戶調用 BGREWRITEAOF 命令, 那么服務器將向用戶回復一個 OK 狀態, 并告知用戶, BGREWRITEAOF 已經被預定執行: 一旦 BGSAVE 執行完畢, BGREWRITEAOF 就會正式開始。
當 Redis 啟動時, 如果 RDB 持久化和 AOF 持久化都被打開了, 那么程序會優先使用 AOF 文件來恢復數據集, 因為 AOF 文件所保存的數據通常是最完整的。