Redis持久化分析

                             什麼是 Redis 持久化?

通過閱讀這邊文章總結到的內容:

1、Redis有兩種羅盤方式。一種RDB(快照模式),一種AOF(追加模式)。

RDB模式:

RDB 功能最核心的是 rdbSave 和 rdbLoad 兩個函數, 前者用於生成 RDB 文件到磁盤, 而後者則用於將 RDB 文件中的數據重新載入到內存中,

可以手工執行Save/BgSave來進行快照模式,Save和BgSave都會調用rdbSave方法,Save模式是阻塞模式,阻塞所有請求BGSave 則是fork出一個子進程,子進程負責調用rdbSave,處理完成之後通知主進程,所以在BgSave期間可以繼續處理客戶端請求。自動觸發的配置一般爲多少秒內達到多少操作執行(rdb  save 900  1 #在900s內至少達到一條寫命令)。

Rdb的模式分三步  1)是生成一個新的.rdb文件,開始寫入數據 2)完成數據寫入,用臨時文件代替正式rdb 3)刪除舊文件

優點:1)恢復比AOF模式快 2) 文件非常緊湊適合備份 3)異步處理對Redis影響較小

缺點:1) 自動觸發RDB持久化,如果時間太短,容易造成頻繁寫入,影響服務器性能。如果時間太長會造成數據丟失。2)BgSave的數據量太大時,Forks的過程也會發生阻塞,另外Forks進程會耗費內存。

AOF模式:

AOF核心:AOF的持久化模式會記錄客戶端對服務端的每一次寫操作的命令,並將這些寫操作以Redis協議追加保存到後綴AOF的文件末尾。重啓的時候會加載運行AOF文件的命令進行數據恢復。

異步寫入的選項:

#appendfsync always  每次操作都寫入,對IO消耗較多

# appendfsync everysec   每秒一次,最多存在一秒的丟失。每次的命令都會存入到Reids的寫入緩衝區中。

# appendfsync no   交由操作系統處理什麼時候寫入,更快,但是不安全,不推薦使用。

# no-appendfsync-on-rewrite no    默認不重寫aof文件,每次fsync都重寫,太消耗IO,不推薦使用。

優點:1)只是追加日誌文件,對服務器影響性能很小,速度比RDB快,消耗內存少。

缺點:1)AOF生成的日誌文件太大,即使重寫,AOF的文件也很大,恢復比較慢。

 

 

Redis 作爲一個鍵值對內存數據庫(NoSQL),數據都存儲在內存當中,在處理客戶端請求時,所有操作都在內存當中進行,如下所示:

 

10分鐘徹底理解Redis持久化和主從複製

 

 

這樣做有什麼問題呢?其實,只要稍微有點計算機基礎知識的人都知道,存儲在內存當中的數據,只要服務器關機(各種原因引起的),內存中的數據就會消失了。

不僅服務器關機會造成數據消失,Redis 服務器守護進程退出,內存中的數據也一樣會消失。

 

10分鐘徹底理解Redis持久化和主從複製

 

 

對於只把 Redis 當緩存來用的項目來說,數據消失或許問題不大,重新從數據源把數據加載進來就可以了。

但如果直接把用戶提交的業務數據存儲在 Redis 當中,把 Redis 作爲數據庫來使用,在其放存儲重要業務數據,那麼 Redis 的內存數據丟失所造成的影響也許是毀滅性。

爲了避免內存中數據丟失,Redis 提供了對持久化的支持,我們可以選擇不同的方式將數據從內存中保存到硬盤當中,使數據可以持久化保存。

 

10分鐘徹底理解Redis持久化和主從複製

 

 

Redis 提供了 RDB 和 AOF 兩種不同的數據持久化方式,下面我們就來詳細介紹一下這種不同的持久化方式吧。

RDB

RDB 是一種快照存儲持久化方式,具體就是將 Redis 某一時刻的內存數據保存到硬盤的文件當中,默認保存的文件名爲 dump.rdb,而在 Redis 服務器啓動時,會重新加載 dump.rdb 文件的數據到內存當中恢復數據。

①開啓 RDB 持久化方式

開啓 RDB 持久化方式很簡單,客戶端可以通過向 Redis 服務器發送 Save 或 Bgsave 命令讓服務器生成 RDB 文件,或者通過服務器配置文件指定觸發 RDB 條件。

save 命令:是一個同步操作。

# 同步數據到磁盤上 
> save 

 

10分鐘徹底理解Redis持久化和主從複製

 

 

當客戶端向服務器發送 Save 命令請求進行持久化時,服務器會阻塞 Save 命令之後的其他客戶端的請求,直到數據同步完成。

如果數據量太大,同步數據會執行很久,而這期間 Redis 服務器也無法接收其他請求,所以,最好不要在生產環境使用 Save 命令。

Bgsave:與 Save 命令不同,Bgsave 命令是一個異步操作。

# 異步保存數據集到磁盤上 
> bgsave 

 

10分鐘徹底理解Redis持久化和主從複製

 

 

當客戶端發服務發出 Bgsave 命令時,Redis 服務器主進程會 Forks 一個子進程來數據同步問題,在將數據保存到 RDB 文件之後,子進程會退出。

所以,與 Save 命令相比,Redis 服務器在處理 Bgsave 採用子線程進行 IO 寫入。

而主進程仍然可以接收其他請求,但 Forks 子進程是同步的,所以 Forks 子進程時,一樣不能接收其他請求。

這意味着,如果 Forks 一個子進程花費的時間太久(一般是很快的),Bgsave 命令仍然有阻塞其他客戶的請求的情況發生。

服務器配置自動觸發:除了通過客戶端發送命令外,還有一種方式,就是在 Redis 配置文件中的 Save 指定到達觸發 RDB 持久化的條件,比如【多少秒內至少達到多少寫操作】就開啓 RDB 數據同步。

例如我們可以在配置文件 redis.conf 指定如下的選項:

# 900s內至少達到一條寫命令 
save 900 1 
# 300s內至少達至10條寫命令 
save 300 10 
# 60s內至少達到10000條寫命令 
save 60 10000 

之後在啓動服務器時加載配置文件。

# 啓動服務器加載配置文件 
redis-server redis.conf 

這種通過服務器配置文件觸發 RDB 的方式,與 Bgsave 命令類似,達到觸發條件時,會 Forks 一個子進程進行數據同步。

不過最好不要通過這方式來觸發 RDB 持久化,因爲設置觸發的時間太短,則容易頻繁寫入 RDB 文件,影響服務器性能,時間設置太長則會造成數據丟失。

②RDB 文件

前面介紹了三種讓服務器生成 RDB 文件的方式,無論是由主進程生成還是子進程來生成,其過程如下:

  • 生成臨時 RDB 文件,並寫入數據。
  • 完成數據寫入,用臨時文代替代正式 RDB 文件。
  • 刪除原來的 DB 文件。

RDB 默認生成的文件名爲 dump.rdb,當然,我可以通過配置文件進行更加詳細配置。

比如在單機下啓動多個 Redis 服務器進程時,可以通過端口號配置不同的 RDB 名稱,如下所示:

# 是否壓縮rdb文件 
rdbcompression yes 
 
# rdb文件的名稱 
dbfilename redis-6379.rdb 
 
# rdb文件保存目錄 
dir ~/redis/ 

RDB的幾個優點:

  • 與 AOF 方式相比,通過 RDB 文件恢復數據比較快。
  • RDB 文件非常緊湊,適合於數據備份。
  • 通過 RDB 進行數據備份,由於使用子進程生成,所以對 Redis 服務器性能影響較小。

RDB 的幾個缺點:

  • 如果服務器宕機的話,採用 RDB 的方式會造成某個時段內數據的丟失,比如我們設置 10 分鐘同步一次或 5 分鐘達到 1000 次寫入就同步一次,那麼如果還沒達到觸發條件服務器就死機了,那麼這個時間段的數據會丟失。
  • 使用 Save 命令會造成服務器阻塞,直接數據同步完成才能接收後續請求。
  • 使用 Bgsave 命令在 Forks 子進程時,如果數據量太大,Forks 的過程也會發生阻塞,另外,Forks 子進程會耗費內存。

AOF

聊完了 RDB,來聊聊 Redis 的另外一個持久化方式:AOF(Append-only file)。

與 RDB 存儲某個時刻的快照不同,AOF 持久化方式會記錄客戶端對服務器的每一次寫操作命令,並將這些寫操作以 Redis 協議追加保存到以後綴爲 AOF 文件末尾。

在 Redis 服務器重啓時,會加載並運行 AOF 文件的命令,以達到恢復數據的目的。

 

10分鐘徹底理解Redis持久化和主從複製

 

 

①開啓 AOF 持久化方式

Redis 默認不開啓 AOF 持久化方式,我們可以在配置文件中開啓並進行更加詳細的配置,如下面的 redis.conf 文件:

# 開啓aof機制 
appendonly yes 
 
# aof文件名 
appendfilename "appendonly.aof" 
 
# 寫入策略,always表示每個寫操作都保存到aof文件中,也可以是everysec或no 
appendfsync always 
 
# 默認不重寫aof文件 
no-appendfsync-on-rewrite no 
 
# 保存目錄 
dir ~/redis/ 

②三種寫入策略

在上面的配置文件中,我們可以通過 appendfsync 選項指定寫入策略,有三個選項:

appendfsync always 
# appendfsync everysec 
# appendfsync no 

always:客戶端的每一個寫操作都保存到 AOF 文件當中,這種策略很安全,但是每個寫操作都有 IO 操作,所以也很慢。

everysec:appendfsync 的默認寫入策略,每秒寫入一次 AOF 文件,因此,最多可能會丟失 1s 的數據。

no:Redis 服務器不負責寫入 AOF,而是交由操作系統來處理什麼時候寫入 AOF 文件。更快,但也是最不安全的選擇,不推薦使用。

③AOF 文件重寫

AOF 將客戶端的每一個寫操作都追加到 AOF 文件末尾,比如對一個 Key 多次執行 Incr 命令,這時候,AOF 保存每一次命令到 AOF 文件中,AOF 文件會變得非常大。

incr num 1 
incr num 2 
incr num 3 
incr num 4 
incr num 5 
incr num 6 
... 
incr num 100000 

AOF 文件太大,加載 AOF 文件恢復數據時,就會非常慢,爲了解決這個問題,Redis 支持 AOF 文件重寫。

通過重寫 AOF,可以生成一個恢復當前數據的最少命令集,比如上面的例子中那麼多條命令,可以重寫爲:

set num 100000 

AOF 文件是一個二進制文件,並不是像上面的例子一樣,直接保存每個命令,而使用 Redis 自己的格式,上面只是方便演示。

兩種重寫方式:通過在 redis.conf 配置文件中的選項 no-appendfsync-on-rewrite 可以設置是否開啓重寫。

這種方式會在每次 Fsync 時都重寫,影響服務器性能,因此默認值爲 no,不推薦使用。

# 默認不重寫aof文件 
no-appendfsync-on-rewrite no 

客戶端向服務器發送 bgrewriteaof 命令,也可以讓服務器進行 AOF 重寫。

# 讓服務器異步重寫追加aof文件命令 
> bgrewriteaof 

AOF 重寫方式也是異步操作,即如果要寫入 AOF 文件,則 Redis 主進程會 Forks 一個子進程來處理,如下所示:

 

10分鐘徹底理解Redis持久化和主從複製

 

 

重寫 AOF 文件的好處:

  • 壓縮 AOF 文件,減少磁盤佔用量。
  • 將 AOF 的命令壓縮爲最小命令集,加快了數據恢復的速度。

③AOF 文件損壞

在寫入 AOF 日誌文件時,如果 Redis 服務器宕機,則 AOF 日誌文件文件會出格式錯誤。

在重啓 Redis 服務器時,Redis 服務器會拒絕載入這個 AOF 文件,可以通過以下步驟修復 AOF 並恢復數據:

  • 備份現在 AOF 文件,以防萬一。
  • 使用 redis-check-aof 命令修復 AOF 文件,該命令格式如下:
# 修復aof日誌文件 
$ redis-check-aof -fix file.aof 
  • 重啓 Redis 服務器,加載已經修復的 AOF 文件,恢復數據。

AOF 的優點:

  • AOF 只是追加日誌文件,因此對服務器性能影響較小,速度比 RDB 要快,消耗的內存較少。

AOF 的缺點:

  • AOF 方式生成的日誌文件太大,即使通過 AFO 重寫,文件體積仍然很大。
  • 恢復數據的速度比 RDB 慢。

選擇 RDB 還是 AOF 呢?

通過上面的介紹,我們瞭解了 RDB 與 AOF 各自的優點與缺點,到底要如何選擇呢?

通過下面的表示,我們可以從幾個方面對比一下 RDB 與 AOF,在應用時,要根據自己的實際需求,選擇 RDB 或者 AOF。

其實,如果想要數據足夠安全,可以兩種方式都開啓,但兩種持久化方式同時進行 IO 操作,會嚴重影響服務器性能,因此有時候不得不做出選擇。

 

10分鐘徹底理解Redis持久化和主從複製

 

 

當 RDB 與 AOF 兩種方式都開啓時,Redis 會優先使用 AOF 日誌來恢復數據,因爲 AOF 保存的文件比 RDB 文件更完整。

小結:上面講了一大堆 Redis 的持久化機制的知識,其實,如果你只是單純把 Redis 作爲緩存服務器,那麼可以完全不用考慮持久化。

但是,在如今的大多數服務器架構中,Redis 不單單只是扮演一個緩存服務器的角色,還可以作爲數據庫,保存我們的業務數據,此時,我們則需要好好了解有關 Redis 持久化策略的區別與選擇。

 

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