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

haoge0205發表於2019-08-14

在這篇文章,我們繼續有關Redis方面知識的學習,一起了解一下其中一個非常重要的內容:Redis的持久化機制。

什麼是Redis持久化?

Redis作為一個鍵值對記憶體資料庫(NoSQL),資料都儲存在記憶體當中,在處理客戶端請求時,所有操作都在記憶體當中進行,如下所示:

這樣做有什麼問題呢?

其實,只要稍微有點計算機基礎知識的人都知道,儲存在記憶體當中的資料,只要伺服器關機(各種原因引起的),記憶體中的資料就會消失了,不僅伺服器關機會造成資料消失,Redis伺服器守護程式退出,記憶體中的資料也一樣會消失。

對於只把Redis當快取來用的專案來說,資料消失或許問題不大,重新從資料來源把資料載入進來就可以了,但如果直接把使用者提交的業務資料儲存在Redis當中,把Redis作為資料庫來使用,在其放儲存重要業務資料,那麼Redis的記憶體資料丟失所造成的影響也許是毀滅性。為了避免記憶體中資料丟失,Redis提供了對持久化的支援,我們可以選擇不同的方式將資料從記憶體中儲存到硬碟當中,使資料可以持久化儲存。

 

 

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

RDB

RDB是一種快照儲存持久化方式,具體就是將Redis某一時刻的記憶體資料儲存到硬碟的檔案當中,預設儲存的檔名為dump.rdb,而在Redis伺服器啟動時,會重新載入dump.rdb檔案的資料到記憶體當中恢復資料。

開啟RDB持久化方式

開啟RDB持久化方式很簡單,客戶端可以透過向Redis伺服器傳送save或bgsave命令讓伺服器生成rdb檔案,或者透過伺服器配置檔案指定觸發RDB條件。

1. save命令

save命令是一個同步操作。

# 非同步儲存資料集到磁碟上> bgsave

當客戶端發服務發出bgsave命令時,Redis伺服器主程式會forks一個子程式來資料同步問題,在將資料儲存到rdb檔案之後,子程式會退出。

所以,與save命令相比,Redis伺服器在處理bgsave採用子執行緒進行IO寫入,而主程式仍然可以接收其他請求,但forks子程式是同步的,所以forks子程式時,一樣不能接收其他請求,這意味著,如果forks一個子程式花費的時間太久(一般是很快的),bgsave命令仍然有阻塞其他客戶的請求的情況發生。

3. 伺服器配置自動觸發

除了透過客戶端傳送命令外,還有一種方式,就是在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檔案的方式,無論是由主程式生成還是子程式來生成,其過程如下:

  1. 生成臨時rdb檔案,並寫入資料。

  2. 完成資料寫入,用臨時文代替代正式rdb檔案。

  3. 刪除原來的db檔案。

RDB預設生成的檔名為dump.rdb,當然,我可以透過配置檔案進行更加詳細配置,比如在單機下啟動多個redis伺服器程式時,可以透過埠號配置不同的rdb名稱,如下所示:

# 是否壓縮rdb檔案
rdbcompression yes
# rdb檔案的名稱
dbfilename redis-6379.rdb
# rdb檔案儲存目錄
dir ~/redis/

RDB的幾個優點

  1. 與AOF方式相比,透過rdb檔案恢復資料比較快。

  2. rdb檔案非常緊湊,適合於資料備份。

  3. 透過RDB進行資料備,由於使用子程式生成,所以對Redis伺服器效能影響較小。

RDB的幾個缺點

  1. 如果伺服器當機的話,採用RDB的方式會造成某個時段內資料的丟失,比如我們設定10分鐘同步一次或5分鐘達到1000次寫入就同步一次,那麼如果還沒達到觸發條件伺服器就當機了,那麼這個時間段的資料會丟失。

  2. 使用save命令會造成伺服器阻塞,直接資料同步完成才能接收後續請求。

  3. 使用bgsave命令在forks子程式時,如果資料量太大,forks的過程也會發生阻塞,另外,forks子程式會耗費記憶體。

AOF

聊完了RDB,來聊聊Redis的另外一個持久化方式:AOF(Append-only file)。
與RDB儲存某個時刻的快照不同,AOF持久化方式會記錄客戶端對伺服器的每一次寫操作命令,並將這些寫操作以Redis協議追加儲存到以字尾為aof檔案末尾,在Redis伺服器重啟時,會載入並執行aof檔案的命令,以達到恢復資料的目的。

開啟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

1. always

客戶端的每一個寫操作都儲存到aof檔案當,這種策略很安全,但是每個寫請注都有IO操作,所以也很慢。

2. everysec

appendfsync的預設寫入策略,每秒寫入一次aof檔案,因此,最多可能會丟失1s的資料。

3. no

Redis伺服器不負責寫入aof,而是交由作業系統來處理什麼時候寫入aof檔案。更快,但也是最不安全的選擇,不推薦使用。

AOF檔案重寫

AOF將客戶端的每一個寫操作都追加到aof檔案末尾,比如對一個key多次執行incr命令,這時候,aof儲存每一次命令到aof檔案中,aof檔案會變得非常大。

incr num 1incr num 2incr num 3incr num 4incr num 5incr 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檔案的好處

  1. 壓縮aof檔案,減少磁碟佔用量。

  2. 將aof的命令壓縮為最小命令集,加快了資料恢復的速度。

AOF檔案損壞

在寫入aof日誌檔案時,如果Redis伺服器當機,則aof日誌檔案檔案會出格式錯誤,在重啟Redis伺服器時,Redis伺服器會拒絕載入這個aof檔案,可以透過以下步驟修復aof並恢復資料。

  1. 備份現在aof檔案,以防萬一。

  2. 使用redis-check-aof命令修復aof檔案,該命令格式如下:

# 修復aof日誌檔案
$ redis-check-aof -fix file.aof
  1. 重啟Redis伺服器,載入已經修復的aof檔案,恢復資料。

AOF的優點

AOF只是追加日誌檔案,因此對伺服器效能影響較小,速度比RDB要快,消耗的記憶體較少。

AOF的缺點

  1. AOF方式生成的日誌檔案太大,即使透過AFO重寫,檔案體積仍然很大。

  2. 恢復資料的速度比RDB慢。

選擇RDB還是AOF呢?

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

透過下面的表示,我們可以從幾個方面對比一下RDB與AOF,在應用時,要根本自己的實際需求,選擇RDB或者AOF,其實,如果想要資料足夠安全,可以兩種方式都開啟,但兩種持久化方式同時進行IO操作,會嚴重影響伺服器效能,因此有時候不得不做出選擇。

當RDB與AOF兩種方式都開啟時,Redis會優先使用AOF日誌來恢復資料,因為AOF儲存的檔案比RDB檔案更完整。

小結

上面講了一大堆Redis的持久化機制的知識,其實,如果你只是單純把Redis作為快取伺服器,那麼可以完全不用考慮持久化,但是,在如今的大多數伺服器架構中,Redis的單單只是扮演一個快取伺服器的角色,還可以作為資料庫,儲存我們的業務資料,此時,我們則需要好好了解有關Redis持久化策略的區別與選擇。

轉自:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28939273/viewspace-2653635/,如需轉載,請註明出處,否則將追究法律責任。

相關文章