Redis持久化:Redis宕機或者出現意外刪庫導致數據丟失--解決方案

Redis持久化的方案其實是很多人接觸的比較少的,因為相對應的數據故障不會很多,一次初始化的設置就能保證後續故障的全部順利解決。本文講述一下該機制的主要設置方法和持久化方案的對比,同時也會講述一些持久化的原理。如果對於Redis持久化比較熟悉的希望能夠給到你幫助,如果不熟悉的,你大可參考本文對你的Redis進行設置。

什麼是Redis的持久化?

可能很多人很少接觸這個詞,總覺的我們Redis的所有數據都是全部能夠永久存儲的。然而你可能不知道的是,Redis的數據都是在內存當中的,如果沒有持久化策略,你關閉Redis或者之後,你的數據有可能全部都丟失了。我們每再一次登錄Redis訪問上一次數據的時候,我們都看到了原來的數據,就是得益於Redis的持久化。Redis的持久化簡單說就是,將Redis存在內存中的值存儲到可以永久存儲的地方(磁盤等)

Redis的持久化方案

  • RDB Redis DataBase
  • AOF Append Only File

RDB [Redis DataBase]

RDB 是 Redis 默認的持久化方案。當滿足一定條件的時候,會把當前內存中的數據寫入磁盤,生成一個快照文件 dump.rdb。Redis 重啟會通過加載 dump.rdb 文件恢復數據。dump.rdb是我們redis文件當中的一個,位置如下圖:

Redis持久化:Redis宕機或者出現意外刪庫導致數據丟失--解決方案

RDB是怎麼實現持久化的

RDB是按照規則來觸發持久化存儲的,在我們的redis.conf中我們可以看到如下的幾個配置:

save 900 1 # 900 秒內至少有一個 key 被修改(包括添加)
save 300 10 # 300 秒內至少有 10 個 key 被修改
save 60 10000 # 60 秒內至少有 10000 個 key 被修改
Redis持久化:Redis宕機或者出現意外刪庫導致數據丟失--解決方案

這幾個配置是不衝突的,只要滿足任意一個都會觸發。

  • RDB方式的優點
  • RDB 是一個緊湊的單一文件,很方便傳送到另一個遠端數據中心,非常適用於災難恢復。
  • 與AOF相比,在恢復大的數據集的時候,RDB 方式會更快一些。
  • RDB方式的缺點
  • RDB 方式數據沒辦法做到實時持久化/秒級持久化。因為 bgsave 每次運行都要
    執行 fork 操作創建子進程,頻繁執行成本過高。
  • 在一定間隔時間做一次備份,所以如果 redis 意外 down 掉的話,就會丟失最後
    一次快照之後的所有修改(數據有丟失)。如果數據相對來說比較重要,希望將損失降到最小,則可以使用 AOF 方式進行持久化。

RDB持久化的演示

如果我們都按照正常程序走的話,我們是很難看到沒有持久化,或者出現持久化問題的故障現場的。所以我們要學會持久化操作,或者只管看到持久化就需要手動觸發持久化問題。這裡主要演示兩種情況,一種是數據正常備份,一種是數據丟失,我們恢復備份數據。

注意

這兩個操作都算是危險操作,我們需要在操作之前進行一下設置一下Redis快照,Redis
提供了兩條命令:

  • save: 在生成快照的時候會阻塞當前 Redis 服務器, Redis 不能處理其他命令。如果
    內存中的數據比較多,會造成Redis長時間的阻塞。生產環境不建議使用這個命令。為了解決這個問題,Redis 提供了第二種方式。
  • bgsave:執行 bgsave 時,Redis 會在後臺異步進行快照操作,快照同時還可以響應客戶端請
    求。具體操作是 Redis 進程執行fork操作創建子進程(copy-on-write),RDB持久化過程由子進程負責,完成後自動結束。它不會記錄fork之後後續的命令。阻塞只發生在fork階段,一般時間很短。用 lastsave 命令可以查看最近一次成功生成快照的時間。

使用shutdown 持久化

我們先在Redis庫中設置如下幾個值

set k1 1
set k2 2

set k3 3
set k4 4
set k5 5

# 操作完成上面的步驟之後我們停止服務器,觸發RDB的自動保存save
shutdown

# 然後再次啟動Redis服務
redis-server redis.conf

# 啟動完成,查看我們那些剛剛保存的數據是否被持久化了
keys *

執行完上面的步驟之後,我們可以看到我們的數據都在,就說明我們的觸發備份是成功的。

使用flushall模擬數據丟失

該操作有一定的風險性,如果是演示練習按照操作來基本不會出現問題,但是生產上慎重操作。我們做該操作之前,一定要注意先備份RDB對應的持久化問題dump.rdb

# 先備份dump.rdb
cp dump.rdb dump.rdb.bak

# 備份完成之後我們確定備份成功在進行下一步操作---清空庫
flushall

# 清空之後我們停止服務器
shutdown


# 再次啟動服務器,查看之前存儲的kye
keys *

再次啟動查看的時候,我們發現我們的數據丟失了

Redis持久化:Redis宕機或者出現意外刪庫導致數據丟失--解決方案

恢復丟失的數據

# 停服務器
shutdown

# 刪除我們現有dump.rdb

rm -rf ./dump.rdb

# 刪除成功之後,將我們的備份的dump.rdb.bak重新命名成為dump.rdb
mv dump.rdb.bak dump.rdb

# 確定之後我們再次啟動redis服務
redis-server redis.conf

# 檢查我們之前丟失的數據是否存在
keys *

完成之後我們查看的數據就出現啦!

Redis持久化:Redis宕機或者出現意外刪庫導致數據丟失--解決方案

AOF [Append Only File]

AOF:Redis 默認不開啟。AOF採用日誌的形式來記錄每個寫操作,並追加到文件中。開啟後,執行更改 Redis 數據的命令時,就會把命令寫入到AOF文件中。Redis重啟時會根據日誌文件的內容把寫指令從前到後執行一次以完成數據的恢復工作。

該方式默認關閉,需要使用我們需要修改如下配置

數據都是實時持久化到磁盤嗎?

由於操作系統的緩存機制,AOF數據並沒有真正地寫入硬盤,而是進入了系統的硬盤緩存。什麼時候把緩衝區的內容寫入到 AOF 文件?

AOF的保存規則有三種

Redis持久化:Redis宕機或者出現意外刪庫導致數據丟失--解決方案

AOF 持久化策略(硬盤緩存到磁盤),默認 everysec

  • no 表示不執行 fsync,由操作系統保證數據同步到磁盤,速度最快,但是不太安全;
  • always 表示每次寫入都執行 fsync,以保證數據同步到磁盤,效率很低;
  • everysec 表示每秒執行一次 fsync,可能會導致丟失這 1s 數據。通常選擇 everysec ,
    兼顧安全性和效率。

文件越來越大,怎麼辦?

由於 AOF 持久化是 Redis 不斷將寫命令記錄到 AOF 文件中,隨著 Redis 不斷的進行,AOF 的文件會越來越大,文件越大,佔用服務器內存越大以及 AOF恢復要求時間越長。
可以使用命令 bgrewriteaof來重寫。AOF文件重寫並不是對原文件進行重新整理,而是直接讀取服務器現有的鍵值對,然後用一條命令去代替之前記錄這個鍵值對的多條命令,生成一個新的文件後去替換原來的 AOF 文件。

AOF指定大小開始重寫

Redis持久化:Redis宕機或者出現意外刪庫導致數據丟失--解決方案

  • auto-aof-rewrite-percentage:默認值為100。aof自動重寫配置,當目前aof文件大小超過上一次重寫的aof文件大小的百分之多少進行重寫,即當aof文件增長到一定大小的時候,Redis能夠調用bgrewriteaof對日誌文件進行重寫。當前AOF文件大小是上次日誌重寫得到AOF文件大小的二倍(設置為100)時,自動啟動新的日誌重寫過程。
  • auto-aof-rewrite-min-size:默認64M。設置允許重寫的最小aof文件大小,避免了達到約定百分比但尺寸仍然很小的情況還要重寫。
  • AOF方式的優點
  • AOF 持久化的方法提供了多種的同步頻率,即使使用默認的同步頻率每秒同步一次,Redis最多也就丟失 1 秒的數據而已。
  • AOF方式的缺點
  • 對於具有相同數據的的Redis,AOF文件通常會比RDF文件體積更大(RDB存的是數據快照)。
  • 雖然 AOF 提供了多種同步的頻率,默認情況下,每秒同步一次的頻率也具有較高的性能。在高併發的情況下,RDB 比 AOF 具好更好的性能保證。

兩種方案比較

那麼對於AOF和RDB兩種持久化方式,我們應該如何選擇呢?
如果可以忍受一小段時間內數據的丟失,毫無疑問使用 RDB 是最好的,定時生成RDB 快照(snapshot)非常便於進行數據庫備份, 並且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快。否則就使用AOF重寫。但是一般情況下建議不要單獨使用某一種持久化機制,而是應該兩種一起用,在這種情況下,當 redis 重啟的時候會優先載入 AOF文件來恢復原始
的數據,因為在通常情況下 AOF 文件保存的數據集要比 RDB 文件保存的數據集要完整。


分享到:


相關文章: