天天看點

Redis 持久化(RDB和AOF模式)Redis持久化

Redis持久化

有兩種持久化方式:

  • RDB (Redis DB;預設開啟;類比于 HDFS 的 fsimage)
  • AOF (Append Only File;類比于 HDFS 的 edits log)

1. RDB

在預設情況下,Redis 将資料庫快照儲存在名字為 dump.rdb 的二進制檔案中。

1.1 持久化政策

  • 自動執行:

    按照配置檔案中的條件滿足就執行 BGSAVE

    • 預設配置

      save 900 1

      save 300 10

      save 60 10000

      隻要上面三個條件滿足一個,就自動執行備份。

      建立RDB檔案之後,時間計數器和次數計數器會清零。是以多個條件的效果不是疊加的

    • 持久化檔案預設目錄

      dir /var/lib/redis/6379

  • 手動執行:

    用戶端發起 SAVE、BGSAVE 指令。

1.2 具體方式

  • save(阻塞)
  • bgsave(非阻塞)

(1)SAVE

阻塞 Redis 服務,無法響應用戶端請求,建立新的 dump.rdb 替代舊檔案;生産環境很少這樣做,一般都是停機維護時期才考慮

Redis 持久化(RDB和AOF模式)Redis持久化

(2)BGSAVE

非阻塞,Redis 服務正常接收處理用戶端請求,Redis 會 fork()一個新的子程序來建立 RDB 檔案,子程序處理完後會向父程序發送一個信号,通知它處理完畢,父程序用新的 dump.rdb 替代舊檔案。BGSAVE 是一個異步指令。

Redis 持久化(RDB和AOF模式)Redis持久化
Redis 持久化(RDB和AOF模式)Redis持久化

1.3 RDB的工作流程:

(1)執行bgsave指令,Redis父程序判斷目前是否存在正在執行的子程序,如RDB/AOF子程序,如果存在bgsave指令直接傳回。

(2)父程序執行fork操作建立子程序(拷貝父程序所有資料的引用),fork操作過程中父程序被阻塞。

(3)父程序fork完成後,bgsave指令傳回“* Background saving started by pid xxx”資訊,并不再阻塞父程序,可以繼續響應其他指令。

(4)父程序建立新的RDB檔案,根據父程序記憶體生成臨時快照檔案,完成後對原有檔案進行原子替換。根據lastsave指令可以擷取最近一次生成RDB的時間,對應info Persistence中的rdb_last_save_time。

(5)子程序完成持久化操作後,通知父程序完成,父程序更新統計資訊。

對于大多數作業系統來說,fork都是個重量級操作,雖然建立的子程序不需要拷貝父程序的實體記憶體空間,但是會複制父程序的空間記憶體頁表。子程序通過fork操作産生,占用記憶體大小等同于父程序,理論上需要兩倍的記憶體來完成持久化操作。

但Linux有寫時複制機制(copy-on-write),子程序拷貝父程序所有資料的引用而不是複制資料本身,如果在 bgsave 過程中用戶端修改了父程序的記憶體,比如發生了寫操作,那麼父程序将開辟一個新的空間來存儲修改的這個資料。

1.4 配置

[[email protected] redis]# vi /etc/redis/6379.conf 
#預設情況下 redis 不是作為守護程序運作的,設定為 yes 讓它在背景運作 
daemonize yes 
#端口号 
port 6379 
#日志級别 
loglevel notice 
#日志位置 
logfile /var/log/redis_6379.log 
#一個 redis 執行個體最多可以包含多少個資料庫 
databases 16 
# Save the DB on disk: 
save 900 1 
save 300 10 
save 60 10000 
# The filename where to dump the DB 
dbfilename dump.rdb 
# The DB will be written inside this directory, with the filename specified 
# above using the 'dbfilename' configuration directive. 
dir /var/lib/redis/6379 
#如果啟動多個 redis,最好指定每個占用的記憶體 
# maxmemory <bytes> 
           

1.5 RDB持久化優缺點

優點:

  • 完全備份,不同時間的資料集備份可以做到多版本恢複
  • 緊湊的單一檔案,友善網絡傳輸,适合災難恢複
  • 恢複大資料集速度較AOF快

缺點:

  • 會丢失最近寫入、修改的而未能持久化的資料
  • fork過程比較耗時,會造成毫秒級不能響應用戶端請求

1.6 生産環境操作

由于RDB模式備份不會保留舊版本,每次都會覆寫,是以,在實際運用中需要将備份檔案定時拷貝至其他目錄,大緻操作如下:

(1)建立一個定時任務cron job,每小時或者每天将 dump.rdb 複制到指定目錄確定備份檔案名稱帶有日期資訊,便于管理和還原對應的時間點的快照版本。

(2)定時任務删除過期的備份

(3)如果有必要,跨實體主機、跨機架、異地備份

2. AOF

Append only file,采用追加的方式儲存,預設檔案 appendonly.aof,記錄所有的寫操作指令,在服務啟動的時候使用這些指令就可以還原資料庫。調整 AOF 持久化政策,可以在 服務出現故障時,不丢失任何資料,也可以丢失一秒的資料。相對于 RDB 損失小得多。

Redis 持久化(RDB和AOF模式)Redis持久化
Redis 持久化(RDB和AOF模式)Redis持久化
Redis 持久化(RDB和AOF模式)Redis持久化

2.1 AOF 寫入機制

AOF 方式不能保證絕對不丢失資料,目前常見的作業系統中,執行系統調用 write 函數,将一些内容寫入到某個檔案裡面時,為了提高效率,系統通常不會直接将内容寫入硬碟裡 面,而是先将内容放入一個記憶體緩沖區(buffer)裡面,等到緩沖區被填滿,或者使用者執行 fsync 調用和 fdatasync 調用時才将儲存在緩沖區裡的内容真正的寫入到硬碟裡,未寫入磁盤之前,資料可能會丢失 。

2.2 寫入磁盤的政策*

appendfsync 選項: append file synchronize 這個選項的值可以是 always、everysec 或者 no 。

  • always: 伺服器每寫入一個指令,就調用一次 fdatasync,将緩沖區裡面的指令寫入到硬 盤。這種模式下,伺服器出現故障,也不會丢失任何已經成功執行的指令資料 。
  • everysec(預設): 伺服器每一秒重調用一次 fdatasync,将緩沖區裡面的指令寫入到硬 盤。這種模式下,伺服器出現故障,最多隻丢失一秒鐘内的執行的指令資料(緩沖區的量) 。
  • no: 伺服器不主動調用 fdatasync,由作業系統決定何時将緩沖區裡面的指令寫入到硬碟。 這種模式下,伺服器遭遇意外停機時,丢失指令的數量是不确定的 。

運作速度: always 的速度慢,everysec 和 no 都很快。

2.3 AOF 重寫機制

  • AOF 檔案過大
  • 合并重複的操作,AOF 會使用盡可能少的指令來記錄
    Redis 持久化(RDB和AOF模式)Redis持久化

2.3.1 AOF重寫觸發

一旦使用AOF,RDB持久化方式即使開啟也将不采納,恢複的時候也是使用AOF檔案恢複。

  • 手動: 用戶端向伺服器發送 BGREWRITEAOF 指令
  • 自動: 配置檔案中的選項,以自動執行 BGREWRITEAOF 指令
    • auto-aof-rewrite-min-size <size> :

      觸發 AOF 重寫所需的最小體積(預設64MB),隻要在 AOF 檔案的 體積大于等于 size 時,才會考慮是否需要進行 AOF 重寫,這個選項用于避免對體積過小的 AOF 檔案進行重寫,但随着精簡後檔案的增長,很可能會超過64MB,此時會陷入無限精簡中,是以還行配置下面的參數。

    • auto-aof-rewrite-percentage <percent>:

      指定觸發重寫所需的 AOF 檔案體積百分比(避免重寫陷入死循環),當 AOF 檔案的體積大于 auto-aof-rewrite-min-size 指定的體積,并且超過上一次重寫之後的 AOF 檔案體積的 percent %時,就會觸發 AOF 重寫。(如果伺服器剛剛啟動不久,還沒有進 行過 AOF 重寫,那麼使用伺服器啟動時載入的 AOF 檔案的體積來作為基準值)。将這個值 設定為 0 表示關閉自動 AOF 重寫。

      比如: 
        auto-aof-rewrite-percentage 100 
        auto-aof-rewrite-min-size 64mb 
        # 當 AOF 檔案大于 64MB 時候,可以考慮重寫 AOF 檔案
        # 隻有當 AOF 檔案的增量大于起始 size 的 100%時(就是檔案大小翻了一倍),啟動重
        
        appendonly yes # 預設關閉,請開啟
                 

2.3.2 重寫過程

Redis 持久化(RDB和AOF模式)Redis持久化
  • 1 執行 AOF 重寫請求
  • 2 父程序執行 fork 建立子程序,開銷等同于 bgsave 過程
  • 3.1 主程序 fork 操作完成後,繼續響應其他指令。所有修改指令依然寫入 AOF 緩沖區,并根據appendfsync 政策同步到磁盤,保證原有 AOF 機制正确性。
  • 3.2 由于 fork 操作運用寫時複制技術,子程序隻能共享 fork 操作時的記憶體資料。由于父程序依然響應指令,redis 使用“ AOF 重寫緩沖區”儲存這部分新資料,防止新 AOF 檔案生成期間丢失這部分資料。
  • 4 子程序根據記憶體快照,按照指令合并規則寫入到新 AOF 檔案。每次批量寫入硬碟資料量由 aof-rewrite-incremental-fsync 控制,預設是32MB,防止單詞刷盤資料過多造成硬碟阻塞。
  • 5.1 新 AOF 檔案寫入完成後,子程序發送信号給父程序,父程序更新統計資訊。
  • 5.2 父程序把 AOF 重寫緩沖區資料寫入到新的 AOF 檔案。
  • 5.3 使用新AOF檔案替換老檔案,完成AOF重寫。

注: 如果寫入操作的時候出現故障導緻指令寫了“半截”,可以使用 redis-check-aof 工具修複

2.3.3 AOF 優缺點

  • 優點
    • 寫入機制,預設 fysnc 每秒執行,性能很好不阻塞服務,最多丢失一秒的資料
    • 重寫機制,優化 AOF 檔案
    • 如果誤操作了(FLUSHALL 等),隻要 AOF 未被重寫,停止服務移除 AOF 檔案尾部 FLUSHALL 指令,重新開機 Redis,可以将資料集恢複到 FLUSHALL 執行之前的狀态
  • 缺點
    • 相同資料集,AOF 檔案體積較 RDB 大了很多
    • 恢複資料庫速度比 RDB 慢(文本,指令重演)

繼續閱讀