redis持久化配置
redis.conf
// RDB配置
save 900 1
save 300 10
save 60 10000
// AOF配置
appendonly yes
//AOF三種同步方式
# appendfsync always
appendfsync everysec
# appendfsync no
RDB配置對應saveparams參數:
dirty:距離上一次成功執行SAVE或BGSAVE指令之後,伺服器對資料庫狀态進行了多少次修改
RDB和AOF對比
因為AOF更新頻率通常比RDB檔案高,是以:
- 如果伺服器開啟了AOF,那麼伺服器優先使用AOF檔案來還原資料庫狀态
- 隻有在AOF關閉狀态,伺服器才使用RDB檔案還原資料庫狀态
RDB
RDB手動觸發和自動觸發
- 手動觸發分别對應save和bgsave指令
- SAVE:阻塞redis程序,直到RDB檔案建立完畢為止
- BGSAVE:不阻塞,派生出一個子程序,然後由子程序負責建立RDB檔案
- BGSAVE指令執行時,用戶端發送SAVE或BGSAVE指令會被拒絕,避免父程序和子程序同時執行兩個rdbSave調用,防止産生競争條件
- BGSAVE指令執行時,用戶端發送BGSAVE指令會被拒絕,避免兩個父程序同時執行兩個rdbSave調用,防止産生競争條件
- BGSAVE指令執行時,用戶端發送BGREWRITEAOF指令會被延遲到BGSAVE指令執行完畢之後執行;若是BGREWRITEAOF指令正在執行,用戶端發送BGSAVE指令會被拒絕
bgsave執行流程(注意第二步,fork操作建立子程序時,父程序會阻塞)
- redis内部自動觸發
- 使用save相關配置,如save m n,表示m秒記憶體在n次修改,自動觸發bgsave
- 如果從節點執行全量複制操作,主節點自動執行bgsave生成RDB檔案并發送給從節點
- 執行debug reload指令重新加載redis時,也會觸發save操作
- 預設情況下執行shutdown指令時,如果沒有開啟AOF持久化功能,則自動執行bgsave
RDB檔案載入:在伺服器啟動時,檢測到RDB檔案存在,自動載入
RDB檔案結構
RDB結構:
- REDIS: 5位元組,儲存"REDIS"5個字元
- db_version:4位元組,記錄RDB檔案的版本号
database部分:
database 0 代表0資料庫所有鍵值對資料;database 3 代表3資料庫所有鍵值對資料;
- SELECTDB:1位元組,代表接下來要讀一個資料庫分區号
AOF
AOF主要作用:解決資料持久化的實時性
AOF工作流程
- 所有寫入指令會追加到aof_buf(緩沖區)中
- AOF緩沖區根據對應的同步政策向硬碟做同步操作
- 随着AOF檔案越來越大,需要定期對AOF檔案進行重寫,達到壓縮的目的
- 當Redis伺服器重新開機時,可以加載AOF檔案進行資料恢複
AOF一些問題
- AOF為何直接采用文本協定?
- 文本協定具有很好的相容性
- 開啟AOF後,所有寫入指令都包含追加操作,直接采用文本協定格式,避免二次處理開銷
- 文本協定具有可讀性,友善直接修改和處理
- AOF為何把指令追加到aof_buf中?
- Redis使用單線程響應指令,如果每次寫AOF指令都直接寫入磁盤,那麼性能完全取決目前硬碟負載。另寫入緩沖區,可以提供多種緩沖區同步硬碟的政策,在性能和安全性方面做出平衡
檔案同步
重寫機制
AOF重寫作用:
- 降低檔案占用空間
- 更小的AOF檔案可以更快的被redis加載
重寫機制指令或配置:
- 手動觸發:bgrewriteaof指令
- 自動觸發配置:
- auto-aof-rewrite-min-size:AOF重寫時,檔案最小體積,預設64MB
- auto-aof-rewrite-percentage:目前AOF空間(aof_current_size)與上一次重寫後AOF檔案空間(aof_base_size)的比值
- 自動觸發時機:aof_current_size > auto-aof-rewrite-min-size && (aof_current_size - aof_base_size) / aof_base_size >= auto-aof-rewrite-percentage
重寫流程:
-
- 執行AOF重寫請求
-
- 父程序執行fork建立子程序
-
- 1)父程序fork操作完成後,繼續響應其他指令;所有修改指令依然寫入AOF緩沖區,并根據appendfsync政策同步到硬碟,保證原有AOF機制正确 2)由于fork操作運用寫時複制技術,子程序隻能共享fork操作時的記憶體資料。由于父程序依然響應指令,Redis使用AOF重寫緩沖區儲存這部分資料,防止AOF檔案生成期間丢失這部分資料
- 子程序根據記憶體快照,按照指令合并規則寫入到新的AOF檔案。每次批量寫入硬碟資料量由配置aof-rewrite-incremental-fsync控制,預設32MB,防止單次刷盤過多造成硬碟阻塞
- 新的AOF檔案寫入完成後,子程序發送信号給父程序,父程序更新統計資訊,具體見info persistence下aof_*相關統計
- 父程序把AOF重寫緩沖區的資料寫入新的AOF檔案
- 使用新的AOF檔案替換老檔案,完成AOF重寫
重寫AOF檔案為什麼可以變小:
- 程序内已經逾時的資料不再寫入檔案
- 舊的AOF檔案含有無效指令,如del key1、hdel key2、srem keys、set a111、set a222等;重寫使用程序内資料直接生成,這樣新的AOF檔案隻保留最終資料寫入指令
- 多條寫指令可以合并為一個;為防止單條指令過大,造成用戶端緩沖區溢出,對于list、set、hash、zset等類型操作,以64個元素為界拆分為多條。
AOF追加阻塞
流程:
- 主線程負責寫入AOF緩沖區
- AOF線程負責每秒執行一次同步磁盤操作,并記錄最近一次同步時間
- 主線程負責對比上次AOF同步時間:
- 如果距離上次同步時間小于2s,直接傳回
- 如果距離上次同步時間大于2s,主線程将會阻塞,直到同步操作完成
可以發現兩個問題:
- everysec配置最多丢失2s資料,不是1s
- 如果系統fsync緩慢,将會導緻redis主線程阻塞,影響效率
每當AOF追加阻塞事件發生時,在info persistence統計中,aof_delayed_fsync名額會累加
一些指令
save //等待RDB檔案建立完畢
bgsave //fork生成子程序
config set dir {newDir} //RDB檔案儲存在dir目錄下
config set dbfilename {newFileName} //RDB檔案名
config set rdbcompression {yew|no}//預設采用LZF算法進行壓縮,預設開啟,此指令動态進行修改是否進行壓縮
bgrewriteaof //aof檔案重寫
redis-cli config set appendonly yes //開啟aof
redis-cli config set save “” //關閉rdb
info stats
redis-check-aof –fix
參考:
《Redis開發與運維》
《Redis設計與實作》
http://www.redis.cn/documentation.html
https://mp.weixin.qq.com/s/GwjQalQ9ZkBbTBtEKpbkMw
http://www.redis.cn/topics/persistence.html