Redis持久化

爲什麼要做持久化存儲?

持久化存儲是將 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 命令查看 latestfork_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 緩衝區中之後立即調用系統的fsync 操作同步到 aof 文件中,fsync 完成後線程返回.
everysec 命令寫入到 aof_buf 緩衝區後每隔一秒調用系統的write 操作,write 完成後線程返回.
no 命令寫入 aof_bug 緩衝區後調用系統 write 操作,不對 aof 文件做 fsync 同步,同步硬盤操作由系統操作完成,時間一般最長爲 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 文件體積.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 文件.
在第 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 方式.

本文轉自微信公衆號 深夜有話聊 發佈!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章