Redis 持久化

RDB

簡介

RDB持久化方式是通過快照(snapshotting)完成的,當符合一定條件時,redis會自動將內存中所有數據以二進制方式生成一份副本並存儲在硬盤上。當redis重啟時,並且AOF持久化未開啟時,redis會讀取RDB持久化生成的二進制文件(默認名稱dump.rdb,可通過設置dbfilename修改)進行數據恢復,對於持久化信息可以用過命令“info Persistence”查看。

save

該命令會由worker thread 執行,因此會阻塞 redis 的 worker ,期間不會響應任何其他客戶端發來的請求,直到RDB快照文件執行完畢,所以慎用。

測試

info persistence 
# rdb_last_save_time:1570126868
save
info persistence
# rdb_last_save_time:1570126928

bgsave

bgsave“後台保存”。與save 最大的差異為它並不是由 worker thread 執行的,而是由redis fork 齣子進程,交由子進程來完成持久化操作。

redisfork子進程這個時間段內 redis是阻塞的(此段時間不會響應客戶端請求),當子進程創建完成以後redis才會響應客戶端請求。

並且redis不會在控制台显示完成信息,只會寫入日誌。

流程

客戶端執行bgsave命令,redis主進程收到指令並判斷此時是否在執行bgrewriteaof(AOF文件重新過程,後續會講解),如果此時正好在執行則bgsave直接返回,不fork子進程,如果沒有執行bgrewriteaof重寫AOF文件,則進入下一個階段;

主進程調用fork方法創建子進程,在創建子進程過程中redis主進程阻塞,所以不能響應客戶端請求;

子進程創建完成以後,bgsave命令返回Background saving started,此時標志著redis可以響應客戶端請求了;

子經常根據主進程的內存副本創建臨時快照文件,當快照文件完成以後對原快照文件進行替換;

子進程發送信號給redis主進程完成快照操作,主進程更新統計信息(info Persistence可查看),子進程退出;

測試

bgsave
Background saving started  # 子進程創建成功,它會去 完成持久化操作

查看日誌

config get logfile
 11) "logfile"
 12) "/var/log/redis/redis-server.log"
cat "/var/log/redis/redis-server.log"
2497:M 04 Oct 2019 10:26:46.764 * Background saving started by pid 28960   # 開始後台 持久化
2497:M 04 Oct 2020 10:26:46.772 * Background saving terminated with success   # 後台持久化完成 

RDB相關配置

查看配置的方法:

1 查看配置文件

2 在redis 中查看當前 redis 的配置

CONFIG get *    # 獲取所有的配置
CONFIG get dir   # 獲取 快照文件 保存的 位置
CONFIG get dbfilename   # 獲取 快照文件 的文件名

快照文件位置

配置文件中 dir 指定

快照文件名

配置文件中 dbfilename

是否壓縮

配置文件中 rdbcompression default:yes

設置存儲至本地數據庫時是否壓縮數據,默認為yes,採用LZF壓縮

yes 會耗費一定的CPU資源,默認是 yes 。

no 會使存儲的文件變大(巨大)

是否校驗

配置文件中 yesrdbchecksumy default: yes

yes 會消耗一部分CPU資源,但是數據相對安全不容易損壞

no 可以節約讀寫性過程約10%時間消耗,但是存儲一定的數據損壞風險

後台持久化報錯

配置文件中 stop-writes-on-bgsave-error default: yes

後台存儲過程中如果出現錯誤線程,是否停止保存操作,默認是停止的

no 則忽略錯誤繼續。

快照檢查

配置文件中 rdbchecksum default: yes
在寫入文件和讀取文件時是否開啟rdb文件檢查,檢查是否有無損壞,如果在啟動是檢查發現損壞,則停止啟動。

RDB觸發

自動觸發

配置文件中 save default: yes

save second changes
# 查看默認的配置
config get save
"900 1 300 10 60 10000"
# 900秒內 1次鍵更新了就觸發持久化 或 300秒內 10次更新 持久化 60 秒內 10000次更新 觸發持久化
# 該持久化是 bgsave

手動觸發

手動執行 savebgsave

其他觸發

以下幾種種情況下會觸發執行快照操作,並且默認的使用bgsave

主從複製時,從庫全量複製同步主庫數據,此時主庫會執行bgsave命令進行快照;

客戶端執行數據庫清空命令FLUSHALL時候,觸發快照;

客戶端執行shutdown關閉redis時,觸發快照,也可以 使用 nosave 參數顯式聲明不保存快照

shutdown nosave

故障恢復

當redis意外崩潰或者關閉再次啟動時,此時AOF持久化未開啟時(默認未開啟),將使用RDB快照文件恢複數據。

# 查看日誌
cat /var/log/redis/redis-server.log
30448:M 04 Oct 2019 10:09:37.145 # Server initialized
30448:M 04 Oct 2019 10:09:37.145 * DB loaded from disk: 0.000 seconds   # 從快照恢復
30448:M 04 Oct 2019 10:09:37.146 * Ready to accept connections

缺點

RDB方式無論是執行指令還是利用配置,無法做到實時持久化,具體較大的可能性丟失數據

bgsave指令每次運行要執行fork操作創建子進程,要犧牲掉一些性能

Redis的眾多版本中未進行RDB文件格式的版本統一,有可能出現個版本服務之間數據格式無法兼容現象

存儲數據量較大,效率較低——基於快照思想,每次讀寫都是全部數據,當數據量巨大時,效率非常低
大數據量下的IO性能較低

AOF

簡介

日誌形式的AOF,將命令追加到文件。AOF可以將Redis執行的每一條寫命令追加到磁盤文件(appendonly.aof)中,在redis啟動時候優先選擇從AOF文件恢複數據。因為要頻繁的將每一個操作記錄到文件中,所以開啟AOF持久化會對性能有一定的影響,但是大部分情況下這個影響是可以接受的。

與RDB持久化相比,AOF持久化數據丟失更少,其消耗內存更少(RDB方式執行bgsve會有內存拷貝)。

AOF持久化過程

redisAOF持久化過程可分為以下階段:

追加寫入

redis將每一條寫命令以redis通訊協議添加至緩衝區aof_buf,這樣的好處在於在大量寫請求情況下,採用緩衝區暫存一部分命令隨後根據策略一次性寫入磁盤,這樣可以減少磁盤的I/O次數,提高性能。

同步三種策略

當寫命令寫入aof_buf緩衝區后,redis會將緩衝區的命令寫入到文件,redis提供了三種同步策略,由配置參數appendfsync決定,下面是每個策略所對應的含義:

no

不使用fsync方法同步,而是交給操作系統write函數去執行同步操作,在linux操作系統中大約每30秒執行一次 sync(man 2 sync 查看)。這種情況下,緩衝區數據同步不可控,並且在大量的寫操作下,aof_buf緩衝區會堆積會越來越嚴重,一旦redis出現故障,數據丟失嚴重,整體不可控。

always

表示每次有寫操作都調用fsync方法強制內核將數據寫入到aof文件。這種情況下由於每次寫命令都寫到了文件中, 雖然數據比較安全,但是因為每次寫操作都會同步到AOF文件中,所以在性能上會有影響,同時由於頻繁的IO操作,硬盤的使用壽命會降低。

everysec

數據將使用調用操作系統write寫入文件,並使用fsync每秒一次從內核刷新到磁盤。 這是折中的方案,兼顧性能和數據安全,所以redis默認推薦使用該配置。

文件重寫

當開啟AOF時,隨着時間推移,AOF文件會越來越大,redis提出一種重寫的策略來緩解數據存儲和恢復壓力。

重寫策略

重複或無效的命令不寫入文件

過期的數據不再寫入文件

多條命令合併寫入(當多個命令能合併一條命令時候會對其優化合併作為一個命令寫入,例如“RPUSH list1 a RPUSH list1 b” 合併為“RPUSH list1 a b” )

觸發條件

AOF文件觸發條件可分為手動觸發和自動觸發:

手動觸發:客戶端執行bgrewriteaof命令。

自動觸發:自動觸發通過以下兩個配置協作生效:

auto-aof-rewrite-min-size

AOF文件最小重寫大小,只有當AOF文件大小大於該值時候才可能重寫,4.0默認配置64mb。

auto-aof-rewrite-percentage

當前AOF文件大小和最後一次重寫后的大小之間的比率等於或者等於指定的增長百分比,如100代表當前AOF文件是上次重寫的兩倍時候才重寫。 

redis在AOF功能開啟的情況下,會維持以下三個變量

aof_current_size :記錄當前AOF文件大小

aof_rewrite_base_size:記錄最後一次AOF重寫之後,AOF文件大小

aof_rewrite_perc:增長百分比變量

每次當serverCron(服務器周期性操作函數)函數執行時,它會檢查以下條件是否全部滿足,如果全部滿足的話,就觸發自動的AOF重寫操作:

沒有BGSAVE命令(RDB持久化)/AOF持久化在執行;

沒有BGREWRITEAOF在進行;

當前AOF文件大小要大於server.aof_rewrite_min_size的值;

當前AOF文件大小和最後一次重寫后的大小之間的比率等於或者大於指定的增長百分比(auto-aof-rewrite-percentage參數)

重寫過程

  AOF文件重寫過程與RDB快照bgsave工作過程有點相似,都是通過fork子進程,由子進程完成相應的操作,同樣的在fork子進程簡短的時間內,redis是阻塞的,以下圖文說明其重寫過程:

開始bgrewriteaof,判斷當前有沒有bgsave命令(RDB持久化)/bgrewriteaof在執行,倘若有,則這些命令執行完成以後在執行。

主進程fork齣子進程,在這一個短暫的時間內,redis是阻塞的。

當完成重寫后,將重寫后的aof 文件合併到原有aof緩存文件中。並刪除臨時創建的重寫后的aof文件

AOF實現本質

AOF實現本質是基於redis通訊協議,將命令以純文本的方式寫入到文件中。

redis協議:

首先Redis是以行來劃分,每行以\r\n行結束。每一行都有一個消息頭,消息頭共分為5種分別如下:

(+) 表示一個正確的狀態信息,具體信息是當前行+後面的字符。

(-) 表示一個錯誤信息,具體信息是當前行-後面的字符。

(*) 表示消息體總共有多少行,不包括當前行,*後面是具體的行數。

($) 表示下一行數據長度,不包括換行符長度\r\n,$後面則是對應的長度的數據。

(:) 表示返回一個數值,:後面是相應的数字節符。

我們可以直接查看AOF文件中的格式,如下圖:

數據恢復

之前已經提到當AOF開啟時候,redis數據恢復優先選用AOF進行數據恢復,以下使用停止redis來模擬redis故障,然後在重寫啟動進行恢復。

AOF配置參數

auto-aof-rewrite-min-size

AOF文件最小重寫大小,只有當AOF文件大小大於該值時候才可能重寫,4.0默認配置64mb。

auto-aof-rewrite-percentage

當前AOF文件大小和最後一次重寫后的大小之間的比率等於或者等於指定的增長百分比,如100代表當前AOF文件是上次重寫的兩倍時候才重寫。默認 100

appendfsync

上文中提到的三種策略,默認 everysec

always | everysec | no

aof-load-truncated yes

當redis突然運行崩潰時,會出現aof文件被截斷的情況,Redis可以在發生這種情況時退出並加載錯誤,以下選項控制此行為。
如果aof-load-truncated設置為yes,則加載截斷的AOF文件,Redis服務器啟動發出日誌以通知用戶該事件。
如果該選項設置為no,則服務將中止並显示錯誤並停止啟動。當該選項設置為no時,用戶需要在重啟之前使用redis-check-aof實用程序修復AOF文件在進行啟動。

appendonly no

yes開啟AOF,no關閉AOF 默認 no

appendfilename

指定AOF文件名,4.0無法通過config set 設置,只能通過修改配置文件設置。默認 appendonly.aof

RDB-AOF混合持久化

簡介

redis4.0添加了新的持久化方式混合持久化

混合持久化默認是關閉的,它採用一種rdb + aof 的方式來實現,文件頭rdb 一個全量的快照,格式為二進制,後面是 aof 格式。這樣恢復會先查看開頭是否為REDIS,rdb開頭必然是REDIS。然後從快照恢復,之後從aof恢復。

這樣做的好處是可以結合 rdb 和 aof 的優點, 快速加載同時避免丟失過多的數據

缺點是 aof 裏面的 rdb 部分就是壓縮格式不再是 aof 格式,可讀性差。

開啟混合持久化

5 版本的redis 默認的開啟了aof-use-rdb-preamble 但是 appendonly 默認是 no 也就是說,只要開啟了aof 默認的會使用混合持久化。如果要使用單純的aof 則需要手動的 將 aof-use-rdb-preamble 設為 no (好坑)

4.0版本的混合持久化默認關閉的,通過aof-use-rdb-preamble配置參數控制,yes則表示開啟,no表示禁用,默認是禁用的,可通過config set修改。

混合持久化過程

創建子進程

生成全量的rdb快照,放在appendonly.aof 文件頭部。然後,接下來將aof緩衝區的增量命令以aof方式寫入文件尾

每次恢複數據時,首先從RDB部分恢復,然後執行aof。

數據恢復

開啟了混合持久化時,啟動redis依然優先加載aof文件,aof文件加載可能有兩種情況如下:

aof文件開頭是rdb的格式, 先加載 rdb內容再加載剩餘的 aof。

aof文件開頭不是rdb的格式,直接以aof格式加載整個文件。

三種持久化方案對比

RDB

優點

RDB 是一個非常緊湊(compact)的文件,體積小,傳輸速度快,適合災備。

RDB 可以最大化 Redis 的性能:父進程在保存 RDB 文件時唯一要做的就是 fork 出一個子進程,然後這個子進程就會處理接下來的所有保存工作,父進程無須執行任何磁盤 I/O 操作。

RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快很多。

缺點

RDB 丟數據將會丟掉兩次持久化之間的所有數據~

當redis中數據集比較大時候,RDB由於RDB方式需要對數據進行完成拷貝並生成快照文件,fork的子進程會耗CPU,並且數據越大,RDB快照生成會越耗時。

RDB文件是特定的格式,閱讀性差,由於格式固定,並且多版本之間存在不兼容情況。很難受~

AOF

優點

數據更完整,秒級數據丟失(取決於設置fsync策略)

兼容性較高,由於是基於redis通訊協議而形成的命令追加方式,無論何種版本的redis都兼容,再者aof文件是明文的,可閱讀性較好。

缺點

數據文件體積較大,即使有重寫機制,但是在相同的數據集情況下,AOF文件通常比RDB文件大。

相對RDB方式,AOF速度慢於RDB,並且在數據量大時候,恢復速度AOF速度也是慢於RDB。

由於頻繁地將命令同步到文件中,AOF持久化對性能的影響相對RDB較大,但是對於我們來說是可以接受的。

混合持久化

優點

混合持久化結合了RDB持久化 和 AOF 持久化的優點, 由於絕大部分都是RDB格式,加載速度快,同時結合AOF,增量的數據以AOF方式保存了,數據更少的丟失。

缺點

由於前部分是RDB格式,閱讀性較差,兼容性差,一旦開啟了混合持久化,4.0 版本之前的redis 都不認識這種aof文件~ 。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

您可能也會喜歡…