Redis 持久化儲存詳解

奕鵬發表於2019-09-13

 為什麼要做持久化儲存?

持久化儲存是將 Redis 儲存在記憶體中的資料儲存在硬碟中,實現資料的永久儲存。我們都知道 Redis 是一個基於記憶體的 nosql 資料庫,記憶體儲存很容易造成資料的丟失,因為當伺服器關機等一些異常情況都會導致儲存在記憶體中的資料丟失。

 持久化儲存分類

在 Redis 中,持久化儲存分為兩種。一種是 aof 日誌追加的方式,另外一種是 rdb 資料快照的方式。

 RDB持久化儲存

什麼是RDB持久化儲存

RDB持久化儲存即是將redis存在記憶體中的資料以快照的形式儲存在本地磁碟中。
   
.RDB持久化儲存分為自動備份和手動備份

1.手動備份通過 save 命令和 bgsave 命令。save是同步阻塞,而 bgsave 是非阻塞(阻塞實際發生在 fork 的子程式中)。因此,在我們實際過程中大多是使用bgsave命令實現備份.


redis> SAVE

OK

redis> BGSAVE

Background saving started

2.自動備份

a.修改配置項 save m n即表示在 m 秒內執行了 n 次命令則進行備份.

b.當Redis 從伺服器項主伺服器傳送複製請求時,主伺服器則會使用 bgsave命令生成 rbd 檔案,然後傳輸給從伺服器.

c.當執行 debug reload 命令時也會使用 save 命令生成rdb檔案.

d.當使用 shutdown 命令關掉服務時,如果沒有啟用 aof方式實現持久化則會採用bgsave的方式做持久化.同時shutdown後面可以加備份引數[nosave|save].

bgsave持久化儲存實現原理

14

1.執行bgsave命令,Redis父程式判斷當前是否存在正在執行的子程式,如果存在則直接返回.

2.父程式fork一個子程式(fork的過程中會造成阻塞的情況),這個過程可以使用info stats命令檢視latest_fork_usec選項,檢視最近一次fork操作小號的時間,單位是微妙.

3.父程式fork完之後,則會返回Background saving started資訊提示,此時fork阻塞解除.

4.fork出的子程式開始根據父程式記憶體資料生成臨時的快照檔案,然後替換原檔案.使用lastsave命令可以檢視最後一次生成rdb的時間,對應info的rdb_last_save_time選項.

5.當備份完畢之後向父程式傳送完成資訊,具體可以見info Persistence下的rbd_*選項.

RDB持久化的優勢與劣勢

優勢:

1.檔案實現的資料快照,全量備份,便於資料的傳輸.比如我們需要把A伺服器上的備份檔案傳輸到B伺服器上面,直接將rdb檔案拷貝即可.

2.檔案採用壓縮的二進位制檔案,當重啟服務時載入資料檔案,比aof方式更快.

劣勢:

1.rbd採用加密的二進位制格式儲存檔案,由於Redis各個版本之間的相容性問題也導致rdb由版本相容問題導致無法再其他的Redis版本中使用.

2.時效性差,容易造成資料的不完整性.因為rdb並不是實時備份,當某個時間段Redis服務出現異常,記憶體資料丟失,這段時間的資料是無法恢復的,因此易導致資料的丟失.

RDB檔案常見的處理方式

1.當遇到磁碟寫滿情況,可以使用如下命令來切換儲存磁碟


// dirName則是新的儲存目錄名(該方式同樣適用於aof格式)

config set dir dirName

2.檔案壓縮處理,雖然對CPU具有消耗,但是減少體積的暫用,同時做檔案傳輸(主從複製)也減少消耗.


// 修改壓縮開啟或關閉

config set rdbcompression yes|no

3.rbd備份檔案損壞檢測.可以使用redis-check-rdb工具檢測rdb檔案,該工具預設在/usr/local/bin/目錄下面.


[root@syncd redis-data]# /usr/local/bin/redis-check-rdb ./6379-rdb.rdb 

[offset 0] Checking RDB file ./6379-rdb.rdb

[offset 26] AUX FIELD redis-ver = '5.0.3'

[offset 40] AUX FIELD redis-bits = '64'

[offset 52] AUX FIELD ctime = '1552061947'

[offset 67] AUX FIELD used-mem = '852984'

[offset 83] AUX FIELD aof-preamble = '0'

[offset 85] Selecting DB ID 0

[offset 105] Checksum OK

[offset 105] \o/ RDB looks OK! \o/

[info] 1 keys read

[info] 0 expires

[info] 0 already expired

 AOF持久化儲存

AOF持久化儲存是什麼

AOF持久化儲存便是以日誌的形式將redis儲存在aof_buf緩衝區中的資料寫入到磁碟中。簡而言之,就是記錄redis的操作日誌,將redis執行過的命令記錄下載,當我們需要資料恢復時,redis去重新執行一次日誌檔案中的命令.

 如何配置持久化儲存


// 將no改為yes,控制aof開啟與否

appendonly no

// 控制aof檔名稱,儲存的目錄便是dir配置項

appendfilename "appendonly.aof"

// 三種備份策略(三者只需要開啟以一個即可)

# appendfsync always // 命令寫入立即寫入磁碟

appendfsync everysec // 每秒實現檔案的同步,寫入磁碟

# appendfsync no // 隨機進行檔案的同步,同步操作則交給作業系統來負責,通常時間是最長30s

AOF持久化儲存實現原理

aof日誌追加方式實現持久化儲存,需要經歷如下四個過程.命令寫入->檔案同步->檔案重寫->檔案過載

15

1.redis命令寫入,此時會將redis命令寫入aof_buf換從區.

2.緩衝區中資料根據備份策略實現寫入日誌檔案.

3.當aof的檔案越來越龐大,會根據我們的配置策略來實現aof的重寫,實現檔案的壓縮,減少體積.

4.當redis重新啟動時,在去重寫載入aof檔案,達到資料恢復的目的.

命令寫入

命令寫入主要是將檔案執行過的命令寫入到日誌檔案中.並且日誌檔案尊徐文字協議格式,下面示例程式碼便是aof日誌檔案中儲存的內容格式.


*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n

aof採用的是文字協議格式。主要是原因根據資料提示,可以能使由於如下原因.

1.文字協議的相容性好.前面我們提及到了rdb檔案是進行二進位制加密,可能不同版本之間會出現不相容的情況,採用文字協議可以加避免該問題。同時文字協議也可以減少跨平臺使用所帶來的諸多問題.

2.可讀性強.由於aof是將命令寫入檔案中,我們可以直接檢視命令內容,同時也可以修改日誌檔案內容.

3.開啟aof後,所有的檔案檔案都包含追加操作,直接採用文字協議,減少二次開銷(這一點,個人不是很理解.因為我們的aof是儲存的是命令,當我們再次去載入的時候,會去執行一次裡面的命令,當檔案大的時候應該是比較耗時的吧。如果沒有做好檔案重寫策略,大量重複無效的命令執行,對於二進位制加密的rdb格式,不需要再去轉換,這一點確實可以減少二次開銷).

檔案寫入

檔案寫入是將aof_buf緩衝區的命令寫入到檔案中.檔案寫入的策略有如下三種方式

|配置項 | 配置說明 |

|:---: | :---: |

|always | 命令寫入到aof_buf緩衝區中之後立即呼叫系統的<font color='red'>fsync操作同步到aof檔案中,fsync完成後執行緒返回. |

|everysec | 命令寫入到aof_buf緩衝區後<font color='red'>每隔一秒呼叫系統的<font color='red'>write操作,write完成後執行緒返回. |

|no | 命令寫入aof_bug緩衝區後呼叫系統write操作,不對aof檔案做fsync同步,同步硬碟操作由<font color='red'>系統操作完成,時間一般最長為30s. |

系統呼叫write和fsync說明:

·write操作會觸發延遲寫( delayed write) 機制。 Linux在核心提供頁緩衝區用來提高硬碟IO效能。 write操作在寫入系統緩衝區後直接返回。 同步硬碟操作依賴於系統排程機制, 例如: 緩衝區頁空間寫滿或達到特定時間週期。 同步檔案之前, 如果此時系統故障當機, 緩衝區內資料將丟失.

·fsync針對單個檔案操作( 比如AOF檔案) , 做強制硬碟同步, fsync將阻塞直到寫入硬碟完成後返回, 保證了資料持久化.

檔案寫入策略分析

配置為always時, 每次寫入都要同步AOF檔案, 在一般的SATA硬碟上, Redis只能支援大約幾百TPS寫入, 顯然跟Redis高效能特性背道而馳,

不建議配置.

配置為no。由於作業系統每次同步AOF檔案的週期不可控, 而且會加大每次同步硬碟的資料量, 雖然提升了效能, 但資料安全性無法保證.

配置為everysec。是建議的同步策略, 也是預設配置, 做到兼顧效能和資料安全性。 理論上只有在系統突然當機的情況下丟失1秒的資料.

檔案過載

1.為什麼要檔案做檔案過載操作?

由於aof採用的是日誌追加,我們redis命令不斷的寫入,aof檔案的體積也也會不斷的增加.因此redis引入了aof重寫機制達到減小aof檔案體積.<font color="blue">aof檔案重寫是把redis程式內的資料轉換為寫命令同步到新的aof檔案的過程(這一點其實不是特別明白,檔案重寫不是針對aof檔案檔案做操作的嗎?為什麼這裡是將redis程式內的資料轉換為命令寫入檔案,這裡的程式內的資料不是太明白,還有待深入研究.個人理解的就是將舊的aof檔案內容根據重寫策略,進行優化生成新的aof檔案。).

2.檔案過載有什麼好處?

檔案過載主要優化的地方有如下三點。使用檔案過載既可以減少檔案的體積,同時去掉了一些無效的操作,可以加快檔案過載效率.

a.將一些在程式內無效的資料不在寫入新的檔案.如過期的鍵.

b.去掉一些無效的命令.如del key1.

c.簡化操作.如lpush list a,lpush list b.直接可以簡化為lpush list a b.

3.檔案過載由那些方式?

檔案過載有自動觸發機制和手動觸發機制.

手動觸發機制:直接使用bgrewriteaof命令即可.該命令在fork子程式的時候會發生阻塞.

自動觸發機制:

auto-aof-rewrite-min-size:aof重寫時檔案最小的體積,預設的是64M.

auto-aof-rewrite-percentage:代表當前AOF檔案空間( aof_current_size) 和上一次重寫後AOF檔案空間( aof_base_size) 的比值.


自動觸發時機=aof_current_size>auto-aof-rewrite-minsize&&( aof_current_size-aof_base_size) /aof_base_size>=auto-aof-rewritepercentage

其中aof_current_size和aof_base_size可以在info Persistence統計資訊中檢視.

4.檔案過載實現的原理是怎樣的?

16

1.執行重寫命令,判斷是否存在子程式。

如果已經有子程式在進行aof重寫,則會提示如下資訊.


ERR Background append only file rewriting already in progress

如果已經存在子程式在進行bgsave操作,重寫命令會延遲到bgsave命令完成之後進行,會返回如下資訊.


Background append only file rewriting scheduled

2.父程式會fork一個子程式,在fork子程式的過程中會造成阻塞.

3.fork子程式結束阻塞解除,進行其他新的命令操作.新的命令依舊根據檔案寫入策略同步資料,保證aof機制正確進行(圖中3.1).

4.子程式在進行寫的過程中,由於fork操作運用的是寫時複製技術,子程式只能共享fork操作時記憶體保留的資料,新的資料是無法操作的.父程式在這過程中仍然在響應其他的命令,於是Redis會使用aof重寫快取區來儲存這部分新的資料(圖中3.2).

5.子程式進行根據重寫規則將資料寫入到新的aof檔案中,並且每次寫入有大小限制,通過aof-rewrite-incremental-fsync配置項來控制,預設是32M,這樣可以見減少單次刷盤(I/O寫)造成硬碟阻塞.

6.子程式在完成重寫之後,會向父程式傳送資訊,父程式更新統計資訊.可參看info persistence下的aof_*相關統計。

7.父程式會把新寫入存在aof重寫緩衝區的資料寫入到aof檔案中(圖5.2).

8.將新的aof檔案替換掉舊的aof檔案.

<font color='blue'>在第3和4中,其實不是特別理解.不理解的是為什麼父程式在響應新的命令會寫入舊的aof檔案,還要aof重寫快取區.個人理解的是,父程式在進行新命令寫入處理的策略是,按照正常的備份策略寫入舊的aof的同時也把新的命令寫入重寫緩衝區,在第5.2中將這部分新的資料寫入到新的aof檔案中,這樣保證資料的完整性.

檔案過載

檔案過載就是將檔案重新加入到redis服務中.比如redis服務重啟用於資料恢復.redis的過載機制非常完善,具體流程如下.

16

AOF檔案常見的問題處理

1.檔案損壞

我們在載入損壞的檔案是可能提示如下資訊.


Bad file format reading the append only file: make a backup of your AOF file,then use ./redis-check-aof --fix <filename>

此時我們可以使用redis-check-aof --fix命令進行修復(記得對檔案做個備份).修復後使用diff-u進行資料對比,找出部分丟失的資料.

2.檔案載入不完整

這可能是資料在備份的時候,redis服務異常,導致備份不完整.可以使用redis的aof-load-truncated相容該異常

 AOF的優缺點

優點:

多種檔案寫入(fsync)策略.

資料實時儲存,資料完整性強.即使丟失某些資料,制定好策略最多也是一秒內的資料丟失.

可讀性強,由於使用的是文字協議格式來儲存的資料,可有直接檢視操作的命令,同時也可以手動改寫命令.

缺點:

檔案體積過大,載入速度比rbd慢.由於aof記錄的是redis操作的日誌,一些無效的,可簡化的操作也會被記錄下來,造成aof檔案過大.但該方式可以通過檔案重寫策略進行優化.

選擇AOF還是RDB進行資料的持久化

1.針對不同的情況來選擇,建議使用兩種方式相結合.

2.針對資料安全性、完整性要求高的採用aof方式.

3.針對不太重要的資料可以使用rdb方式.

4.對於資料進行全量備份,便於資料備份的可以採用rdb方式.

相關文章