redis持久化概念 Author:SimpleWu 什麼是持久化? 概念:把記憶體的數據保存在磁碟的過程。 Redis的持久化? redis是記憶體資料庫,它把數據存儲在記憶體中,這樣在加快讀取速度的同時也對數據安全性產生了新的問題,即當redis所在伺服器發生宕機後,redis資料庫里的所有數據將會全 ...
redis持久化概念
Author:SimpleWu
GitHub-redis
什麼是持久化?
概念:把記憶體的數據保存在磁碟的過程。
Redis的持久化?
redis是記憶體資料庫,它把數據存儲在記憶體中,這樣在加快讀取速度的同時也對數據安全性產生了新的問題,即當redis所在伺服器發生宕機後,redis資料庫里的所有數據將會全部丟失。
Redis實現持久化的兩種方式:
- RDB(Redis DataBase ):就是在不同的時間點,將redis存儲的數據生成快照並存儲到磁碟等介質上.
- AOF(Append Only File ):那就是將redis執行過的所有寫指令記錄下來,在下次redis重新啟動時,只要把這些寫指令從前到後再重覆執行一遍,就可以實現數據恢復了。
全量寫入-RDB
是將redis某一時刻的數據持久化到磁碟中,是一種快照式的持久化方法。
這種方式是就是將記憶體中所有的數據以快照的方式寫入到二進位文件中,預設的文件名為dump.rdb。
修改預設文件名,找到將dump.rdb修改即可:
dbfilename dump.rdb
可以通過配置設置自動做快照持久化的方式。
預設:
save 900 1
save 300 10
save 60 10000
三個配置解析:
- 900秒內如果超過1個key被修改,則發起快照保存。
- 300秒內如果超過10個key被修改,則發起快照保存。
- 60秒內如果超過10000個key被修改,則發起快速保存。
註意:修改配置後,需要重啟redis服務。
RDB參數
查看配置:
config get save
修改配置:
config set save "120 10"
RDB快照及恢復
三種觸發快照方式:
- 自動保存快照,配置文件中的快照參數設置。
- 輸入命令保存save或者bgsave。
- 執行shutdown或者flsuhall命令時。
save和bgsave的區別:
當執行save時,不能進行其他操作,全部阻斷。 bgsave為後臺非同步操作,執行時,伺服器任然可以進行其它操作。如果想禁用RDB持久化策略,只要不設置任何save命令,或者給save傳入一個空字元串也可以。
RDB-優點
- redis在進行數據持久化的過程中,會先將數據寫入到一個臨時文件中,待持久化過程都結束了,才會用這個臨時文件替換上次持久化好的文件。正是這種特性,讓我們可以隨時來進行備份,因為快照文件總是完整可用的。
- RDB 可以最大化 Redis 的性能:父進程在保存 RDB 文件時唯一要做的就是 fork 出一個子進程,然後這個子進程就會處理接下來的所有保存工作,父進程無須執行任何磁碟 I/O 操作。
- 如果需要進行大規模數據的恢復,且對於數據恢復的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。
RDB-缺點
- 雖然RDB有不少優點,但它的缺點也是不容忽視的。如果你對數據的完整性非常敏感,那麼RDB方式就不太適合你,因為即使你每5分鐘都持久化一次,當redis故障時,仍然會有近5分鐘的數據丟失。
- 每次保存 RDB 的時候,Redis 都要 fork() 出一個子進程,並由子進程來進行實際的持久化工作。 在數據集比較龐大時, fork() 可能會非常耗時,造成伺服器在某某毫秒內停止處理客戶端; 如果數據集非常巨大,並且 CPU 時間非常緊張的話,那麼這種停止時間甚至可能會長達整整一秒。 雖然 AOF 重寫也需要進行 fork() ,但無論 AOF 重寫的執行間隔有多長,數據的耐久性都不會有任何損失。
增量寫入AOF
AOF方式是將執行過的寫指令記錄下來,在數據恢復時按照從前到後的順序再將指令都執行一遍,就這麼簡單。
redis會將每一個收到的寫命令(如set、sadd、rpush)追加到 (預設是appendonly.aof)文件中。當redis重啟時會通過重新執行文件中保存的寫命令來在記憶體中重建整個資料庫的內容。
預設的AOF持久化策略是每秒鐘fsync一次(fsync是指把緩存中的寫指令記錄到磁碟中),因為在這種情況下,redis仍然可以保持很好的處理性能,即使redis故障,也只會丟失最近1秒鐘的數據。
AOF配置
修改AOF文件存放路徑:
預設:dir ./
開啟AOF持久化,預設關閉:
appendonly no #將no改為yes為開啟
修改AOF文件名稱:
appendfilename "appendonly.aof"
AOF持久化策略:
appendfsync everysec #everysec是預設策略
持久化策略:
- always:選擇always的時候伺服器會在每執行一個事件就把AOF緩衝區的內容強制性的寫入硬碟上的AOF文件里,可以看成你每執行一個redis寫入命令就往AOF文件里記錄這條命令,這保證了數據持久化的完整性,但效率是最慢的,卻也是最安全的
- everysec:配置成everysec的話服務端每執行一次寫操作(如set、sadd、rpush)也會把該條命令追加到一個單獨的AOF緩衝區的末尾,並將AOF緩衝區寫入AOF文件,然後每隔一秒才會進行一次文件同步把記憶體緩衝區里的AOF緩存數據真正寫入AOF文件里,這個模式兼顧了效率的同時也保證了數據的完整性,即使在伺服器宕機也只會丟失一秒內對redis資料庫做的修改;
- no:將appendfsync配置成no則意味redis資料庫里的數據就算丟失你也可以接受,它也會把每條寫命令追加到AOF緩衝區的末尾,然後寫入文件,但什麼時候進行文件同步真正把數據寫入AOF文件里則由系統自身決定,即當記憶體緩衝區的空間被填滿或者是超過了設定的時限後系統自動同步。這種模式下效率是最快的,但對數據來說也是最不安全的,如果redis里的數據都是從後臺資料庫如mysql中取出來的,屬於隨時可以找回或者不重要的數據,那麼可以考慮設置成這種模式。
AOP文件的修複
如果在追加日誌時,恰好遇到磁碟空間滿、inode滿或斷電等情況導致日誌寫入不完整,也沒有關係,redis提供了redis-check-aof工具,可以用來進行日誌修複。
可以通過以下命令進行修複:
redis-check-aof --fix appendonly.aof #該命令會修複aof文件。
AOF重寫(rewrite)
由於AOF採用追加方式,文件會變得越來越大,針對這種情況採用了重寫機制,從而保留可以恢複數據的最小指令集。可以使用命令 bgrewriteaof。
AOF重寫的內部運行原理:
- 在重寫即將開始之際,redis會創建(fork)一個“重寫子進程”,這個子進程會首先讀取現有的AOF文件,並將其包含的指令進行分析壓縮併到一個臨時文件中。
- 與此同時,主工作進程會將新接收到的寫指令一邊累積到記憶體緩衝區中,一邊繼續寫入到原有的AOF文件中,這樣做是保證原有的AOF文件的可用性,避免在重寫過程中出現意外。
- 當“重寫子進程”完成重寫工作後,它會給父進程發一個信號,父進程收到信號後就會將記憶體中緩存的寫指令追加到新AOF文件中。
- 當追加結束後,redis就會用新AOF文件來代替舊AOF文件,之後再有新的寫指令,就都會追加到新的AOF文件中了。
觸發條件:Redis會記錄上一次重寫時的AOF大小,預設配置是當AOF文件大小是上次rewrite後大小的一倍且文件大於64M時觸發。
RDB和AOF的共存
RDB和AOF兩種方式也可以同時使用,在這種情況下,如果redis重啟的話,則會優先採用AOF方式來進行數據恢復,這是因為AOF方式的數據恢復完整度更高。
AOF-優點
- 使用 AOF 持久化會讓 Redis 變得非常耐久(much more durable):你可以設置不同的 fsync 策略,比如無 fsync ,每秒鐘一次 fsync ,或者每次執行寫入命令時 fsync 。 AOF 的預設策略為每秒鐘 fsync 一次,在這種配置下,Redis 仍然可以保持良好的性能,並且就算發生故障停機,也最多只會丟失一秒鐘的數據( fsync 會在後臺線程執行,所以主線程可以繼續努力地處理命令請求)。
- AOF 文件是一個只進行追加操作的日誌文件(append only log), 因此對 AOF 文件的寫入不需要進行 seek , 即使日誌因為某些原因而包含了未寫入完整的命令(比如寫入時磁碟已滿,寫入中途停機,等等), redis-check-aof 工具也可以輕易地修複這種問題。
- Redis 可以在 AOF 文件體積變得過大時,自動地在後臺對 AOF 進行重寫: 重寫後的新 AOF 文件包含了恢復當前數據集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在創建新 AOF 文件的過程中,會繼續將命令追加到現有的 AOF 文件裡面,即使重寫過程中發生停機,現有的 AOF 文件也不會丟失。 而一旦新 AOF 文件創建完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,並開始對新 AOF 文件進行追加操作。
- AOF 文件有序地保存了對資料庫執行的所有寫入操作, 這些寫入操作以 Redis 協議的格式保存, 因此 AOF 文件的內容非常容易被人讀懂, 對文件進行分析(parse)也很輕鬆。 導出(export) AOF 文件也非常簡單: 舉個例子, 如果你不小心執行了 FLUSHALL 命令, 但只要 AOF 文件未被重寫, 那麼只要停止伺服器, 移除 AOF 文件末尾的 FLUSHALL 命令, 並重啟 Redis , 就可以將數據集恢復到 FLUSHALL 執行之前的狀態。
AOF-缺點
- 對於相同的數據集來說,AOF 文件的體積通常要大於 RDB 文件的體積。而且,AOF方式的恢復速度也要慢於RDB方式。
- 如果你直接執行BGREWRITEAOF命令,那麼redis會生成一個全新的AOF文件,其中便包括了可以恢復現有數據的最少的命令集。
- 根據所使用的 fsync 策略,AOF 的速度可能會慢於 RDB 。 在一般情況下, 每秒 fsync 的性能依然非常高, 而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間(latency)。
RDB和AOF的區別
RDB方式能夠在指定的時間間隔能對你的數據進行快照存儲。
AOF方式記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來恢復,AOF命令以redis協議追加保存每次寫的操作到文件末尾。redis還能對AOF文件進行後臺重寫,使得AOF文件的體積不至於過大。
如何選擇RDB和AOF
因為RDB文件只用作後備用途,建議只在Slave上持久化RDB文件,而且只要15分鐘備份一次就夠了,只保留save 900 1這條規則。
如果Enalbe AOF,好處是在最惡劣情況下也只會丟失不超過兩秒數據,啟動腳本較簡單隻load自己的AOF文件就可以了。代價一是帶來了持續的IO,二是AOF rewrite的最後將rewrite過程中產生的新數據寫到新文件造成的阻塞幾乎是不可避免的。只要硬碟許可,應該儘量減少AOF rewrite的頻率,AOF重寫的基礎大小預設值64M太小了,可以設到5G以上。預設超過原大小100%大小時重寫可以改到適當的數值。
如果不Enable AOF ,僅靠Master-Slave Replication 實現高可用性也可以。能省掉一大筆IO也減少了rewrite時帶來的系統波動。代價是如果Master/Slave同時倒掉,會丟失十幾分鐘的數據,啟動腳本也要比較兩個Master/Slave中的RDB文件,載入較新的那個。新浪微博就選用了這種架構
只做緩存:如果你只希望你的數據在伺服器運行時候存在,你也可以不使用任何持久化方式。
對於我們應該選擇RDB還是AOF,官方的建議是兩個同時使用。這樣可以提供更可靠的持久化方案。