1. 程式人生 > >Redis系列之----Redis的兩種持久化機制(RDB和AOF)

Redis系列之----Redis的兩種持久化機制(RDB和AOF)

Redis的兩種持久化機制(RDB和AOF)

什麼是持久化

   Redis的資料是儲存在記憶體中的,記憶體中的資料隨著伺服器的重啟或者宕機便會不復存在,在生產環境,伺服器宕機更是屢見不鮮,所以,我們希望Redis能夠將資料從記憶體中以某種形式儲存到磁碟中,使得重啟的時候可以載入磁碟中的檔案記錄恢復資料,這一過程便是Redis的持久化。
   Redis支援兩種持久化機制,一種是RDB,另一種是AOF。Redis預設情況下使用RDB方式進行持久化。兩種持久化可以單獨使用其中的一種,也可以二者結合使用,下面便來分別介紹下這兩種持久化機制。

RDB方式

   RDB方式的持久化是通過快照(snapshotting)方式完成的,當符合一定條件的時候redis會自動將記憶體中的資料生成一份副本儲存在磁碟中,這個過程即為“快照”。

Redis會根據以下幾種情況對資料進行快照:

  • 根據配置規則自動進行快照
  • 使用者執行SAVE或者BGSAVE命令;
  • 執行FLUSHALL命令;
  • 執行復制時;

1)根據規則自定義快照條件

使用者可以自定義快照條件,當符合快照條件,Redis便會執行快照操作,在redis.conf配置檔案中,有這麼一段配置及說明:

It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save ""

save 900 1
save 300 10
save 60 10000

# By default Redis will stop accepting writes if RDB snapshots are enabled
# (at least one save point) and the latest background save failed.
# This will make the user aware (in a hard way) that data is not persisting
# on disk properly, otherwise chances are that no one will notice and some
# disaster will happen.

在save命令後面加上兩個數字,save <指定時間間隔> <執行指定次數更新操作>。例如:save 900 1 表示在900秒內有一個或者一個以上的鍵被更改時即執行快照操作。

2)執行SAVE或者BGSAVE命令

1、save命令
   執行save命令時redis會同步執行快照操作,這將會阻塞所有來自客戶端的請求,伺服器無法響應其他的處理,直到執行完成為止。如果資料量小,用此命令可能感覺不出有什麼區別,但是當資料量很大的時候,就需要謹慎使用這個命令。
2、bgasve命令
執行bgsave命令時,redis會fork出一個子程序去完成備份的操作,不會影響redis處理其他的請求。

3)執行FLUSHALL命令

   執行FLUSHALL命令時,Redis會清除資料庫中的所有資料,不論清空資料庫的過程是否觸發了自動快照條件,只要快照條件存在,就會執行快照操作,當沒有快照條件時,執行FLUSHALL不會進行快照。

4)執行復制時

當設定了主從模式時,Redis會在複製初始化時進行自動快照,即使沒有設定自動快照條件時,也會執行快照操作。

儲存路徑:
   Redis預設將快照檔案儲存在Redis當前程序的工作目錄中的dump.rdb檔案中,可以通過配置dir和dbfilename兩個引數分別制定快照文案件的儲存路徑和檔名。如redis.conf檔案中的配置和註釋:

# The filename where to dump the DB
dbfilename dump.rdb

# The working directory.
# DB將以dbfilename指定檔名被寫入這個目錄中,
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
# Note that you must specify a directory here, not a file name.
dir ./

執行快照的過程

  1. Redis使用fork函式複製一份當前程序(父程序)的副本(子程序);
  2. 父程序繼續接受來自客戶端的請求,子程序開始將記憶體中的資料寫入到硬碟中的臨時檔案;
  3. 當子程序寫入完之後會用該臨時檔案替換舊的rdb檔案。

   redis在執行快照的過程中不會修改RDB檔案,在快照結束後才會進行替換。因此RDB檔案通常也用來實現Redis的資料備份,並且RDB檔案是經過壓縮的二進位制格式,所以佔用空間比記憶體中的資料小。

   Redis啟動後會讀取RDB檔案,將資料從磁碟載入到記憶體,通常將一個記錄了1000萬字符串型別鍵、大小為1GB的快照檔案載入記憶體需要20~30秒,載入的時間根據不同的伺服器效能和Redis的資料結構而不同。

RDB 的優缺點
優點:
1 適合大規模的資料恢復。
2 如果業務對資料完整性和一致性要求不高,RDB是很好的選擇。

缺點:
1 資料的完整性和一致性不高,因為RDB可能在最後一次備份時宕機了。
2 備份時佔用記憶體,因為Redis 在備份時會獨立建立一個子程序,將資料寫入到一個臨時檔案(此時記憶體中的資料是原來的兩倍哦),最後再將臨時檔案替換之前的備份檔案。


AOF方式

   為了降低因為程序終止導致的資料丟失的風險,Redis還提供了AOF的方式來進行持久化,AOF可以將Redis執行的每一條命令追加到硬碟檔案中,這一過程會降低redis的效能,但從資料的安全性來說,這個影響是可以接受的。

AOF檔案的儲存地址和RDB檔案位置相同,都是通過dir引數設定,預設檔名為appendonly.aof。
如下所示:

appendonly no

# The name of the append only file (default: "appendonly.aof")

appendfilename "appendonly.aof"

預設情況下,Redis沒有開啟AOF的方式,可通過修改redis.conf配置檔案中的appendonly引數為yes進行啟動。

如果還沒有生成aof檔案的話,可以使用命令設定:

./redis-cli config set appendonly yes

aof檔案開啟是這樣的:

*2
$6
SELECT
$1
0
*3
$3
SET
$3
age
$2
28
*3
$3
SET
$2
cc
$2
vv

   AOF檔案以純文字的形式記錄了Redis的執行命令,AOF檔案中的內容是Redis客戶端向Redis傳送的原始通訊協議的內容,當對相同key進行多次賦值操作時,aof也會將這些命令記錄下來,但其實我們只希望它記錄最後一次的值,為此Redis在redis.conf檔案中提供了這樣的引數來自動重寫AOF檔案:

# 當目前的AOF檔案大小超過上一次重寫的AOF檔案大小的百分之多少進行重寫
auto-aof-rewrite-percentage 100
# 允許重寫的AOF的最小AOF檔案大小
auto-aof-rewrite-min-size 64mb

Redis在啟動的時候會逐條執行AOF檔案中的命令來將硬碟中的檔案寫入到記憶體中,因此載入的速度相對慢些。


# The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use "everysec".

# appendfsync always
appendfsync everysec
# appendfsync no

並且我們需要注意的是下面這段描述:

The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.

   雖然每次更改資料庫內容的操作時,redis都會把更新記錄在AOF檔案中,但是由於作業系統的快取機制,資料並沒有真正的寫入磁碟,而是進入了系統硬碟快取。在預設情況下會每30秒執行一次同步操作,如果在這30秒之內系統異常會導致硬碟快取中的資料丟失,我們使用AOF命令的方式就是為了儘可能的減少資料的丟失,所以redis提供了appendfsync引數來設定同步機制。預設情況下使用everysec,即每秒執行一次同步操作,將資料從快取更新到磁碟中。always表示每次執行寫入都會執行同步操作,這是最慢也是最安全的方式。no表示不主動執行,交由作業系統執行,這是最不安全的方式。一般情況下兼顧系統性能,使用everysec的方式即可。

優點:資料的完整性和一致性更高
缺點:因為AOF記錄的內容多,檔案會越來越大,資料恢復也會越來越慢。

   RDB和AOF可以同時存在,這樣既保證了資料安全又使得進行備份操作十分容易,Redis會使用AOF檔案來恢復資料,因為AOF的方式持久化丟失的資料會更少。

參考書籍:《Redis入門指南