Redis持久化原理:
Redis支持兩種持久化:RDB和AOF模式
一、名詞解釋:
RDB:持久化可以在指定的時間間隔內生成數據集的時間點快照(point-in-time snapshot)。
AOF:持久化記錄服務器執行的所有寫操作命令,並在服務器啟動時,通過重新執行這些命令來還原數據集。
AOF 文件中的命令全部以 Redis 協議的格式來保存,新命令會被追加到文件的末尾。 Redis 還可以在后台對 AOF 文件進行重寫(rewrite)
使得 AOF 文件的體積不會超出保存數據集狀態所需的實際大小。
PDB和AOF的優先級:
如果同時開啟RDB和AOF模式,AOF的優先級要比RDB高:
Redis 還可以同時使用 AOF 持久化和 RDB 持久化。 在這種情況下, 當 Redis 重啟時, 它會優先使用 AOF 文件來還原數據集。
因為 AOF 文件保存的數據集通常比 RDB 文件所保存的數據集更完整。
AOF 的方式有點像ORCAL的邏輯備庫!
AOF redis 還會在后台對數據進行重寫,比如set key1 , set key1 ,其實第一次的set key1 沒用,這樣就可以把第一次set key1 刪掉了。這樣保存下來的數據集就很小了可以壓縮了!
你甚至可以關閉持久化功能,讓數據只在服務器運行時存在。
二、RDB&AOF優缺點
RDB的優缺點:
優點:
1、緊湊易於備份,他就一個文件。
2、RDB可以最大化redis性能、父進程無需做任何操作只需要for一個子進程即可
3、恢復比AOF塊
缺點:
1、數據完整性:如果非常注重數據的完整性,那么RDB就不行,雖然他是一個point-in-time 的快照方式,但是在快照的過程中,redis重啟了,那么在快照中的這些數據將會丟失
2、數據非常龐大后,非常耗CPU和時間,那么redis講可能down掉1秒鍾設置更長。
AOF的優缺點:
優點:
1、 使用 AOF 持久化會讓 Redis 變得非常耐久,AOF默認的每一秒追加一次也可以修改他的方式沒執行一次命令追加一次,所以你最多丟失1秒鍾的數據
2、 AOF 文件是一個只進行追加操作的日志文件(append only log)
3、 Redis 可以在 AOF 文件體積變得過大時,自動地在后台對 AOF 進行重寫
缺點:
1、對於相同的數據集來說,AOF 文件的體積通常要大於 RDB 文件的體積。
2、 根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB
三、RDB & AOF 持久化原理
快照的運行方式:
當 Redis 需要保存 dump.rdb 文件時, 服務器執行以下操作:
- Redis 調用 fork() ,同時擁有父進程和子進程。
- 子進程將數據集寫入到一個臨時 RDB 文件中。
- 當子進程完成對新 RDB 文件的寫入時,Redis 用新 RDB 文件替換原來的 RDB 文件,並刪除舊的 RDB 文件。
- 這種工作方式使得 Redis 可以從寫時復制(copy-on-write)機制中獲益。
AOF 重寫和 RDB 創建快照一樣,都巧妙地利用了寫時復制機制。
以下是 AOF 重寫的執行步驟:
- Redis 執行 fork() ,現在同時擁有父進程和子進程。
- 子進程開始將新 AOF 文件的內容寫入到臨時文件。
- 對於所有新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有 AOF 文件的末尾: 這樣即使在重寫的中途發生停機,現有的 AOF 文件也還是安全的。
- 當子進程完成重寫工作時,它給父進程發送一個信號,父進程在接收到信號之后,將內存緩存中的所有數據追加到新 AOF 文件的末尾。
- 搞定!現在 Redis 原子地用新文件替換舊文件,之后所有命令都會直接追加到新 AOF 文件的末尾。
AOF重寫
因為 AOF 的運作方式是不斷地將命令追加到文件的末尾, 所以隨着寫入命令的不斷增加, AOF 文件的體積也會變得越來越大。
舉個例子, 如果你對一個計數器調用了 100 次 INCR , 那么僅僅是為了保存這個計數器的當前值, AOF 文件就需要使用 100 條記錄(entry)。
然而在實際上, 只使用一條 SET 命令已經足以保存計數器的當前值了, 其余 99 條記錄實際上都是多余的。
為了處理這種情況, Redis 支持一種有趣的特性: 可以在不打斷服務客戶端的情況下, 對 AOF 文件進行重建(rebuild)。
執行 BGREWRITEAOF 命令, Redis 將生成一個新的 AOF 文件, 這個文件包含重建當前數據集所需的最少命令。
Redis 2.2 需要自己手動執行 BGREWRITEAOF 命令; Redis 2.4 則可以自動觸發 AOF 重寫, 具體信息請查看 2.4 的示例配置文件。
Rdis持久化設置:
默認Redis是開啟的RDB模式的持久化的看下面配置文件:
vim /etc/redis/6379.conf ============================================================= ################################ SNAPSHOTTING ################################ # # Save the DB on disk: # # save <seconds> <changes> # # Will save the DB if both the given number of seconds and the given # number of write operations against the DB occurred. # # In the example below the behaviour will be to save: # after 900 sec (15 min) if at least 1 key changed # after 300 sec (5 min) if at least 10 keys changed # after 60 sec if at least 10000 keys changed # # Note: you can disable saving completely by commenting out all "save" lines. # # It is also possible to remove all the previously configured save # points by adding a save directive with a single empty string argument # like in the following example: # # save "" save 900 1 save 300 10 save 60 10000 ================================================================ 上面3個save 是或的關系 # save <seconds> <changes> ###格式! 解釋: # after 900 sec (15 min) if at least 1 key changed # after 300 sec (5 min) if at least 10 keys changed # after 60 sec if at least 10000 keys changed 900 sec內有1個key發生了改變就做一次快照 或 300sec 內有10個keys發生了改變做一次快照 或60 sec內 10000 keys發生了改變做一次快照 快照原理: forker出一個進程,是當前進程的一個副本相當於子進程,不會影響你當前運行的進程。 當子進程寫的時候會有一個臨時的文件,當子進程寫完之后會把這個 臨時的文件move替換老的文件,所以這個rdb的文件任何時間都是一個完整的可用的副本! 你寫的時候不會影響RDB這個文件,因為forker出的子進程正在寫的是一個臨時文件! 但是如果如果故障了,你這個保存的時間是你開始快照那一刻那個時間,你快照到快照完畢那一段時間的數據就丟失了! 如果想禁用持久化把這三行刪了就行了 save 900 1 save 300 10 save 60 10000
1、快照保存在那里呢?
# The filename where to dump the DB dbfilename dump.rdb #如果你啟用了多個快照名稱,可以使用端口好來定義比如:dump_6379.rdb # Note that you must specify a directory here, not a file name. dir ./ #不僅僅是RDB模式下的DB存放在這個目錄AOF模式下也是存放在這個目錄的,建議存放在你指定的地方! 比如: dir /opt/redis/ 比如我上面指定了: # The filename where to dump the DB dbfilename dump_6379.rdb # Note that you must specify a directory here, not a file name. dir /opt/redis/
2、手動在Redis中保存
127.0.0.1:6379> SET key 1 OK 127.0.0.1:6379> SAVE OK 下目錄下面有沒有修改: -rw-r--r-- 1 root root 27 Oct 14 13:35 dump_6379.rdb 當前時間創建 在設置個key看下: 127.0.0.1:6379> SET key 2 OK 127.0.0.1:6379> SAVE OK -rw-r--r-- 1 root root 27 Oct 14 13:37 dump_6379.rdb 127.0.0.1:6379> BGSAVE Background saving started SAVE和BGSAVE有什么區別:SAVE 是阻塞的當你直接執行SAVE的時候他就不干活了,BGSAVE是在后台執行。forker一個子進程來進行SAVE! SAVE的使用場景僅限於:當Redis需要遷移的時候,Redis沒有數據寫入並且可以停的時候使用! 測試添加一個:key然后停掉看看!不保存: 目前的key是: 127.0.0.1:6379> KEYS * 1) "key" 2) "key2" 3) "key3" 127.0.0.1:6379> SET key4 4 OK 殺掉,重啟之后發現設置的key丟失了。 #所以當redis異常掛掉之后,沒有SAVE收據!
3、啟用了AOF后
給這個文件追加,把所有的命令都寫到一個文件里面,你執行一個我寫一個。 恢復的話在執行一遍不就行了嗎!非常簡單 (但是恢復相對RDB模式回慢他相當於重新把AOF庫里的記錄重新往內存中寫一邊) 可以RDB和AOF同時使用!優點都占用了!但是也的根據業務來定! 開啟方法:修改配置文件 appendonly yes #改為yes appendfilename "appendonly.aof" #文件名 工作原理: forker 一個子進程寫到臨時文件,寫完之后就給父進程發一個信號,開始寫到寫完的這個過程還會有子進程給父進程發信號。先保存在內存里 但是他有個好的功能,重寫,他會定時對aof進行重新,這樣文件就會非常小! 測試:(他會根據Redis可識別的方式寫入文件,不過大概人也能看懂) 16:50 [root@192.168.7.107]$ cat appendonly.aof *2 $6 SELECT $1 0 *3 $3 SET $4 kye1
部分參考:http://redisdoc.com/topic/persistence.html#id7