自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解Redis的持久化機制--RDB和AOF

存儲 存儲軟件 Redis
redis跟memcached類似,都是內存數(shù)據(jù)庫,不過redis支持數(shù)據(jù)持久化,也就是說redis可以將內存中的數(shù)據(jù)同步到磁盤來持久化,以確保redis 的數(shù)據(jù)安全。不過持久化這塊可能比較容易產生誤解,下面聊聊這塊。

redis跟memcached類似,都是內存數(shù)據(jù)庫,不過redis支持數(shù)據(jù)持久化,也就是說redis可以將內存中的數(shù)據(jù)同步到磁盤來持久化,以確保redis 的數(shù)據(jù)安全。不過持久化這塊可能比較容易產生誤解,下面聊聊這塊。

Redis持久化是如何工作的?

什么是持久化?簡單來講就是將數(shù)據(jù)放到斷電后數(shù)據(jù)不會丟失的設備中,也就是我們通常理解的硬盤上。

1. 數(shù)據(jù)庫寫操作的5個過程

首先我們來看一下數(shù)據(jù)庫在進行寫操作時到底做了哪些事,主要有下面五個過程:

  • 客戶端向服務端發(fā)送寫操作(數(shù)據(jù)在客戶端的內存中)。
  • 數(shù)據(jù)庫服務端接收到寫請求的數(shù)據(jù)(數(shù)據(jù)在服務端的內存中)。
  • 服務端調用write這個系統(tǒng)調用,將數(shù)據(jù)往磁盤上寫(數(shù)據(jù)在系統(tǒng)內存的緩沖區(qū)中)。
  • 操作系統(tǒng)將緩沖區(qū)中的數(shù)據(jù)轉移到磁盤控制器上(數(shù)據(jù)在磁盤緩存中)。
  • 磁盤控制器將數(shù)據(jù)寫到磁盤的物理介質中(數(shù)據(jù)真正落到磁盤上)。

2. 故障分析

寫操作大致有上面5個流程,當數(shù)據(jù)庫系統(tǒng)故障時,這時候系統(tǒng)內核還是完好的。那么此時只要我們執(zhí)行完了第3步,那么數(shù)據(jù)就是安全的,因為后續(xù)操作系統(tǒng)會來完成后面幾步,保證數(shù)據(jù)最終會落到磁盤上。當系統(tǒng)斷電時,這時候上面5項中提到的所有緩存都會失效,并且數(shù)據(jù)庫和操作系統(tǒng)都會停止工作。所以只有當數(shù)據(jù)在完成第5步后,才能保證在斷電后數(shù)據(jù)不丟失。

【補充】這里可能有幾個疑問:

  • 數(shù)據(jù)庫多長時間調用一次write,將數(shù)據(jù)寫到內核緩沖區(qū)?
  • 內核多長時間會將系統(tǒng)緩沖區(qū)中的數(shù)據(jù)寫到磁盤控制器?
  • 磁盤控制器又在什么時候把緩存中的數(shù)據(jù)寫到物理介質上?

對于***個問題,通常數(shù)據(jù)庫層面會進行全面控制。

而對第二個問題,操作系統(tǒng)有其默認的策略,但是我們也可以通過POSIX API提供的fsync系列命令強制操作系統(tǒng)將數(shù)據(jù)從內核區(qū)寫到磁盤控制器上。

對于第三個問題,看起來數(shù)據(jù)庫已經無法觸及,但實際上,大多數(shù)情況下磁盤緩存是被設置關閉的,或者是只開啟為讀緩存,也就是說寫操作不會進行緩存,直接寫到磁盤。建議的做法是僅僅當你的磁盤設備有備用電池時才開啟寫緩存。

3. 數(shù)據(jù)損壞

所謂數(shù)據(jù)損壞,就是數(shù)據(jù)無法恢復,上面我們講的都是如何保證數(shù)據(jù)是確實寫到磁盤上去,但是寫到磁盤上可能并不意味著數(shù)據(jù)不會損壞。比如我們可能一次寫請求會進行兩次不同的寫操作,當意外發(fā)生時,可能會導致一次寫操作安全完成,但是另一次還沒有進行。如果數(shù)據(jù)庫的數(shù)據(jù)文件結構組織不合理,可能就會導致數(shù)據(jù)完全不能恢復的狀況出現(xiàn)。

三種解決策略:

  • 最粗糙的處理,就是不通過數(shù)據(jù)的組織形式保證數(shù)據(jù)的可恢復性。而是通過配置數(shù)據(jù)同步備份的方式,在數(shù)據(jù)文件損壞后通過數(shù)據(jù)備份來進行恢復。實際上MongoDB在不開啟操作日志,通過配置Replica Sets時就是這種情況。
  • 在上面基礎上添加一個操作日志,每次操作時記一下操作的行為,這樣我們可以通過操作日志來進行數(shù)據(jù)恢復。因為操作日志是順序追加的方式寫的,所以不會出現(xiàn)操作日志也無法恢復的情況。這也類似于MongoDB開啟了操作日志的情況。
  • 更保險的做法是數(shù)據(jù)庫不進行舊數(shù)據(jù)的修改,只是以追加方式去完成寫操作,這樣數(shù)據(jù)本身就是一份日志,這樣就永遠不會出現(xiàn)數(shù)據(jù)無法恢復的情況了。實際上CouchDB就是此做法的優(yōu)秀范例。

那么,redis又針對持久化提供了什么方式呢?

redis持久化的兩種方式

redis提供了兩種持久化的方式,分別是RDB(Redis DataBase)和AOF(Append Only File)。

RDB,簡而言之,就是將存儲的數(shù)據(jù)快照的方式存儲到磁盤上,

AOF,則是將redis執(zhí)行過的所有寫指令記錄下來,通過write函數(shù)追加到AOF文件的末尾。在下次redis重新啟動時,只要把這些寫指令從前到后再重復執(zhí)行一遍,就可以實現(xiàn)數(shù)據(jù)恢復了。

RDB機制

1. 概念

RDB持久化是指在指定的時間間隔內將內存中的數(shù)據(jù)集快照寫入磁盤。也是默認的持久化方式,這種方式是就是將內存中數(shù)據(jù)以快照的方式寫入到二進制文件中,默認的文件名為dump.rdb。

詳解Redis 的持久化機制--RDB和AOF

可以通過配置設置自動做快照持久化的方式。我們可以配置redis在n秒內如果超過m個key被修改就自動做快照,下面是默認的快照保存配置

  1. save 900 1 #900秒內如果超過1個key被修改,則發(fā)起快照保存 
  2. save 300 10 #300秒內容如超過10個key被修改,則發(fā)起快照保存 
  3. save 60 10000 

2. RDB文件保存過程

  • redis調用fork,現(xiàn)在有了子進程和父進程。
  • 父進程繼續(xù)處理client請求,子進程負責將內存內容寫入到臨時文件。由于os的寫時復制機制(copy on write)父子進程會共享相同的物理頁面,當父進程處理寫請求時os會為父進程要修改的頁面創(chuàng)建副本,而不是寫共享的頁面。所以子進程的地址空間內的數(shù) 據(jù)是fork時刻整個數(shù)據(jù)庫的一個快照。
  • 當子進程將快照寫入臨時文件完畢后,用臨時文件替換原來的快照文件,然后子進程退出。

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

另一點需要注意的是,每次快照持久化都是將內存數(shù)據(jù)完整寫入到磁盤一次,并不是增量的只同步臟數(shù)據(jù)。如果數(shù)據(jù)量大的話,而且寫操作比較多,必然會引起大量的磁盤io操作,可能會嚴重影響性能。

3. 優(yōu)勢

  • 一旦采用該方式,那么你的整個Redis數(shù)據(jù)庫將只包含一個文件,這樣非常方便進行備份。比如你可能打算每1天歸檔一些數(shù)據(jù)。
  • 方便備份,我們可以很容易的將一個一個RDB文件移動到其他的存儲介質上
  • RDB 在恢復大數(shù)據(jù)集時的速度比 AOF 的恢復速度要快。
  • RDB 可以***化 Redis 的性能:父進程在保存 RDB 文件時唯一要做的就是 fork 出一個子進程,然后這個子進程就會處理接下來的所有保存工作,父進程無須執(zhí)行任何磁盤 I/O 操作。

4. 劣勢

  • 如果你需要盡量避免在服務器故障時丟失數(shù)據(jù),那么 RDB 不適合你。 雖然 Redis 允許你設置不同的保存點(save point)來控制保存 RDB 文件的頻率, 但是, 因為RDB 文件需要保存整個數(shù)據(jù)集的狀態(tài), 所以它并不是一個輕松的操作。 因此可能會至少 5 分鐘才保存一次 RDB 文件。 在這種情況下, 一旦發(fā)生故障停機就可能會丟失好幾分鐘的數(shù)據(jù)。
  • 每次保存 RDB 的時候,Redis 都要 fork() 出一個子進程,并由子進程來進行實際的持久化工作。 在數(shù)據(jù)集比較龐大時, fork() 可能會非常耗時,造成服務器在某某毫秒內停止處理客戶端; 如果數(shù)據(jù)集非常巨大,并且 CPU 時間非常緊張的話,那么這種停止時間甚至可能會長達整整一秒。 雖然 AOF 重寫也需要進行 fork() ,但無論 AOF 重寫的執(zhí)行間隔有多長,數(shù)據(jù)的耐久性都不會有任何損失。

AOF

1. 概念

redis會將每一個收到的寫命令都通過write函數(shù)追加到文件中(默認是 appendonly.aof)。

當redis重啟時會通過重新執(zhí)行文件中保存的寫命令來在內存中重建整個數(shù)據(jù)庫的內容。當然由于os會在內核中緩存 write做的修改,所以可能不是立即寫到磁盤上。這樣aof方式的持久化也還是有可能會丟失部分修改。

詳解Redis 的持久化機制--RDB和AOF

可以通過配置文件告訴redis通過fsync函數(shù)強制os寫入到磁盤的時機。有三種方式如下(默認是:每秒fsync一次)

  1. appendonly yes //啟用aof持久化方式 
  2. # appendfsync always //每次收到寫命令就立即強制寫入磁盤,最慢的,但是保證完全的持久化,不推薦使用 
  3. appendfsync everysec //每秒鐘強制寫入磁盤一次,在性能和持久化方面做了很好的折中,推薦 
  4. # appendfsync no //完全依賴os,性能***,持久化沒保證 

2. AOF文件保存過程

aof 的方式也同時帶來了另一個問題。持久化文件會變的越來越大。例如我們調用incr test命令100次,文件中必須保存全部的100條命令,其實有99條都是多余的。因為要恢復數(shù)據(jù)庫的狀態(tài)其實文件中保存一條set test 100就夠了。

為了壓縮aof的持久化文件。redis提供了bgrewriteaof命令。收到此命令redis將使用與快照類似的方式將內存中的數(shù)據(jù) 以命令的方式保存到臨時文件中,***替換原來的文件。具體過程如下:

詳解Redis 的持久化機制--RDB和AOF

  • redis調用fork ,現(xiàn)在有父子兩個進程
  • 子進程根據(jù)內存中的數(shù)據(jù)庫快照,往臨時文件中寫入重建數(shù)據(jù)庫狀態(tài)的命令
  • 父進程繼續(xù)處理client請求,除了把寫命令寫入到原來的aof文件中。同時把收到的寫命令緩存起來。這樣就能保證如果子進程重寫失敗的話并不會出問題。
  • 當子進程把快照內容寫入已命令方式寫到臨時文件中后,子進程發(fā)信號通知父進程。然后父進程把緩存的寫命令也寫入到臨時文件。
  • 現(xiàn)在父進程可以使用臨時文件替換老的aof文件,并重命名,后面收到的寫命令也開始往新的aof文件中追加。

需要注意到是重寫aof文件的操作,并沒有讀取舊的aof文件,而是將整個內存中的數(shù)據(jù)庫內容用命令的方式重寫了一個新的aof文件,這點和快照有點類似。

3. 優(yōu)勢

  • 使用 AOF 持久化會讓 Redis 變得非常耐久:你可以設置不同的 fsync 策略,比如無 fsync ,每秒鐘一次 fsync ,或者每次執(zhí)行寫入命令時 fsync 。AOF 的默認策略為每秒鐘 fsync 一次,在這種配置下,Redis 仍然可以保持良好的性能,并且就算發(fā)生故障停機,也最多只會丟失一秒鐘的數(shù)據(jù)( fsync 會在后臺線程執(zhí)行,所以主線程可以繼續(xù)努力地處理命令請求)。
  • AOF 文件是一個只進行追加操作的日志文件, 因此對 AOF 文件的寫入不需要進行 seek , 即使日志因為某些原因而包含了未寫入完整的命令(比如寫入時磁盤已滿,寫入中途停機,等等), redis-check-aof 工具也可以輕易地修復這種問題。
  • Redis 可以在 AOF 文件體積變得過大時,自動地在后臺對 AOF 進行重寫: 重寫后的新 AOF 文件包含了恢復當前數(shù)據(jù)集所需的最小命令集合。 整個重寫操作是絕對安全的,因為 Redis 在創(chuàng)建新 AOF 文件的過程中,會繼續(xù)將命令追加到現(xiàn)有的 AOF 文件里面,即使重寫過程中發(fā)生停機,現(xiàn)有的 AOF 文件也不會丟失。 而一旦新 AOF 文件創(chuàng)建完畢,Redis 就會從舊 AOF 文件切換到新 AOF 文件,并開始對新 AOF 文件進行追加操作。
  • AOF 文件有序地保存了對數(shù)據(jù)庫執(zhí)行的所有寫入操作, 這些寫入操作以 Redis 協(xié)議的格式保存, 因此 AOF 文件的內容非常容易被人讀懂, 對文件進行分析(parse)也很輕松。 導出(export) AOF 文件也非常簡單: 舉個例子, 如果你不小心執(zhí)行了 FLUSHALL 命令, 但只要 AOF 文件未被重寫, 那么只要停止服務器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重啟 Redis , 就可以將數(shù)據(jù)集恢復到 FLUSHALL 執(zhí)行之前的狀態(tài)。

4. 劣勢

  • 對于相同的數(shù)據(jù)集來說,AOF 文件的體積通常要大于 RDB 文件的體積。
  • 根據(jù)所使用的 fsync 策略,AOF 的速度可能會慢于 RDB 。 在一般情況下, 每秒 fsync 的性能依然非常高, 而關閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負荷之下也是如此。 不過在處理巨大的寫入載入時,RDB 可以提供更有保證的***延遲時間。

總結

對于我們應該選擇RDB還是AOF,取決于具體的應用場景,官方的建議是兩個同時使用。這樣可以提供更可靠的持久化方案。其實RDB和AOF兩種方式也可以同時使用,在這種情況下,如果redis重啟的話,則會優(yōu)先采用AOF方式來進行數(shù)據(jù)恢復,這是因為AOF方式的數(shù)據(jù)恢復完整度更高。

如果你沒有數(shù)據(jù)持久化的需求,也完全可以關閉RDB和AOF方式,這樣的話,redis將變成一個純內存數(shù)據(jù)庫,就像memcache一樣。

責任編輯:趙寧寧 來源: 今日頭條
相關推薦

2024-09-06 17:49:46

2020-01-06 14:54:31

RDBAOFRedis

2023-05-11 09:12:35

RedisRDB日志

2024-09-12 08:49:53

2021-07-18 07:59:42

RedisRDBAOF

2021-03-10 00:02:01

Redis

2024-03-26 00:03:08

Redis數(shù)據(jù)RDB

2024-09-29 09:25:53

2021-10-18 07:43:30

RedisAOF日志RDB快照

2023-03-13 08:08:48

數(shù)據(jù)庫Redis

2021-02-04 08:01:35

RedisRDBAOF

2020-12-11 11:40:37

RDBAOFRedis

2023-09-12 10:49:44

Redis數(shù)據(jù)庫

2025-01-22 10:16:46

RedisRDBAOF

2024-12-20 12:15:06

RedisRDB持久化

2019-11-12 14:15:07

Redis內存持久化

2021-05-28 10:25:39

Redis數(shù)據(jù)庫內存

2021-12-12 10:29:41

AOFRedisAOF日志

2025-01-16 14:03:35

Redis

2019-11-18 16:20:48

RedisRDB數(shù)據(jù)庫
點贊
收藏

51CTO技術棧公眾號