久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

如何進行Redis持久化RDB和AOF的分析

196次閱讀
沒有評論

共計 11937 個字符,預計需要花費 30 分鐘才能閱讀完成。

如何進行 Redis 持久化 RDB 和 AOF 的分析,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

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 文件。

在默認情況下,Redis 將數據庫快照保存在根目錄下,名字為 dump.rdb 的二進制文件中。可通過參數 dir 配置指定保存目錄,dbfilename 指定文件名。你可以對 Redis 進行設置,如“save N M”,表示 N 秒內數據項中有 M 個改動時這一條件被滿足時,自動保存一次數據集。比如你可以配置當 10 分鐘以內有 100 次寫入就生成快照,也可以配置當 1 分鐘內有 1000 次寫入就生成快照,支持可以多個規則一起生效,當匹配到哪個就哪個規則生效。這些規則的定義就在 Redis 的配置文件中,你也可以通過 Redis 的 CONFIG SET 命令在 Redis 運行時設置規則,不需要重啟 Redis。

比如說,以下設置會讓 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 這兩種持久化功能。

看完上述內容,你們掌握如何進行 Redis 持久化 RDB 和 AOF 的分析的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注丸趣 TV 行業資訊頻道,感謝各位的閱讀!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-19發表,共計11937字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 汉沽区| 黎川县| 阳泉市| 平舆县| 高州市| 同心县| 平和县| 淅川县| 临桂县| 望江县| 西安市| 柳河县| 阳谷县| 新余市| 个旧市| 休宁县| 香格里拉县| 吴桥县| 甘孜| 沈丘县| 大悟县| 广水市| 平乡县| 卢氏县| 博客| 六枝特区| 潮州市| 仁寿县| 江西省| 化州市| 通山县| 荔波县| 龙海市| 文成县| 新乡市| 郸城县| 曲阳县| 长丰县| 即墨市| 屏东市| 尉氏县|