Redis持久化方式RDB與AOF詳解

前言

創(chuàng)新互聯長期為1000多家客戶提供的網站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯網生態(tài)環(huán)境。為浦江企業(yè)提供專業(yè)的網站設計制作、成都做網站,浦江網站改版等技術服務。擁有十載豐富建站經驗和眾多成功案例,為您定制開發(fā)。


redis提供了兩種數據存儲方式,分別是:cache-only && persistence;cache-only顧名知義,是用與緩存服務的,數據在

 

RDB持久化方式


RDB是"Redis DataBase"的簡稱,RDB持久化是指按指定的策略將內存中的數據集快照并寫入磁盤。是默認的持久化方式,這種方式就是將內存中數據以快照的方式寫入到二進制文件中,默認的文件名為dump.rdb??梢酝ㄟ^修改配置文件設置自動做快照的方式。我們可以設置redis在n秒內如果超過m次key被修改就自動做快照,下面是默認的快照保存配置。匹配優(yōu)先級由下到上。

 

save 900 1                    # 900秒內如果超過1次key被修改,則發(fā)起快照保存

save 300 10                  # 300秒內超過10次key被修改,則發(fā)起快照保存

save 60   10000            # 60s內發(fā)生10000次可以值修改,則發(fā)起快照

 

1 RDB文件存儲過程

1)當有相關操作時,redis父進程調用fork(),創(chuàng)建子進程。

2)父進程繼續(xù)處理client請求,子進程負責將內存內容寫入到臨時文件。由于os的寫時復制機制(copy on write)父子進程會共享相同的物理頁面,當父進程處理寫請求時os會為父進程要修改的頁面創(chuàng)建副本,而不是寫共享的頁面。所以子進程的地址空間中的數 據是fork()時刻整個數據庫的一個快照。

3)當子進程將快照寫入臨時文件完畢后,用臨時文件替換原有的快照文件,然后子進程退出。

Redis的client也可以使用"save"或者"bgsave"命令通知redis做一次快照持久化。save操作是在主線程中保存快照的,由于redis是用一個主線程(即單進程)來處理所有client的請求,這種方式將會阻塞所有client請求,不推薦使用。

值得注意的是,每次RDB都是將內存數據完整寫入到磁盤一次,并不是增量的只同步臟數據。如果數據量大的話,而且寫操作比較多,必然會引起大量的磁盤IO操作,可能會嚴重影響性能。

 

2 RDB的優(yōu)勢

1)一旦采用該方式,那么你的整個Redis數據庫將只包含一個文件,這樣非常方便進行備份。比如你可以每1天備份一次數據,而不用擔心磁盤空間不夠。而且我們可以很容易的將一個RDB文件移動到其他的存儲介質上。

2)RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。

3)RDB 可以最大化Redis的性能:父進程在保存RDB文件時唯一要做的就是調用fork()生成子進程,然后這個子進程就會處理接下來的所有保存工作,而父進程無需參與磁盤IO,大大提升性能。

 

3 RDB的劣勢

1)如果服務器運行時發(fā)生故障,那么RDB方式將會丟失數據,雖然Redis允許你設置不同的保存點(save point)來控制保存RDB文件的頻率, 但是, 因為RDB 文件需要保存整個數據集的狀態(tài),所以它并不是一個輕松的操作。 因此你可能會至少 5 分鐘才保存一次RDB文件。 在這種情況下, 一旦發(fā)生故障停機, 你就可能會丟失好備份時間段中的數據。

2)每次保存 RDB 的時候,Redis都要fork()出一個子進程,并由子進程來進行實際的持久化工作。在數據集比較龐大時,fork() 可能會非常耗時,造成服務器在某毫秒內停止處理客戶端; 如果數據集非常巨大,并且 CPU 時間非常緊張的話,那么這種停止時間甚至可能會長達整整一秒。 雖然AOF重寫也需要進行fork() ,但無論AOF重寫的執(zhí)行間隔有多長,數據的耐久性都不會有任何損失。

 

4 RDB的相關配置參數

除了上面用于定義RDB快照條件的項之外,還有一些其他的配置參數,放置在配置文件"/etc/redis.conf"中的"SNAPSHOTTING"字段中;詳細信息如下:

rdbcompression yes                             # 是否開啟壓縮功能

rdbchecksum yes                                 # 檢測數據校驗和

dbfilename dump.rdb                          # 數據集文件名

dir /var/lib/redis                                  # 數據存放目錄

stop-writes-on-bgsave-error yes       # 默認情況下,如果啟用了RDB快照(至少有一個保存點),而最新的數據保存失敗,將停止接受寫入。這將使用戶(以一種困難的方式)意識到數據并不是正確地在磁盤上進行持續(xù)的,否則很可能沒有人會注意到,并且會發(fā)生一些錯誤,即使存在磁盤、權限等問題,仍然照常工作。如果后臺保存進程再次開始工作,Redis將自動允許再次寫入。 但是,如果您已經設置了對Redis服務器和持久性的正確監(jiān)視,則應該禁用此功能,以便即使磁盤,權限等方面存在問題,Redis也將照常繼續(xù)工作。

 

AOF持久化方式


AOF是"Append-Only File"的簡稱,是一種將內存中的數據以命令的方式追加保存至臨時文件中,然后依賴次此文件進行數據重現的方式。

 

1 AOF文件保存過程

redis會將每一個收到的寫命令都通過write函數追加到文件中(默認是appendonly.aof)。當redis重啟時會通過重新執(zhí)行文件中保存的寫命令在內存中重建整個數據庫的內容。當然由于os會在內核中緩存 write做的修改,所以可能不是立即寫到磁盤上。這樣AOF方式的持久化也還是有可能會丟失部分修改。不過我們可以通過選項告訴redis我們想要 通過fsync函數強制os寫入到磁盤。有三種方式如下(默認是:每秒fsync一次)

 

appendonly yes               # 啟用aof持久化方式

appendfsync always        # 每次收到寫命令就立即強制寫入磁盤,雖然保證完全的持久化,但是嚴重影響性能,不推薦使用。

appendfsync everysec     # 每秒鐘強制寫入磁盤一次,在性能和持久化方面做了很好的折中,推薦。

appendfsync no              # 完全依賴os,即Redis在不參與。這種性能最好,但持久化沒保證。

 

AOF的方式也同時帶來了另一個問題。持久化文件會變的越來越大。例如我們調用"incr count"命令100次,文件中必須保存全部的100條命令,其實前99條都是多余的。因為要恢復數據庫的狀態(tài)時只需要執(zhí)行"set test 100"就夠了。為了壓縮aof的持久化文件。redis提供了"bgrewriteaof"命令。收到此命令redis將使用與快照類似的方式將內存中的數據 以命令的方式保存到臨時文件中(類似于MySQL中的二進制日志),最后替換原來的文件。具體過程如下:

1)redis調用fork ,生成子進程

2)子進程根據內存中的數據庫快照,向臨時文件中寫入重建數據庫狀態(tài)的命令

3)父進程繼續(xù)處理client請求,除了把寫命令寫入到原來的aof文件中。同時把收到的寫命令緩存起來。這樣就能保證如果子進程重寫失敗的話并不會出問題。

4)當子進程把快照內容以命令的方式寫到臨時文件中后,子進程發(fā)信號通知父進程。然后父進程把緩存的寫命令也追加寫入到臨時文件中。

5)現在父進程可以使用臨時文件替換老的aof文件,并重命名,后面收到的寫命令也開始往新的aof文件中追加。

值得注意的是:重寫aof文件的操作,并沒有讀取舊的aof文件,而是將整個內存中的數據庫內容以命令的方式重寫至了一個新的aof文件,這點和快照有點類似。

 

2 AOF持久化優(yōu)勢

1)使用 AOF 持久化會讓 Redis 變得非常耐久(much more durable):你可以設置不同的 fsync 策略,比如無 fsync ,每秒鐘一次 fsync ,或者每次執(zhí)行寫入命令時 fsync 。 AOF 的默認策略為每秒鐘 fsync 一次,在這種配置下,Redis 仍然可以保持良好的性能,并且就算發(fā)生故障停機,也最多只會丟失一秒鐘的數據( fsync 會在后臺線程執(zhí)行,所以主線程可以繼續(xù)努力地處理命令請求)。

2)AOF文件是一個只進行追加操作的日志文件(append only log), 因此對AOF文件的寫入不需要進行seek, 即使日志因為某些原因而包含了未寫入完整的命令(比如寫入時磁盤已滿,寫入中途停機,等等), redis-check-aof 工具也可以輕易地修復這種問題。

Redis 可以在 AOF 文件體積變得過大時,自動地在后臺對 AOF 進行重寫: 重寫后的新 AOF 文件包含了恢復當前數據集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在創(chuàng)建新 AOF 文件的過程中,會繼續(xù)將命令追加到現有的 AOF 文件里面,即使重寫過程中發(fā)生停機,現有的 AOF 文件也不會丟失。 而一旦新 AOF 文件創(chuàng)建完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,并開始對新 AOF 文件進行追加操作。

3)AOF 文件有序地保存了對數據庫執(zhí)行的所有寫入操作, 這些寫入操作以 Redis 協(xié)議的格式保存, 因此 AOF 文件的內容非常容易被人讀懂, 對文件進行分析(parse)也很輕松。 導出(export) AOF 文件也非常簡單: 舉個例子, 如果你不小心執(zhí)行了FLUSHALL命令, 但只要 AOF 文件未被重寫,那么只要停止服務器,移除AOF文件末尾的FLUSHALL命令,并重啟Redis ,就可以將數據集恢復到FLUSHALL執(zhí)行之前的狀態(tài)。

 

3 AOF持久化的劣勢

1)對于相同的數據集來說,AOF 文件的體積通常要大于 RDB 文件的體積。

2)根據所使用的 fsync 策略,AOF 的速度可能會慢于 RDB 。在一般情況下,每秒 fsync 的性能依然非常高,而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。不過在處理巨大的寫入載入時,RDB 可以提供更有保證的最大延遲時間(latency)。

3)AOF在過去曾經發(fā)生過這樣的 bug : 因為個別命令的原因,導致 AOF 文件在重新載入時,無法將數據集恢復成保存時的原樣。(例如,阻塞命令 BRPOPLPUSH 就曾經引起過這樣的bug) 測試套件里為這種情況添加了測試:它們會自動生成隨機的、復雜的數據集, 并通過重新載入這些數據來確保一切正常。雖然這種 bug 在 AOF 文件中并不常見,但是對比來說,RDB幾乎是不可能出現這種bug的。

 

4 AOF的相關配置參數

關于Redis的持久化方式之一"AOF",與其相關的配置項放置在Redis配置文件"/etc/redis.conf"中的"APPEND ONLY MODE"字段中;與其相關的參數如下:

 

# 開啟AOF持久化模式

appendonly no  

 

# The name of the append only file (default: "appendonly.aof")

appendfilename "appendonly.aof"

 

# AOF持久化方式,只要分為三種,有寫操作就fsync(影響性能)、每秒fync(折中方式,只丟失1s數據)以及OS執(zhí)行刷寫(持久化無保證),

# appendfsync always

appendfsync everysec

# appendfsync no

 

# 是否在后臺執(zhí)行aof重寫期間不調用fsync,默認為no,表示調用;當AOF的fsync策略設置為always或everysec時,并且后臺保存進程(后臺保存或AOF日志背景重寫)對磁盤執(zhí)行大量I/O時,Redis可能在fsync()調用上阻塞太久。目前并沒有解決此問題的方法,因為即使在其他線程中執(zhí)行fsync也會阻止我們的同步寫入調用。為了減輕這個問題,可以使用下面的選項來防止在BGSAVE或BGREWRITEAOF進程中在主進程中調用fsync()。這意味著,當另一個子進程正在保存時,Redis的持久性與"appendfsync none"相同。這意味著在最壞的情況下(使用默認的設置),最多可能會丟失30秒的日志。 如果有延遲問題,請將其轉為"yes"

no-appendfsync-on-rewrite no

 

# 定義文件重寫頻度,有兩個參數,一是百分不,即系列第一條命令;二是按AOF日志大小,默認為64MB。如果日志當前的增漲量大于預定義的增長率(百分比)則觸發(fā)重寫。此外,您還需要指定要重寫的AOF文件的最小大小,即使達到了百分比增加但仍然非常小,這對于避免重寫AOF文件很有用。指定百分比為零,表示禁用自動AOF重寫功能。

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

 

# 在Redis啟動過程中,當AOF數據被加載回內存時,可能會發(fā)現一個AOF文件被截斷。如果將AOF-load-truncated設置為yes,則會加載一個截斷的AOF文件,而Redis服務器開始發(fā)出日志,以通知該事件的用戶。如果該選項被設置為no,服務器將以錯誤中止并拒絕啟動。當選項設置為no時,用戶需要使用"redis-checkaof"實用程序修復AOF文件,然后再重新啟動服務器。

aof-load-truncated yes

 

總結:


一般來說, 如果想達到足以媲美 PostgreSQL 的數據安全性,你應該同時使用兩種持久化功能。如果你非常關心你的數據,但仍然可以承受數分鐘以內的數據丟失,那么你可以只使用RDB持久化。

 

新聞標題:Redis持久化方式RDB與AOF詳解
文章地址:http://muchs.cn/article24/gjsije.html

成都網站建設公司_創(chuàng)新互聯,為您提供響應式網站、云服務器做網站、用戶體驗、服務器托管、靜態(tài)網站

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

成都網頁設計公司