Redis的持久化

来源:https://www.cnblogs.com/ivictor/archive/2018/10/07/9749465.html
-Advertisement-
Play Games

RDB RDB是將當前數據生成快照保存到硬碟上。 RDB的工作流程: 1. 執行bgsave命令,Redis父進程判斷當前是否存在正在執行的子進程,如RDB/AOF子進程,如果存在bgsave命令直接返回。 2. 父進程執行fork操作創建子進程,fork操作過程中父進程被阻塞。 3. 父進程for ...


RDB

RDB是將當前數據生成快照保存到硬碟上。

 

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)。父子進程會共用相同的物理記憶體頁,當父進程處理寫請求時會把要修改的頁創建副本,而子進程在fork操作過程中會共用父進程的記憶體快照。

 

觸發機制:

1. 手動觸發

   包括save和bgsave命令。

    因為save會阻塞當前Redis節點,所以,Redis內部所有涉及RDB持久化的的操作都通過bgsave方式,save方式已廢棄。

2. 自動觸發

    1> 使用save的相關配置。

    2> 從節點執行全量複製操作。

    3> 執行debug reload命令。

    4> 執行shutdown命令時,如果沒有開啟AOF持久化功能則會自動執行bgsave。

 

RDB的優缺點:

優點:

1. RDB是一個緊湊壓縮的二進位文件,代表Redis在某個時間點上的數據快照,適合備份,全量複製等場景。

2. 載入RDB恢複數據遠遠快於AOF的方式。

缺點:

沒辦法做到實時持久化/秒級持久化,因為bgsave每次運行都要執行fork操作創建子進程,屬於重量級操作,頻繁執行成本過高。

 

RDB的相關參數

save 900 1
save 300 10
save 60 10000

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename dump.rdb

dir ./

 

其中,前三個參數的含義是,

#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed

 

如果要禁用RDB的自動觸發,可註銷這三個參數,或者設置save ""。

stop-writes-on-bgsave-error:在開啟RDB且最近一次bgsave執行失敗的情況下,如果該參數為yes,則Redis會阻止客戶端的寫入,直到bgsave執行成功。

rdbcompression:使用LZF演算法壓縮字元對象。

rdbchecksum:從RDB V5開始,在保存RDB文件時,會在文件末尾添加CRC64校驗和,這樣,能較容易的判斷文件是否被損壞。但同時,對於帶有校驗和的RDB文件的保存和載入,會有10%的性能損耗。

dbfilename: RDB文件名。

dir:RDB文件保存的目錄。

 

RDB的相關變數

127.0.0.1:6379> info Persistence
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1538447605
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:155648

其含義如下:

loading: Flag indicating if the load of a dump file is on-going。是否在載入RDB文件

rdb_changes_since_last_save: Number of changes since the last dump。

rdb_bgsave_in_progress: Flag indicating a RDB save is on-going。是否在執行bgsave操作。

rdb_last_save_time: Epoch-based timestamp of last successful RDB save。最近一次bgsave操作時的時間戳。

rdb_last_bgsave_status: Status of the last RDB save operation。最近一次bgsave是否執行成功。

rdb_last_bgsave_time_sec: Duration of the last RDB save operation in seconds。最近一次bgsave操作花費的時間。

rdb_current_bgsave_time_sec: Duration of the on-going RDB save operation if any。當前bgsave操作已經執行的時間。

rdb_last_cow_size: The size in bytes of copy-on-write allocations during the last RBD save operation。COW的大小。指的是父進程與子進程相比執行了多少修改,包括讀取緩衝區,寫入緩衝區,數據修改等。

 

AOF

與RDB不一樣的是,AOF記錄的是命令,而不是數據。需要註意的是,其保存的是Redis Protocol,而不是直接的Redis命令。但是以文本格式保存。

 

如何開啟AOF

只需將appendonly設置為yes就行。

 

AOF的工作流程:

1. 所有的寫入命令追加到aof_buf緩衝區中。

2. AOF會根據對應的策略向磁碟做同步操作。刷盤策略由appendfsync參數決定。

3. 定期對AOF文件進行重寫。重寫策略由auto-aof-rewrite-percentage,auto-aof-rewrite-min-size兩個參數決定。

 

appendfsync參數有如下取值:

no: don't fsync, just let the OS flush the data when it wants. Faster. 只調用系統write操作,不對AOF文件做fsync操作,同步硬碟操作由操作系統負責,通常同步周期最長為30s。

always: fsync after every write to the append only log. Slow, Safest. 命令寫入到aof_buf後,會調用系統fsync操作同步到文件中。

everysec: fsync only one time every second. Compromise. 只調用系統write操作,fsync同步文件操作由專門進程每秒調用一次。

預設值為everysec,也是建議值。

 

重寫機制

為什麼要重寫?重寫後可以加快節點啟動時的載入時間。

重寫後的文件為什麼可以變小?

1. 進程內超時的數據不用再寫入到AOF文件中。

2. 存在刪除命令。

3. 多條寫命令可以合併為一個。

 

重寫條件:

1. 手動觸發

     直接調用bgrewriteaof命令。

2. 自動觸發。

    與auto-aof-rewrite-percentage,auto-aof-rewrite-min-size兩個參數有關。

    觸發條件,aof_current_size > auto-aof-rewrite-min-size 並且 (aof_current_size  - aof_base_size) / aof_base_size >= auto-aof-rewrite-percentage。

    其中,aof_current_size是當前AOF文件大小,aof_base_size 是上一次重寫後AOF文件的大小,這兩部分的信息可從info Persistence處獲取。

 

AOF重寫的流程。

1. 執行AOF重寫請求。

    如果當前進程正在執行bgsave操作,重寫命令會等待bgsave執行完後再執行。

2. 父進程執行fork創建子進程。

3. fork操作完成後,主進程會繼續響應其它命令。所有修改命令依然會寫入到aof_buf中,並根據appendfsync策略持久化到AOF文件中。

4. 因fork操作運用的是寫時複製技術,所以子進程只能共用fork操作時的記憶體數據,對於fork操作後,生成的數據,主進程會單獨開闢一塊aof_rewrite_buf保存。

5. 子進程根據記憶體快照,按照命令合併規則寫入到新的AOF文件中。每次批量寫入磁碟的數據量由aof-rewrite-incremental-fsync參數控制,預設為32M,避免單次刷盤數據過多造成硬碟阻塞。

6. 新AOF文件寫入完成後,子進程發送信號給父進程,父進程更新統計信息。

7. 父進程將aof_rewrite_buf(AOF重寫緩衝區)的數據寫入到新的AOF文件中。

8. 使用新AOF文件替換老文件,完成AOF重寫。

實際上,當Redis節點執行完一個命令後,它會同時將這個寫命令發送到AOF緩衝區和AOF重寫緩衝區。

 

Redis通過AOF文件還原資料庫的流程。

1.  創建一個不帶網路連接的偽客戶端。因為Redis的命令只能在客戶端上下文中執行。

2. 從AOF文件中分析並讀取一條命令。

3. 使用偽客戶端執行該命令。

4. 反覆執行步驟2,3,直到AOF文件中的所有命令都被處理完。 

 

註意:AOF的持久化也可能會造成阻塞。

AOF常用的持久化策略是everysec,在這種策略下,fsync同步文件操作由專門線程每秒調用一次。當系統磁碟較忙時,會造成Redis主線程阻塞。

1. 主線程負責寫入AOF緩衝區。

2. AOF線程負責每秒執行一次同步磁碟操作,並記錄最近一次同步時間。

3. 主線程負責對比上次AOF同步時間。

   1> 如果距上次同步成功時間在2s內,主線程直接返回。

   2> 如果距上次同步成功時間超過2s,主線程會阻塞,直到同步操作完成。每出現一次阻塞,info Persistence中aof_delayed_fsync的值都會加1。

所以,使用everysec策略最多會丟失2s數據,而不是1s。

 

AOF的相關變數

127.0.0.1:6379> info Persistence
# Persistence
...
aof_enabled:1
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0
aof_current_size:19276803
aof_base_size:19276803
aof_pending_rewrite:0
aof_buffer_length:0
aof_rewrite_buffer_length:0
aof_pending_bio_fsync:0
aof_delayed_fsync:0

其含義如下,

aof_enabled: Flag indicating AOF logging is activated. 是否開啟AOF

aof_rewrite_in_progress: Flag indicating a AOF rewrite operation is on-going. 是否在進行AOF的重寫操作。

aof_rewrite_scheduled: Flag indicating an AOF rewrite operation will be scheduled once the on-going RDB save is complete. 是否有AOF操作等待執行。

aof_last_rewrite_time_sec: Duration of the last AOF rewrite operation in seconds. 最近一次AOF重寫操作消耗的時間。

aof_current_rewrite_time_sec: Duration of the on-going AOF rewrite operation if any. 當前正在執行的AOF操作已經消耗的時間。

aof_last_bgrewrite_status: Status of the last AOF rewrite operation. 最近一次AOF重寫操作是否執行成功。

aof_last_write_status: Status of the last write operation to the AOF. 最近一次追加操作是否執行成功。

aof_last_cow_size: The size in bytes of copy-on-write allocations during the last AOF rewrite operation. 在執行AOF重寫期間,分配給COW的大小。

 

如果開啟了AOF,還會增加以下變數

aof_current_size: AOF current file size. AOF的當前大小。

aof_base_size: AOF file size on latest startup or rewrite. 最近一次重寫後AOF的大小。

aof_pending_rewrite: Flag indicating an AOF rewrite operation will be scheduled once the on-going RDB save is complete.是否有AOF操作在等待執行。

aof_buffer_length: Size of the AOF buffer. AOF buffer的大小

aof_rewrite_buffer_length: Size of the AOF rewrite buffer. AOF重寫buffer的大小。

aof_pending_bio_fsync: Number of fsync pending jobs in background I/O queue. 在等待執行的fsync操作的數量。

aof_delayed_fsync: Delayed fsync counter. Fsync操作延遲執行的次數。


如果一個load操作在進行,還會增加以下變數
loading_start_time: Epoch-based timestamp of the start of the load operation. Load操作開始的時間。

loading_total_bytes: Total file size. 文件的大小。

loading_loaded_bytes: Number of bytes already loaded.已經載入的文件的大小。

loading_loaded_perc: Same value expressed as a percentage. 已經載入的比例。

loading_eta_seconds: ETA in seconds for the load to be complete. 預計多久載入完畢。

 

AOF的相關參數

appendonly yes
appendfilename "appendonly.aof"

appendfsync everysec

no-appendfsync-on-rewrite no

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

aof-load-truncated yes

aof-use-rdb-preamble no

其中,

no-appendfsync-on-rewrite:在執行bgsave或bgrewriteaof操作時,不調用fsync()操作,此時,Redis的持久化策略相當於"appendfsync none"。

aof-load-truncated:在Redis節點啟動的時候,如果發現AOF文件已經損壞了,其處理邏輯與該參數的設置有關,若為yes,則會忽略掉錯誤,儘可能載入較多的數據,若為no,則會直接報錯退出。預設為yes。需要註意的是,該參數只適用於Redis啟動階段,如果在Redis運行過程中,發現AOF文件corrupted,Redis會直接報錯退出。

aof-use-rdb-preamble:是否啟用Redis 4.x提供的AOF+RDB的混合持久化方案,若為yes,在重寫AOF文件時,Redis會將數據以RDB的格式作為AOF文件的開始部分。在重寫之後,Redis會繼續以AOF格式持久化寫入操作。預設值為no。

 

參考:

1. 《Redis開發與運維》

2. 《Redis設計與實現》

3. 《Redis 4.X Cookbook》


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [20181007]12cR2 Using SQL Patch.txt--//12cR2 已經把sql打補丁集成進入dbms_sqldiag,不是11g的 DBMS_SQLDIAG_INTERNAL.I_CREATE_PATCH .做一個記錄.--//以前的鏈接:http://blog.itpub. ...
  • 解決在將Excel表格導入到SQL Server資料庫時出現:Text was truncated or one or more characters had no match in the target code 的錯誤。將Excel表中最長的那條記錄移到第二行(即第一條記錄所在行)即可解決導入失... ...
  • MySQL集群架構系列將討論MySQL集群架構的幾種最常見形式解決的問題,實現原理,存在的問題,以及環境搭建步驟。 本文主要討論MySQL架構關註的問題。 1.高可用的作用 在MySQL的高可用架構中,高可用的作用簡單來講就是保證整個架構的對外服務不會出現中斷,即通過技術手段避免單點故障引起架構整體 ...
  • MySQL的字元串是從1開始編號的,這與電腦編程語言有所不同,在MySQL中1代表第一個字元,-1代表最後一個字元,以此類推。 MySQL中百分號“%”代表的是任意個字元,下劃線“_”代表的是任意一個字元。 ...
  • 本文配置主從使用的操作系統是Centos7,資料庫版本是mysql5.7。 準備好兩台安裝有mysql的機器(mysql安裝教程鏈接) 主資料庫配置 每個從資料庫會使用一個MySQL賬號來連接主資料庫,所以我們要在主資料庫里創建一個賬號,並且該賬號要授予 REPLICATION SLAVE 許可權 創 ...
  • #創建資料庫create database ST CHARACTER set utf8;#創建用戶create user ST identified by '19980510';#授權用戶操作該資料庫grant all on ST.* to ST; #創建學生表create table Studen ...
  • 1.環境準備 RHEL7.4(最小化安裝) 64bit 2G 記憶體 (1G 記憶體編譯將近一個小時) 磁碟空間 15G 以上。 配置為本地yum 源 從MySQL5.7版本開始,安裝MySQL需要依賴 Boost 的C++擴展,而且只能是 1.59.0 版本; 2.cmake簡介 從mysql5.5起 ...
  • 大數據又稱黑暗數據,是指人腦無法處理的海量數據聚合成的信息資產,在民生、IT、金融、農業、通信等方面都有廣泛應用。未來5年大數據行業呈井噴趨勢,人才需求火爆,2018年大數據人才缺口更是高達900萬。以後想要做大數據相關的工作,需要學習哪些技術知識? 羅馬不是一天建成的,大數據工程師也不是短時間能鍛 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...