你說你精通Redis,你看過持久化的配置嗎?
今天讓我們從理論和配置兩個層面來揭開Redis
持久化的神秘面紗。
所謂持久化可以簡單理解為將記憶體中的資料儲存到硬碟上儲存的過程。持久化之後的資料在系統重啟或者當機之後依然可以進行訪問,保證了資料的安全性。
Redis
有兩種持久化方案,一種是快照方式(SNAPSHOTTING
),簡稱RDB
;一種是隻追加模式(APPEND ONLY MODE
),稱為AOF。接下來讓我們分別瞭解一下它們的使用與注意事項。
RDB
RDB
為Redis DataBase
的縮寫,是 Redis
預設的持久化方案。它能夠在指定的時間間隔內將記憶體資料集快照(snapshot
)寫入磁碟,恢復時將快照檔案( dump.rdb
)讀回記憶體。
我們先來扒一下配置檔案中的SNAPSHOTTING
:
配置檔案
save <seconds> <changes>
在給定的秒數內,如果對資料庫執行的寫入運算元達到設定的值,則將資料同步到資料檔案。支援多個條件配合,Redis
預設配置檔案中提供了三個條件:
save 900 1 //900s內有1個更改
save 300 10 //300s內有10個更改
save 60 10000 //60s內有10000次更改
注意:若不想用RDB
方案,可以把 save ""
的註釋開啟,上邊三個註釋掉。
stop-writes-on-bgsave-error yes
當bgsave
出現錯誤時,Redis
是否停止執行寫命令;
如果為 yes
,則當硬碟出現問題時,Redis
將停止接受寫入操作,這樣我們可以及時發現,避免資料的大量丟失;如果為 no
,則Redis
無視bgsave
的錯誤繼續執行寫命令。
如果已經設定了對
Redis
伺服器的正確監視和永續性,即採用了其他手段發現和控制資料完整性,可能希望禁用此功能,以便即使在磁碟、許可權等方面出現問題時,Redis
仍能正常工作。
注意:如果後臺儲存過程將再次開始工作,Redis
將自動允許再次寫入。
rdbcompression yes
指定儲存到本地資料庫時是否壓縮(Redis
採用LZF
壓縮)資料,預設為yes
。如果為了節省CPU
時間,可以關閉該選項,但會導致資料庫檔案變得巨大。
rdbchecksum yes
從RDB
版本5
開始,在儲存快照後,還可以使用CRC64
演算法來進行資料校驗,CRC64
校驗放在檔案的末尾。開啟之後,儲存和載入RDB
檔案時會增加大約10%
的效能消耗,如果希望獲取到最大的效能提升,可以關閉此功能。
禁用校驗和建立的RDB
檔案的校驗和為零,這將告訴載入程式碼跳過檢查。
dbfilename dump.rdb
指定本地資料庫檔名,重啟之後自動載入進記憶體,手動執行save
命令的話即刻生效。
大坑請注意:
flushall
、shutdown
命令都會清空並提交至dump.rdb
dir ./
指定本地資料庫存放目錄。
理論
工作方式
當 Redis
需要儲存dump.rdb
檔案時,它會呼叫系統函式fork()
,建立一個子程式(與主程式完全一致);子程式將資料集寫入臨時檔案 RDB
中;當子程式完成對新 RDB
檔案的寫入時,Redis
用新RDB
檔案替換原來的RDB
檔案,並刪除舊的RDB
檔案。
這種工作方式使得 Redis
可以從寫時複製(copy-on-write
)機制中獲益。
如何觸發RDB快照
配置檔案中預設的快照配置; 命令 save
(阻塞, 只管儲存快照,其他的等待)或者是bgsave
(非同步)命令,快照同時還可以響應客戶端命令;執行 flushall
命令,清空資料庫所有資料,意義不大;執行 shutdown
命令,保證伺服器正常關閉且不丟失任何資料,意義也不大。
透過RDB檔案恢復資料
在實際開發中,一般會考慮到物理機硬碟損壞的情況,所以我們會選擇備份dump.rdb
檔案。將備份的dump.rdb
檔案複製到redis
的安裝目錄的bin
目錄下,重啟redis
服務即可。
優點
RDB
是一個非常緊湊的檔案,非常適用於資料集的備份;RDB
是一個緊湊的單一檔案,很方便傳送到另一個遠端資料中心或者亞馬遜的S3(可能加密),非常適用於災難恢復;Redis
的主程式不進行I/O
操作,確保了極高的效能;適合大規模資料的恢復,對於資料的完整性和一致性要求不高的話, RDB
比AOF
方式更加高效。
缺點
在 Redis
意外當機時,你可能會丟失幾分鐘的資料;RDB
需要經常fork
子程式來儲存資料集到硬碟上,當資料集比較大的時候,fork
的過程是非常耗時的,可能會導致Redis
在一些毫秒級內不能響應客戶端的請求。如果資料集巨大並且CPU
效能不是很好的情況下,這種情況會持續1秒;AOF
也需要fork
,但是可以調節重寫日誌檔案的頻率來提高資料集的耐久度。
AOF
為了解決RDB
方式在當機時丟失資料過多的問題,從1.1
版本開始,Redis
增加了一種durable
的持久化方式:AOF
。
AOF
是Append Only File
的縮寫,預設不開啟。AOF
以日誌的形式來記錄每個寫操作,只允許追加檔案但不可以改寫檔案,當伺服器重啟的時候會重新執行這些命令來恢復原始的資料。
我們再來看一下配置檔案中的APPEND ONLY MODE
:
配置檔案
appendonly no
預設為關閉狀態,改為yes
開啟持久化。AOF
和RDB
可以同時啟用而不會出現問題。
appendfilename "appendonly.aof"
檔案預設名稱,啟動即建立。載入先於dump.rdb
檔案
appendfsync
同步策略:系統函式fsync()
告訴作業系統在磁碟上實際寫入資料。Redis
支援三種不同的模式
appendfsync always //每次發生資料變更會被立即記錄到磁碟,效能較差但資料完整性比較好
appendfsync everysec //預設推薦,非同步操作,每秒記錄,如果當機,有1秒內資料丟失
appendfsync no //不同步,只有在作業系統需要時在重新整理資料
要想了解接下來的配置內容,先得說一下“日誌重寫”的原理:
重寫
由於AOF
採用的是將命令追加到檔案末尾的方式,所以隨著寫入命令的不斷增加,AOF
檔案的體積會變得越來越大。為避免出現此種情況,新增了重寫機制:可以在不打斷服務客戶端的情況下,對AOF
檔案進行重建(rebuild
)。
重寫觸發: 透過執行bgrewriteaof
命令,可以生成一個新的AOF
檔案,該檔案包含重建當前資料集所需的最少命令。Redis 2.2
需手動執行該命令,Redis 2.4
則可以透過修改配置檔案的方式自動觸發(配置在下邊涉及)。
重寫原理:
Redis
執行系統函式fork()
,建立一個子程式(與主程式完全一致);子程式開始將新 AOF
檔案的內容寫入到臨時檔案;對於所有新執行的寫入命令,父程式一邊將它們累積到一個記憶體快取中,一邊將這些改動追加到現有 AOF
檔案的末尾,這樣即使在重寫的中途發生停機,現有的AOF
檔案也是安全的;當子程式完成重寫工作時,它給父程式傳送一個訊號,父程式在接收到訊號之後,將記憶體快取中的所有資料追加到新 AOF
檔案的末尾。Redis
原子地用新檔案替換舊檔案,之後所有命令都會直接追加到新AOF
檔案的末尾。
no-appendfsync-on-rewrite no
當我們同時執行主程式的寫操作和子程式的重寫操作時,兩者都會操作磁碟,而重寫往往會涉及到大量的磁碟操作,這樣就會造成主程式在寫aof
檔案的時候出現阻塞的情形。
為了解決這個問題,no-appendfsync-on-rewrite
引數出場了。
如果該引數設定為 no
,是最安全的方式,不會丟失資料,但是要忍受阻塞的問題;如果設定為 yes
,這就相當於將appendfsync
設定為no
,這說明並沒有執行磁碟操作,只是寫入了緩衝區。因此這樣並不會造成阻塞(因為沒有競爭磁碟),但是如果這個時候redis
掛掉,就會丟失資料。丟失多少資料呢?在linux
的作業系統的預設設定下,最多會丟失30s的資料。
因此,如果應用系統無法忍受延遲,而可以容忍少量的資料丟失,則設定為yes
;如果應用系統無法忍受資料丟失,則設定為no
。
auto-aof-rewrite-percentage 100
重寫百分比,預設為上次重寫後aof
檔案大小的一倍。
auto-aof-rewrite-min-size 64mb
重寫觸發的最小值:64mb。
根據auto-aof-rewrite-min-size
和auto-aof-rewrite-percentage
引數確定自動觸發時機。Redis
會記錄上次重寫時的AOF
大小,預設配置是當AOF
檔案大小是上次rewrite
後大小的一倍且檔案大於64M
時觸發。
大型網際網路公司一般都是
3G
起步
aof-load-truncated yes
當AOF
檔案被截斷時,即AOF
檔案的最後命令不完整,如果此時啟動Redis
,會將AOF
資料載入回記憶體,此時便會出現問題。
yes:載入一個截斷的 AOF
,Redis
伺服器開始發出日誌,通知使用者該事件;no:伺服器將中止並出現錯誤,拒絕啟動。
當我們得知AOF
檔案報錯時,可以用以下方法來修復出錯的 AOF
檔案:
為現有的
AOF
檔案建立一個備份;使用
Redis
附帶的redis-check-aof
命令,對原來的AOF
檔案進行修復;redis-check-aof –fix
redis-check-aof --fix appendonly.aof
修復命令,殺光不符合規範的語法(可選)使用
diff -u
對比修復後的AOF
檔案和原始AOF
檔案的備份,檢視兩個檔案之間的不同之處;重啟
Redis
伺服器,等待伺服器載入修復後的AOF
檔案,並進行資料恢復。
aof-use-rdb-preamble yes
在重寫AOF
檔案時,Redis
能夠在AOF
檔案中使用RDB
前導,以加快重寫和恢復速度。啟用此選項後,重寫的AOF
檔案由兩個不同的節組成:RDB file
、AOF tail
載入Redis
時,會識別AOF
檔案以Redis字串開頭,並載入帶字首的RDB
檔案,然後繼續載入AOF
尾部。
理論
優點
資料的完整性和一致性更高, AOF
的持久化透過使用不同的策略,最多丟失1秒的資料;AOF
檔案是一個只進行追加的日誌檔案,不需要寫入seek
;Redis
可以在AOF
檔案體積變得過大時,自動地在後臺對AOF
進行重寫,重寫操作是絕對安全的;AOF
檔案記錄的寫入操作以Redis
協議的格式儲存,容易讀懂,容易對檔案進行分析;
缺點
對於相同的資料集來說, AOF
檔案的體積通常要大於RDB
檔案的體積;根據所使用的 fsync
策略,AOF
的速度可能會慢於RDB
。
在一般情況下,每秒
fsync
的效能依然非常高,而關閉fsync
可以讓AOF
的速度和RDB
一樣快, 即使在高負荷之下也是如此。不過在處理巨大的寫入載入時,RDB
可以提供更有保證的最大延遲時間(latency
)。
對比與總結
如何選擇使用哪種持久化方式?
一般來說,如果想達到足以媲美 PostgreSQL
的資料安全性,應該同時使用兩種持久化功能。
如果非常關心資料,但仍然可以承受數分鐘以內的資料丟失,那麼可以只使用 RDB
持久化。
由於AOF持久化的實時性更好,即當程式意外退出時丟失的資料更少,因此AOF
是目前主流的持久化方式。
有很多使用者都只使用AOF
持久化,但我們並不推薦這種方式:因為定時生成 RDB
快照(snapshot
)非常便於進行資料庫備份,並且 RDB
恢復資料集的速度也要比 AOF
恢復的速度要快。
AOF和RDB之間的相互作用
在版本號大於等於 2.4
的 Redis
中,BGSAVE
執行的過程中,不可以執行 BGREWRITEAOF
。反過來說,在 BGREWRITEAOF
執行的過程中,也不可以執行 BGSAVE
。這可以防止兩個 Redis
後臺程式同時對磁碟進行大量的I/O
操作。
如果 BGSAVE
正在執行,並且使用者顯示地呼叫 BGREWRITEAOF
命令,那麼伺服器將向使用者回覆一個 OK
狀態, 並告知使用者BGREWRITEAOF
已經被預定執行:一旦 BGSAVE
執行完畢,BGREWRITEAOF
就會正式開始。
當 Redis
啟動時,如果 RDB
持久化和 AOF
持久化都被開啟了, 那麼程式會優先使用 AOF
檔案來恢復資料集,因為 AOF
檔案所儲存的資料通常是最完整的。
備份redis資料
建立一個定期任務( cron job
),每小時將一個RDB
檔案備份到一個資料夾,並且每天將一個RDB
檔案備份到另一個資料夾;確保快照的備份都帶有相應的日期和時間資訊,每次執行定期任務指令碼時,使用 find
命令來刪除過期的快照;至少每天一次,將 RDB
備份到你的資料中心之外,或者至少是備份到你執行Redis
伺服器的物理機器之外。
效能建議
在實際應用時,因為RDB
檔案只用作後備用途,建議只在slave
上持久化RDB
檔案,而且只需要15分鐘備份一次就夠了,只保留save 900 1
這條規則。
如果開啟AOF
,好處是在最惡劣情況下也只會丟失不超過2秒資料,啟動指令碼較簡單隻load
自己的AOF
檔案就可以了。代價一是帶來了持續的IO
,二是AOF rewrite
的最後將rewrite
過程中產生的新資料寫到新檔案造成的阻塞幾乎是不可避免的。
只要硬碟許可,應該儘量減少AOF rewrite
的頻率,AOF
重寫的基礎大小預設值64M
太小了,可以設定到5G
以上。預設超過原大小的100%時重寫可以改到適當的數值。
如果不開啟AOF
,僅靠Master-Slave Replication
實現高可用性也可以。能省掉一大筆IO
,也減少了rewrite
時帶來的系統波動。代價是如果Master/Slave
同時倒掉,會丟失十幾分鐘的資料,啟動指令碼也要比較兩個Master/Slave
中的RDB
檔案,載入較新的那個。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024420/viewspace-2924359/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Redis的持久化機制你學會了嗎Redis持久化
- 你有用過table佈局嗎?說說你的感受
- 你有開發過彈幕嗎?知道它的原理嗎?說說看
- 你有使用過JWT嗎?說說你對它的理解JWT
- 你對Redis持久化了解多少?一篇文章讓你明白Redis持久化Redis持久化
- 你有聽說過“分詞”嗎?說說你對它的理解分詞
- 你有開發過chrome外掛嗎?說說你的開發過程Chrome
- 你有用過彈性佈局嗎?說說你對它的理解
- 天天在用Redis,持久化方案你又知道哪些?Redis持久化
- 你不是說你會Aop嗎?
- 你有沒有看過哪些開源專案的原始碼?說說你看原始碼的流程原始碼
- 一文讓你明白Redis持久化(RDB、AOF)Redis持久化
- 你有用過HTML5中的datalist標籤嗎?說說你對它的理解HTML
- 面試官:你說你精通 Docker,那你來詳細說說 Dockerfile 吧面試Docker
- 你能說說你理解的資料庫規範嗎?資料庫
- 你說你學不動啦,看 Redux 作者怎麼說?Redux
- 你有用過clip-path嗎?說說你對它的理解和它都有哪些運用場景?
- 你知道時間四象限嗎?說說你對它的理解
- 你有自己寫過爬蟲的程式嗎?說說你對爬蟲和反爬蟲的理解?爬蟲
- redis之 Redis持久化配置Redis持久化
- 一文帶你深入瞭解 Redis 的持久化方式及其原理Redis持久化
- 你有使用過figure標籤嗎?說說你對它的認識,有哪些應用場景?
- 你有使用過2k屏或4k屏嗎?說說你對它們的理解
- 深度介紹:? 你聽說過原生 HTML 元件嗎?HTML元件
- 你瞭解什麼是微前端嗎?說說你對它的理解前端
- 手機好像在“監聽”你說話,你有過這種恐慌嗎?
- 你所在的公司裡的專案有用過敏捷開發嗎?請說說你對敏捷開發的理解敏捷
- 面試官問:如果讓你寫一個配置中心,說說你的設計思路? 不要慌,看這個!面試
- 業務部門說數字化系統你看著辦,涼拌嗎?
- 對於5G的到來,你是怎麼看的?說說你的想法
- 你見過Python的GIL嗎Python
- 你踩過flutter的坑嗎Flutter
- Redis持久化及其配置Redis持久化
- 你有使用過FileReader嗎?說說它有哪些應用場景?
- 你知道什麼是CSS-in-JS嗎?說說你對它的瞭解CSSJS
- 【大廠面試06期】談一談你對Redis持久化的理解?面試Redis持久化
- 看了此文,你還敢說你懂了Javascript運算子嗎JavaScript
- 你有使用過ExtJs嗎?說說它的優缺點是什麼?JS