天天看點

深入了解Redis系列之持久化

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手動觸發和自動觸發

  1. 手動觸發分别對應save和bgsave指令
  • SAVE:阻塞redis程序,直到RDB檔案建立完畢為止
  • BGSAVE:不阻塞,派生出一個子程序,然後由子程序負責建立RDB檔案
  • BGSAVE指令執行時,用戶端發送SAVE或BGSAVE指令會被拒絕,避免父程序和子程序同時執行兩個rdbSave調用,防止産生競争條件
  • BGSAVE指令執行時,用戶端發送BGSAVE指令會被拒絕,避免兩個父程序同時執行兩個rdbSave調用,防止産生競争條件
  • BGSAVE指令執行時,用戶端發送BGREWRITEAOF指令會被延遲到BGSAVE指令執行完畢之後執行;若是BGREWRITEAOF指令正在執行,用戶端發送BGSAVE指令會被拒絕

bgsave執行流程(注意第二步,fork操作建立子程序時,父程序會阻塞)

  1. 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資料庫所有鍵值對資料;

深入了解Redis系列之持久化
  • SELECTDB:1位元組,代表接下來要讀一個資料庫分區号
    深入了解Redis系列之持久化
深入了解Redis系列之持久化

AOF

AOF主要作用:解決資料持久化的實時性

AOF工作流程

  1. 所有寫入指令會追加到aof_buf(緩沖區)中
  2. AOF緩沖區根據對應的同步政策向硬碟做同步操作
  3. 随着AOF檔案越來越大,需要定期對AOF檔案進行重寫,達到壓縮的目的
  4. 當Redis伺服器重新開機時,可以加載AOF檔案進行資料恢複

AOF一些問題

  1. AOF為何直接采用文本協定?
  • 文本協定具有很好的相容性
  • 開啟AOF後,所有寫入指令都包含追加操作,直接采用文本協定格式,避免二次處理開銷
  • 文本協定具有可讀性,友善直接修改和處理
  1. AOF為何把指令追加到aof_buf中?
  • Redis使用單線程響應指令,如果每次寫AOF指令都直接寫入磁盤,那麼性能完全取決目前硬碟負載。另寫入緩沖區,可以提供多種緩沖區同步硬碟的政策,在性能和安全性方面做出平衡

檔案同步

重寫機制

AOF重寫作用:

  • 降低檔案占用空間
  • 更小的AOF檔案可以更快的被redis加載

重寫機制指令或配置:

  1. 手動觸發:bgrewriteaof指令
  2. 自動觸發配置:
  • 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

重寫流程:

    1. 執行AOF重寫請求
    1. 父程序執行fork建立子程序
    1. 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追加阻塞

流程:

  1. 主線程負責寫入AOF緩沖區
  2. AOF線程負責每秒執行一次同步磁盤操作,并記錄最近一次同步時間
  3. 主線程負責對比上次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

繼續閱讀