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 替代舊檔案;生産環境很少這樣做,一般都是停機維護時期才考慮
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLxYTM0QjMwATMyIjNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
(2)BGSAVE
非阻塞,Redis 服務正常接收處理用戶端請求,Redis 會 fork()一個新的子程序來建立 RDB 檔案,子程序處理完後會向父程序發送一個信号,通知它處理完畢,父程序用新的 dump.rdb 替代舊檔案。BGSAVE 是一個異步指令。
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 損失小得多。
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 重寫過程
- 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 慢(文本,指令重演)