1. 程式人生 > >分散式快取Redis的持久化方式RDB和AOF

分散式快取Redis的持久化方式RDB和AOF

一、前言

  Redis支援兩種方式的持久化,RDB和AOF。RDB會根據指定的規則“定時”將記憶體中的資料儲存到硬碟上,AOF會在每次執行命令後將命令本身記錄下來。兩種持久化方式可以單獨使用其中一種,但更多情況下是兩種結合使用。

二、RDB

  RDB方式的持久化是通過快照完成的,當符合一定條件的時候Redis會自動將記憶體中的所有資料生成一份副本並存儲在硬碟上,這個過程即為“快照”。Redis會在以下四種情況下對資料進行快照:

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

  1.根據配置規則進行自動快照

  Redis允許使用者自定義快照條件,當符合快照條件的時候,Redis會自動進行快照操作。進行快照的條件可以由使用者的配置檔案中自定義,有兩個引數構成:時間視窗M和改動的鍵的個數N。每當時間M內被更改的鍵的個數大於N時,即符合自動快照的條件。例如Redis的安裝目錄中包含的樣例配置檔案中預置的3個條件:

 

   每條快照條件佔一行,並且以save引數開頭。同時可以存在多個條件,條件之間是or的關係。就這個例子來說,save 900 1 的意思是在十五分鐘內(900秒)內有一個或者以上的鍵被更改則進行快照。同理,save 300 10 表示在300秒內至少有十個鍵被修改則進行快照。

  2.使用者指定save或bgsave命令

  除了讓Redis自動進行快照外,當進行服務重啟、手動遷移以及備份時我們也會需要手動執行快照操作。Redis提供了兩個命令:

  save:當執行save命令的時候,Redis同步地進行快照操作,在快照執行地過程中阻塞所有來自客戶端的請求。當資料庫中的資料比較多的時候,這一過程會導致Redis較長時間不能響應,所以要儘量避免在生產環境使用。

127.0.0.1:6379> save
OK

  bgsave:需要手動執行快照時推薦使用bgsave命令。bgsave命令可以在後臺非同步地進行快照操作,快照地同時伺服器還可以繼續響應來自客戶端的請求。執行bgsave後Redis會立即返回Background saving started表示開始執行快照操作。如果想知道快照是否完成,可以通過lastsave命令獲取最後一次成功執行快照地時間,返回一個unix時間戳,如:

127.0.0.1:6379> bgsave
Background saving started
127.0.0.1:6379> lastsave
(integer) 1580356962

  3.執行flushall命令

  當執行flushall命令時,Redis會清除資料庫中的所有資料。需要注意的是,不論清空資料庫的過程是否觸發了自動快照的條件,只要自動快照條件不為空,Redis就會執行一次快照操作。當沒有自定義的自動快照條件時,執行flushall則不會進行自動快照。

  4.執行復制

  當設定了主從模式,Redis會在複製初始化時進行自動快照。

  5.快照原理

  理清Redis實現快照的過程對我們瞭解快照檔案的特性有很大的幫助。Redis預設會將快照檔案儲存在Redis當前程序的工作目錄中的dump.rdb檔案中,可以通過配置dir和dbfilename兩個引數分別指定快照檔案的儲存路徑和檔名。快照過程如下:

  • Redis使用fork函式複製一份當前程序(父程序)的副本(子程序)。
  • 父程序繼續接收並處理客戶端發來的命令,而子程序開始將記憶體中的資料寫入硬碟中的臨時檔案。‘
  • 當子程序寫入完所有的資料後會用臨時檔案替換舊的RDB檔案,至此一次快照操作完成。

  通過上述過程可以發現Redis在進行快照的過程中不會修改RDB檔案,只有快照結束後才會將舊的檔案替換成新的,也就是說任何時候RDB檔案都是完整的。這使得我們可以通過定時備份RDB檔案來實現Redis資料庫的備份。RDB檔案經過壓縮的二進位制格式(可通過配置rdbcompression引數禁用壓縮節省cpu佔用),所以佔用的空間會小於記憶體中的資料大小,更加利於傳輸。

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

  通過RDB方式實現持久化,一旦Redis異常退出,就會丟失最後一次快照以後更改的所有資料。這就需要開發者根據實際情況,通過組合設定自動快照條件的方式來將可能發生的資料損失控制在能夠接受的範圍內。例如,使用Redis儲存快取資料時,丟失最近幾秒的資料或者丟失最近更新的幾十個鍵問題不大。要是資料十分重要,希望將損失降低到最小,就可以使用AOF方式進行持久化。

三、AOF方式

  當使用Redis儲存非臨時資料時,一般需要開啟AOF方式持久化來降低程序中止導致的資料丟失。AOF可以將Redis執行的每一條寫命令追加到硬碟檔案中,這一過程顯然會降低Redis的效能,但是大部分情況下是可以接受的,另外使用較快的硬碟可以提高AOF的效能。

  1.開啟AOF

  預設情況下Redis沒有開啟AOF方式的持久化,可以通過配置檔案的appendonly引數啟動,直接修改配置檔案可能沒有appendonly.aof檔案,需要通過下列語句啟動:

127.0.0.1:6379> config set appendonly yes
OK

   開啟AOF持久化後每執行一條更改Redis中的資料的命令,Redis就會將該命令寫入硬碟中的AOF檔案。AOF檔案的儲存位置和RDB檔案的位置相同,都是通過dir引數設定的,預設檔名是appendonly.aof,可以通過appendfilename引數修改。

   2.AOF的實現

  AOF檔案以純文字的形式記錄了Redis執行的寫命令,例如在開啟AOF持久化的情況下執行了如下幾個命令:

127.0.0.1:6379> set day 1
OK
127.0.0.1:6379> set day 2
OK
127.0.0.1:6379> get day
"2"

  appendonly.aof檔案內的資料如下:

*2
$6
SELECT
$1
0
*3
$3
SET
$3
day
$1
2

  從上可以看到AOF檔案的內容正是Redis客戶端向Redis傳送的原始通訊協議的內容。如果執行的Redis命令越多那這個檔案就越大,即使記憶體中實際的資料可能並沒有多少。所以我們可以通過設定配置檔案,來讓Redis在達到特定條件時自動重寫Redis檔案:

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

  auto-aof-rewirte-percentage引數的意義時當目前的AOF檔案大小超過上一次AOF重寫時的檔案大小的百分之多少時會再次進行重寫,如果之前沒有重寫過,則以啟動時的AOF檔案大小為依據。

  auto-aof-rewirte-min-size引數是限制允許重寫的AOF檔案最小的大小。

  在啟動Redis時會從AOF檔案中逐個執行命令,所以比RDB速度會慢。

  3.同步硬碟資料

  雖然每次執行更改Redis資料庫的命令時,AOF都會記錄在AOF檔案中,但是事實上,由於作業系統的快取機制,資料並沒有真正的寫入硬碟,而是進入了系統的硬碟快取。在預設情況下系統每30秒會執行一次同步操作,以便將硬碟快取中的內容真正寫入硬碟,所以在這之前系統異常會導致數丟失,所以我們需要在Redis的配置檔案中設定同步時機:

# appendfsync always
appendfsync everysec
# appendfsync no

  預設情況下Redis採用everysec規則,即每秒執行一次同步。always表示每次執行寫入都同步,這最安全卻也最慢。no表示不主動同步,由作業系統自動來做。

  Redis允許同時開啟AOF和RDB模式,同時啟動的情況下,Redis會採用AOF的資料來恢復,因為它可能丟失的資料最