配置方案:Redis持久化RDB和AOF

Redis持久化方案linux

Redis是內存數據庫,數據都是存儲在內存中,爲了不進程退出致使數據的永久丟失,須要按期將Redis中的數據以某種形式(數據或命令)從內存保存到硬盤。當下次Redis重啓時,利用持久化文件實現數據恢復。除此以外,爲了進行災難備份,能夠將持久化文件拷貝到一個遠程位置。redis

Redis提供了多種不一樣級別的持久化方式:一種是RDB,另外一種是AOF。算法

RDB持久化能夠在指定的時間間隔內生成數據集的時間點快照(point-in-time snapshot),將數據庫的快照(snapshot)以二進制的方式保存到磁盤中。數據庫

AOF持久化記錄服務器執行的全部更改操做命令,AOF文件中的命令所有以Redis協議的格式來保存,新命令會被追加到文件的末尾。Redis還能夠在後臺對AOF文件進行重寫(rewrite),使得AOF文件的體積不會超出保存數據集狀態所需的實際大小。緩存

Redis能夠同時使用AOF持久化和RDB持久化。在這種狀況下,當Redis重啓時,它會優先使用AOF文件來還原數據集,由於AOF文件保存的數據集一般比RDB文件所保存的數據集更完整。你甚至能夠關閉持久化功能,讓數據只在服務器運行時存在。安全

瞭解RDB持久化和AOF持久化之間的異同是很是重要的,如下幾個小節將詳細地介紹這這兩種持久化功能,並對它們的相同和不一樣之處進行說明。服務器

RDB快照網絡

下面咱們說一下Redis的第一個持久化策略,RDB快照。Redis支持將當前內存數據的快照存成一個數據文件的持久化機制,而一個持續寫入的數據庫如何生成快照呢?Redis巧妙地藉助了fork命令的寫時複製(copy on write)機制,將當前進程fork出一個子進程,子進程根據內存快照,循環將數據持久化爲RDB文件。app

在默認狀況下, Redis將數據庫快照保存在根目錄下,名字爲dump.rdb的二進制文件中。可經過參數dir配置指定保存目錄,dbfilename指定文件名。你能夠對Redis進行設置,如「save N M」,表示N秒內數據項中有M個改動時這一條件被知足時,自動保存一次數據集。好比你能夠配置當10分鐘之內有100次寫入就生成快照,也能夠配置當1分鐘內有1000次寫入就生成快照,支持能夠多個規則一塊兒生效,當匹配到哪一個就哪一個規則生效。這些規則的定義就在Redis的配置文件中,你也能夠經過Redis的CONFIG SET命令在Redis運行時設置規則,不須要重啓Redis。async

好比說,如下設置會讓Redis在知足「60秒內有至少有1000個鍵被改動」這一條件時,自動保存一次數據集:

save 60 1000

你也能夠經過調用SAVE或者BGSAVE,手動讓Redis進行數據集保存操做。SAVE命令執行一個同步操做,以RDB文件的方式保存全部數據的快照,不多在生產環境直接使用SAVE命令,由於它會阻塞全部的客戶端的請求,不要在生產環境使用,可使用BGSAVE命令代替。BGSAVE命令執行過程當中是經過fork一個子進程來完成的,因此不會阻塞客戶端請求,只有fork子進程時會阻塞服務器。另外,在自動觸發RDB持久化時,Redis也會選擇BGSAVE而不是SAVE來進行持久化。

Redis自動RDB持久化在其內部是經過serverCron週期性操做函數、dirty計數器、和lastsave時間戳來實現的。其中serverCron每100ms執行一次,檢查服務器狀態,其中就包括檢查「save N M」是否知足條件,若是知足就執行BGSAVE;固然也包括AOF重寫檢查。dirty計數器是Redis服務器維持的一個狀態,記錄了上一次執行BGSAVE/SAVE命令後,服務器狀態進行了多少次修改(包括增刪改),而當BGSAVE/SAVE執行完成後,會將dirty從新置爲0。lastsave時間戳也是Redis服務器維持的一個狀態,記錄的是上一次成功執行BGSAVE/SAVE的時間,當前時間減去lastsave需知足M。

除了手動和自動之外,還有一些其餘狀況會觸發BGSAVE:

在主從複製場景下,若是從節點執行全量複製操做,則主節點會執行BGSAVE命令,並將rdb文件發送給從節點。
執行shutdown命令時,自動執行rdb持久化。
另外須要瞭解的,由於其寫操做是在一個新進程中進行的,當生成一個新的RDB文件時,Redis生成的子進程會先將數據寫到一個臨時文件中,而後經過原子性rename系統調用將臨時文件重命名爲RDB文件,這樣在任什麼時候候出現故障,Redis的RDB文件都老是可用的。

這種持久化方式被稱爲快照(snapshot)。可是,咱們能夠很明顯的看到,RDB有他的不足,就是一旦數據庫出現問題,那麼咱們的RDB文件中保存的數據並非全新的,從上次RDB文件生成到Redis停機這段時間的數據所有丟掉了。在某些業務下,若是能夠忍受間隔內數據丟失,咱們也推薦這些業務使用RDB的方式進行持久化,由於開啓RDB的代價並不高。可是對於另一些對數據安全性要求極高的應用,沒法容忍數據丟失的應用,RDB就無能爲力了,因此Redis引入了另外一個重要的持久化機制,AOF日誌方式持久化。

爲了儘量使RDB文件體積減少,Redis默認採用LZF算法對RDB文件進行壓縮。雖然壓縮耗時,可是能夠大大減少RDB文件的體積,所以壓縮默認開啓,參數爲rdbcompression。須要注意的是,RDB文件的壓縮並非針對整個文件進行的,而是對數據庫中的字符串進行的,且只有在字符串達到必定長度(20字節)時纔會進行。

除了壓縮,你也能夠檢驗RDB文件,經過參數rdbchecksum設置,默認爲yes。在寫入文件和讀取文件時都起做用,關閉checksum在寫入文件和啓動文件時大約能帶來10%的性能提高,可是數據損壞時沒法發現。

另外,當bgsave出現錯誤時,Redis是否中止執行寫命令。Redis提供了一個參數stop-writes-on-bgsave-error,設置爲yes,則當硬盤出現問題時,能夠及時發現,避免數據的大量丟失;設置爲no,則Redis無視bgsave的錯誤繼續執行寫命令,當對Redis服務器的系統(尤爲是硬盤)使用了監控時,該選項考慮設置爲no。

說說FORK的開銷?

父進程經過fork操做能夠建立子進程,第一代Unix系統實現了一種傻瓜式的進程建立:當執行fork系統調用時,內核複製父進程的整個用戶空間並把複製獲得的那一份分配給子進程。這種行爲時很是耗時的,由於它須要完成如下幾項任務:爲子進程的頁表分配頁面、爲子進程的頁分配頁面、初始化子進程的頁表、把父進程的頁複製到子進程對應的頁中。

如今Linux的fork()使用寫時拷貝(copy-on-write)頁實現。寫時拷貝是一種能夠推遲甚至免除拷貝數據的技術。內核此時並不複製整個進程地址空間,而是讓父進程和子進程共享同一個拷貝。只有在須要寫入的時候,數據纔會被複制,從而使各個進程擁有各自的拷貝。也就是說,資源的複製只有在須要寫入的時候才進行,在此以前,只是以只讀方式共享。這種技術使地址空間上的頁的拷貝被推遲到實際發生寫入的時候。因此就算fork很大內存的進程,對內存的消耗和耗時都很小。

如今雖然fork時,子進程不會複製父進程的數據空間,可是會複製內存頁表(頁表至關於內存的索引、目錄);父進程的數據空間越大,內存頁表越大,fork時複製耗時也會越多。這個問題也是致使Redis內存不宜過大的緣由之一,固然還有致使故障恢復時間延長也是Redis內存不宜過大的緣由。

AOF日誌

經過上面的分析,咱們知道RDB快照有大機率丟失最近寫入、且仍未保存到快照中的那些數據。儘管對於某些程序來講,數據安全並非最重要的考慮因素,可是對於那些追求數據安全的程序來講,快照功能就不太適用了。從1.1版本開始,Redis增長了一種實時性更好的持久化方式,即AOF持久化。AOF日誌的全稱是append only file,從名字上咱們就能看出來,它是一個追加寫入的日誌文件。與RDB相比,AOF的實時性更好,所以已成爲主流的持久化方案。

AOF文件與MySQL數據庫的binlog不一樣的是,AOF是一種純文本格式,具備兼容性好、可讀性強、容易處理、操做簡單避免二次開銷等優勢,它記錄的內容就是一個個的Redis標準命令。開啓AOF持久化命令以下:

appendonly yes
appendfilename "appendonly.aof"

從如今開始,每當Redis執行一個改變數據集的命令時(好比SET),這個命令就會被追加到AOF文件的末尾。這樣的話,當Redis從新啓時,程序就能夠經過從新執行AOF文件中的命令來達到重建數據集的目的。

因爲須要記錄Redis的每條寫命令,所以AOF不須要觸發,下面介紹AOF的執行流程:

命令追加(append)

Redis先將寫命令追加到緩衝區,而不是直接寫入文件,主要是爲了不每次有寫命令都直接寫入硬盤,致使硬盤IO成爲Redis負載的瓶頸。

文件寫入(write)和文件同步(sync)

Redis提供了多種AOF緩存區的同步文件策略,策略涉及到操做系統的write函數和fsync函數,說明以下:

爲了提升文件寫入效率,在現代操做系統中,當用戶調用write函數將數據寫入文件時,操做系統一般會將數據暫存到一個內存緩衝區裏,當緩衝區被填滿或超過了指定時限後,才真正將緩衝區的數據寫入到硬盤裏。這樣的操做雖然提升了效率,但也帶來了安全問題:若是計算機停機,內存緩衝區中的數據會丟失;所以系統同時提供了fsync、fdatasync等同步函數,能夠強制操做系統馬上將緩衝區中的數據寫入到硬盤裏,從而確保數據的安全性。

AOF緩存區的同步文件策略由參數appendfsync控制,各個值的含義以下:

always:命令寫入aof_buf後當即調用系統fsync操做同步到AOF文件,fsync完成後線程返回。這種狀況下,每次有寫命令都要同步到AOF文件,硬盤IO成爲性能瓶頸,Redis只能支持大約幾百TPS寫入,嚴重下降了Redis的性能;即使是使用固態硬盤(SSD),每秒大約也只能處理幾萬個命令,並且會大大下降SSD的壽命。

no:命令寫入aof_buf後調用系統write操做,不對AOF文件作fsync同步;同步由操做系統負責,一般同步週期爲30秒。這種狀況下,文件同步的時間不可控,且緩衝區中堆積的數據會不少,數據安全性沒法保證。
everysec:命令寫入aof_buf後調用系統write操做,write完成後線程返回;fsync同步文件操做由專門的線程每秒調用一次。everysec是前述兩種策略的折中,是性能和數據安全性的平衡,所以是Redis的默認配置,也是咱們推薦的配置。

文件重寫(rewrite)

由於AOF的運做方式是不斷地將命令追加到文件的末尾,因此隨着寫入命令的不斷增長,AOF文件的體積也會變得愈來愈大。舉個例子,若是你對一個計數器調用了100次INCR,那麼僅僅是爲了保存這個計數器的當前值,AOF文件就須要使用100條記錄(entry)。然而在實際上,只使用一條SET命令已經足以保存計數器的當前值了,其他99條記錄實際上都是多餘的。另外還有一些過時的數據,無效的數據也都是能夠去除。

過大的AOF文件不只會影響服務器的正常運行,也會致使數據恢復須要的時間過長。爲了處理這種狀況,Redis支持一種有趣的特性,能夠在不打斷服務客戶端的狀況下,對AOF文件進行重建(rebuild)。執行BGREWRITEAOF命令, Redis將生成一個新的AOF文件, 這個文件包含重建當前數據集所需的最少命令。

AOF REWRITE(重寫)生成過程和RDB快照相似,都巧妙地利用了寫時複製機制。一樣也是fork一個子進程(此時主線程是阻塞的),子進程根據內存快照,按照命令合併規則寫入到新的AOF文件。當主進程fork完子線程後繼續接受請求,全部寫命令依然寫入AOF緩衝區(aof_buf),並根據appendfsync策略同步到硬盤,保證原有AOF機制的正確。但因爲fork操做使用寫時複製技術,子進程只能共享fork操做時的內存數據。因爲父進程依然在響應命令,所以Redis使用AOF重寫緩衝區(aof_rewrite_buf)保存這部分新日誌,防止新AOF文件生成期間丟失這部分數據。也就是說,bgrewriteaof執行期間,Redis的寫命令同時追加到aof_buf和aof_rewirte_buf兩個緩衝區。

當子進程寫完新的AOF文件後,向父進程發信號,父進程更新統計信息,具體能夠經過info persistence查看。而後父進程把AOF重寫緩衝區的數據寫入到新的AOF文件,這樣就保證了新AOF文件所保存的數據庫狀態和服務器當前狀態一致。而後調用原子性的rename命令用新的AOF文件取代老的AOF文件,完成AOF重寫。

這裏須要注意,由於由主進程把aof_rewrite_buf緩存追加到新日誌文件。主進程追加日誌時,不會處理其餘請求,若是aof_rewrite_buf特別大,例如幾百M,也可能形成Redis幾秒甚至幾十秒不響應。

從上面的流程咱們可以看到,RDB和AOF操做都是順序IO操做,性能都很高。而在經過RDB文件或者AOF日誌進行數據庫恢復的時候,也是順序的讀取數據加載到內存中。因此也不會形成磁盤的隨機讀。

文件重寫的觸發,分爲手動觸發和自動觸發:

手動觸發:直接調用bgrewriteaof命令,該命令的執行與bgsave有些相似:都是fork子進程進行具體的工做,且都只有在fork時阻塞。

自動觸發:根據auto-aof-rewrite-min-size和auto-aof-rewrite-percentage參數,以及aof_current_size和aof_base_size狀態肯定觸發時機。

auto-aof-rewrite-min-size表示執行AOF重寫時,文件的最小體積,默認值爲64MB。

auto-aof-rewrite-percentage表示執行AOF重寫時,當前AOF大小(即aof_current_size)和上一次重寫時AOF大小(aof_base_size)的比值,即增加比例達到設定值。

只有當auto-aof-rewrite-min-size和auto-aof-rewrite-percentage兩個參數同時知足時,纔會自動觸發AOF重寫,即bgrewriteaof操做。

其中,參數能夠經過config get命令查看:

127.0.0.1:6391> CONFIG GET auto-aof-rewrite-min-size
1) "auto-aof-rewrite-min-size"
2) "64000000"
127.0.0.1:6391> CONFIG GET auto-aof-rewrite-percentage
1) "auto-aof-rewrite-percentage"
2) "100"

狀態能夠經過info persistence查看:

127.0.0.1:6379> info persistence
# Persistence
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:0
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_current_size:40876638
aof_base_size:2217565
aof_pending_rewrite:0
aof_buffer_length:0
aof_rewrite_buffer_length:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0

另外在aof rewrite過程當中,是否採起增量」文件同步」策略,由參數aof-rewrite-incremental-fsync控制,默認爲」yes」,並且必須爲yes。rewrite過程當中,每32M數據進行一次文件同步,這樣能夠減小」aof大文件」寫入對磁盤的操做次數。

bgrewriteaof機制,在一個子進程中進行aof的重寫,從而不阻塞主進程對其他命令的處理,同時解決了aof文件過大問題。如今問題出現了,同時在執行bgrewriteaof操做和主進程寫aof文件的操做,二者都會操做磁盤,而bgrewriteaof每每會涉及大量磁盤操做,這樣就會形成主進程在寫aof文件的時候出現阻塞的情形,如今no-appendfsync-on-rewrite參數出場了。

若是該參數設置爲no,是最安全的方式,不會丟失數據,可是要忍受阻塞的問題。若是設置爲yes呢?這就至關於將appendfsync設置爲no,這說明並無執行磁盤操做,只是寫入了緩衝區,所以這樣並不會形成阻塞(由於沒有競爭磁盤),可是若是這個時候Redis掛掉,就會丟失數據。丟失多少數據呢?在Linux的操做系統的默認設置下,最多會丟失30s的數據。所以,若是應用系統沒法忍受延遲,而能夠容忍少許的數據丟失,則設置爲yes。若是應用系統沒法忍受數據丟失,則設置爲no。

AOF刷新策略?

前面提到過,在AOF中,若是AOF緩衝區的文件同步策略爲everysec,則:在主線程中,命令寫入aof_buf後調用系統write操做,write完成後主線程返回;fsync同步文件操做由專門的文件同步線程每秒調用一次。這種作法的問題在於,若是硬盤負載太高,那麼fsync操做可能會超過1s;若是Redis主線程持續高速向aof_buf寫入命令,硬盤的負載可能會愈來愈大,IO資源消耗更快;若是此時Redis進程異常退出,丟失的數據也會愈來愈多,可能遠超過1s。

爲此,Redis的處理策略是這樣的:主線程每次進行AOF會對比上次fsync成功的時間;若是距上次不到2s(也就是延遲了1s),主線程直接返回;若是超過2s,則主線程阻塞直到上一次fsync同步完成。所以,若是系統硬盤負載過大致使fsync速度太慢,會致使Redis主線程的阻塞;此外,使用everysec配置,AOF最多可能丟失2s的數據,而不是1s。具體看Redis AOF刷新策略分析

AOF追加阻塞問題定位的方法,監控info Persistence中的aof_delayed_fsync,當AOF追加阻塞發生時(即主線程等待fsync而阻塞),該指標累加。另外,AOF阻塞時的Redis日誌:Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.

若是AOF追加阻塞頻繁發生,說明系統的硬盤負載太大;能夠考慮更換IO速度更快的硬盤,或者經過IO監控分析工具對系統的IO負載進行分析。

對於pipelining有什麼不一樣?

對於pipelining的操做,其具體過程是客戶端一次性發送N個命令,而後等待這N個命令的返回結果被一塊兒返回。經過採用pipilining就意味着放棄了對每個命令的返回值確認。因爲在這種狀況下,N個命令是在同一個執行過程當中執行的。因此當設置appendfsync爲everysec時,可能會有一些誤差,由於這N個命令可能執行時間超過1秒甚至2秒。可是能夠保證的是,最長時間不會超過這N個命令的執行時間和。

若是AOF文件出錯了,怎麼辦?

服務器可能在程序正在對AOF文件進行寫入時停機,若是停機形成了 AOF 文件出錯(corrupt),那麼Redis在重啓時會拒絕載入這個AOF文件, 從而確保數據的一致性不會被破壞。當發生這種狀況時,能夠用如下方法來修復出錯的 AOF 文件:爲現有的AOF文件建立一個備份。而後使用Redis附帶的redis-check-aof --fix程序對原來的AOF文件進行修復。

而後可選使用 diff -u 對比修復後的 AOF 文件和原始 AOF 文件的備份,查看兩個文件之間的不一樣之處。再次重啓Redis服務器,等待服務器載入修復後的AOF文件,並進行數據恢復。

但若是是AOF文件結尾不完整(機器忽然宕機等容易致使文件尾部不完整),且aof-load-truncated參數開啓,則日誌中會輸出警告,Redis忽略掉AOF文件的尾部,啓動成功。aof-load-truncated參數默認是開啓的。

RDB和AOF優缺點

RDB的優勢?

RDB是一個很是緊湊(compact)的文件,體積小,網絡傳輸快,它保存了Redis在某個時間點上的數據集。這種文件很是適合用於進行備份,恢復速度比AOF快不少。固然,與AOF相比,RDB最重要的優勢之一是對性能的影響相對較小。父進程在保存RDB文件時惟一要作的就是fork出一個子進程,而後這個子進程就會處理接下來的全部保存工做,父進程無須執行任何磁盤 I/O 操做。

RDB的缺點?

RDB文件的致命缺點在於其數據快照的持久化方式決定了必然作不到實時持久化,而在數據愈來愈重要的今天,數據的大量丟失不少時候是沒法接受的,所以AOF持久化成爲主流。此外,RDB文件須要知足特定格式,兼容性差(如老版本的Redis不兼容新版本的RDB文件)。

AOF的優勢?

與RDB持久化相對應,AOF的優勢在於支持秒級持久化、兼容性好。你能夠設置不一樣的fsync策略,好比無fsync,每秒鐘一次fsync,或者每次執行寫入命令時fsync。AOF的默認策略爲每秒鐘fsync一次,在這種配置下,Redis仍然能夠保持良好的性能,而且就算髮生故障停機,也最多隻會丟失一秒鐘的數據。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文件的體積、且恢復速度慢。對於相同的數據集來講,根據所使用的fsync策略,AOF的速度可能會慢於RDB。在通常狀況下,每秒fsync的性能依然很是高,而關閉fsync可讓AOF的速度和RDB同樣快。另外,AOF在過去曾經發生過這樣的bug,由於個別命令的緣由,致使AOF文件在從新載入時,沒法將數據集恢復成保存時的原樣。雖然這種bug在AOF文件中並不常見,可是對比來講,RDB幾乎是不可能出現這種bug的。

RDB和AOF,我應該用哪個?

首先要明白不管是RDB仍是AOF,持久化的開啓都是要付出性能方面代價的:對於RDB持久化,一方面是bgsave在進行fork操做時Redis主進程會阻塞,另外一方面,子進程向硬盤寫數據也會帶來IO壓力。但若是業務能容忍幾分鐘到10幾分鐘的數據丟失(且不使用備庫),RDB是一個不錯的選擇;否則,就選擇AOF。

對於AOF持久化,向硬盤寫數據的頻率大大提升(everysec策略下爲秒級),IO壓力更大,甚至可能形成AOF追加阻塞問題(後面會詳細介紹這種阻塞),此外,AOF文件的重寫與RDB的bgsave相似,會有fork時的阻塞和子進程的IO壓力問題。相對來講,因爲AOF向硬盤中寫數據的頻率更高,所以對Redis主進程性能的影響會更大。

在實際生產環境中,根據數據量、應用對數據的安全要求、預算限制等不一樣狀況,會有各類各樣的持久化策略;如徹底不使用任何持久化、使用RDB或AOF的一種,或同時開啓RDB和AOF持久化等。此外,持久化的選擇必須與Redis的主從策略一塊兒考慮,由於主從複製與持久化一樣具備數據備份的功能,並且主機master和從機slave能夠獨立的選擇持久化方案。好比徹底關閉master持久化(包括RDB和AOF),這樣可讓master的性能達到最好;而slave能夠只開啓AOF。但這種狀況下,若是master服務由於故障宕掉了,若是系統中有自動拉起機制(即檢測到服務中止後重啓該服務)將master自動重啓,因爲沒有持久化文件,那麼master重啓後數據是空的,slave同步數據也變成了空的,意味着數據丟失。因此儘可能避免這種狀況出現。

RDB和AOF之間的相互做用?

在版本號大於等於2.4的Redis中,BGSAVE執行的過程當中,不能夠執行BGREWRITEAOF。反過來講,在BGREWRITEAOF執行的過程當中,也不能夠執行BGSAVE。這能夠防止兩個Redis後臺進程同時對磁盤進行大量的I/O操做。

若是BGSAVE正在執行,而且用戶顯示地調用BGREWRITEAOF命令,那麼服務器將向用戶回覆一個OK狀態,並告知用戶,BGREWRITEAOF已經被預約執行: 一旦BGSAVE執行完畢,BGREWRITEAOF就會正式開始。當Redis啓動時,若是RDB持久化和AOF持久化都被打開了,那麼程序會優先使用AOF文件來恢復數據集,由於AOF文件所保存的數據一般是最完整的。

RDB和AOF數據導入

這些持久化的數據有什麼用,固然是用於重啓後的數據恢復。Redis是一個內存數據庫,不管是RDB仍是AOF,都只是其保證數據恢復的措施。因此Redis在利用RDB或AOF進行恢復的時候,會讀取RDB或AOF文件,從新加載到內存中。相對於MySQL等數據庫的啓動時間來講,會長不少,由於MySQL原本是不須要將數據加載到內存中的。

可是相對來講,MySQL啓動後提供服務時,其被訪問的熱數據也會慢慢加載到內存中,一般咱們稱之爲預熱,而在預熱完成前,其性能都不會過高。而Redis的好處是一次性將數據加載到內存中,一次性預熱。這樣只要Redis啓動完成,那麼其提供服務的速度都是很是快的。

而在利用RDB和利用AOF啓動上,其啓動時間有一些差異。RDB的啓動時間會更短,緣由有兩個,一是RDB文件中每一條數據只有一條記錄,不會像AOF日誌那樣可能有一條數據的屢次操做記錄。因此每條數據只須要寫一次就好了。另外一個緣由是RDB文件的存儲格式和Redis數據在內存中的編碼格式是一致的,不須要再進行數據編碼工做。在CPU消耗上要遠小於AOF日誌的加載。

注意:當redis啓動時,若是rdb持久化和aof持久化都打開了,那麼程序會優先使用aof方式來恢復數據集,由於aof方式所保存的數據一般是最完整的。若是aof文件丟失了,則啓動以後數據庫內容爲空。

注意:若是想把正在運行的redis數據庫,從RDB切換到AOF,建議先使用動態切換方式,再修改配置文件,重啓數據庫。(不能直接修改配置文件,重啓數據庫,不然數據庫中數據就爲空了。)
在Redis 2.2或以上版本,能夠在不重啓的狀況下,從RDB切換到AOF :

爲最新的dump.rdb文件建立一個備份,將備份放到一個安全的地方。執行如下兩條命令:

127.0.0.1:6379> CONFIG SET dir /apps/redis/data/redis-8836
127.0.0.1:6379> CONFIG SET appendonly yes
127.0.0.1:6379> CONFIG SET save ""

確保命令執行以後,數據庫的鍵的數量沒有改變。確保寫命令會被正確地追加到 AOF 文件的末尾。

步驟2是開啓了AOF功能,Redis會阻塞直到初始AOF文件建立完成爲止,以後Redis會繼續處理命令請求,並開始將寫入命令追加到AOF文件末尾。

步驟3用於關閉RDB功能,這一步是可選的,若是你願意的話,也能夠同時使用RDB和AOF這兩種持久化功能。

相關文章
相關標籤/搜索