Redis持久化存儲詳解(一)

爲何要作持久化存儲?

持久化存儲是將 Redis 存儲在內存中的數據存儲在硬盤中,實現數據的永久保存。咱們都知道 Redis 是一個基於內存的 nosql 數據庫,內存存儲很容易形成數據的丟失,由於當服務器關機等一些異常狀況都會致使存儲在內存中的數據丟失。php

持久化存儲分類

在 Redis 中,持久化存儲分爲兩種。一種是 aof 日誌追加的方式,另一種是 rdb 數據快照的方式。redis

RDB持久化存儲
什麼是RDB持久化存儲

RDB持久化存儲便是將redis存在內存中的數據以快照的形式保存在本地磁盤中。sql

.RDB持久化存儲分爲自動備份和手動備份

1.手動備份經過 save 命令和 bgsave 命令。save是同步阻塞,而 bgsave 是非阻塞(阻塞實際發生在 fork 的子進程中)。所以,在咱們實際過程當中大可能是使用bgsave命令實現備份.shell

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持久化存儲實現原理

圖片描述
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日誌追加方式實現持久化存儲,須要經歷以下四個過程.命令寫入->文件同步->文件重寫->文件重載
圖片描述
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操做</font>同步到aof文件中,fsync完成後線程返回.
everysec 命令寫入到aof_buf緩衝區後<font color='red'>每隔一秒</font>調用系統的<font color='red'>write操做</font>,write完成後線程返回.
no 命令寫入aof_bug緩衝區後調用系統write操做,不對aof文件作fsync同步,同步硬盤操做由<font color='red'>系統操做</font>完成,時間通常最長爲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文件。).</font>
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.文件重載實現的原理是怎樣的?
圖片描述
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文件中,這樣保證數據的完整性.</font>

文件重載

文件重載就是將文件從新加入到redis服務中.好比redis服務重啓用於數據恢復.redis的重載機制很是完善,具體流程以下.圖片描述

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方式.原文轉自微信公衆號:浪子編程走四方

相關文章
相關標籤/搜索