日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

【Redis】Redis的持久化(備份)

作者:Mr.VK 更新時間: 2024-03-10 編程語言

【Redis】Redis的持久化(備份)

Redis的數據全部在內存里,如果突然宕機,數據就會全部丟失,因此必須有一種機制來保證Redis的數據不會因為故障而丟失,這種機制就是Redis的持久化機制。

如圖所示,Redis的持久化機制有兩種:

  • 快照(snapshotting),它是備份當前時間節點Redis在內存中的數據記錄。
  • 只追加文件(Append-OnlyFile,AOF),其作用就是當Redis執行寫命令后,在一定的條件下將執行過的寫命令依次保存在Redis的備份文件中,將來就可以依次執行那些被保存的命令恢復Redis的數據了。

在這里插入圖片描述

快照是一次全量備份,AOF日志是連續的增量備份

快照是內存數據的二進制序列化形式,在存儲上非常緊湊,而AOF日志記錄的是內存數據修改的指令記錄文本。AOF日志在長期的運行過程中會變得無比龐大,數據庫重啟時需要加載AOF日志進行指令重放,這個時間就會無比漫長,所以需要定期進行AOF重寫,給AOF日志進行瘦身。

對于快照備份,如果當前Redis的數據量大備份這個快照文件時可能造成Redis卡頓,但是它的優點是恢復和重啟速度比較快,對于AOF備份,它只是追加寫入命令,備份代價較小,所以備份一般不會造成Redis卡頓,但是恢復重啟要執行更多的命令,備份文件可能也很大。兩種備份的方式都有各自的優缺點,在Redis中快照備份是必備的,AOF備份則是可選的,當然我們也可以同時使用快照備份和AOF備份。下面我們來詳細講解它們的內容。

RDB(快照)持久化

RDB(快照)備份是Redis默認開啟的備份方式。我們打開配置文件redis.conf,可以看到以下默認配置:

################SNAPSHOTTING################
# 在900s(15分鐘)內存在1個key改變,則執行備份
save 900 1
# 在300s(6分鐘)內存在10個key改變,則執行備份
save 300 10
# 在60s(1分鐘)內存在1000個key改變,則執行備份
save 60 10000
# 后臺備份運行出錯時停止Redis的寫入命令
stop-writes-on-bgsave-error yes
# 是否壓縮備份的RDB文件
rdbcompression yes
# RDB(快照)備份文件名稱
dbfilename dump.rdb
# 是否檢驗RDB備份文件
rdbchecksum yes
# 備份文件路徑
dir ./

首先看save的三個配置:

save 900 1
save 300 10
save 60 10000

Redis會在一定情況下備份數據,配置save后面的兩個整數分別是時間(單位:s)key的改變數量。這里要考慮的是觸發備份的頻率,如果太密集了,備份就多了,會影響到系統的性能:如果很少備份,就有可能丟失數據。這是大家在配置的時候需要注意的地方。

stop-writes-on-bgsave-error yes

這個配置項是讓Redis在備份失敗時,停止寫入命令,這樣就可以讓運維或者開發者注意到發生的問題了。至于其他的配置,在注釋中也交代得比較清晰了,這里不再贅述。

RDB(快照)原理

? 我們知道Redis是單線程程序,這個線程要同時負責多個客戶端套接字的并發讀寫操作和內存數據結構的邏輯讀寫。

? 在服務線上請求的同時,Redis還需要進行內存快照,內存快照要求Redis必須進行文件IO操作,可文件IO操作不能使用多路復用API。

? 這意味著單線程在服務線上請求的同時,還要進行文件IO操作,而文件IO操作會嚴重拖累服務器的性能。

? 還有個重要的問題,為了不阻塞線上的業務,Redis就需要一邊持久化,一邊響應客戶端的請求。持久化的同時,內存數據結構還在改變,比如一個大型的hash字典正在持久化,結果一個請求過來把它給刪掉了,可是還沒持久化完呢,這該怎么辦呢?

? Redis使用操作系統的多進程COw(CopyOnWrite)機制來實現快照持久化,這個機制很有意思,也很少人知道。多進程COW也是鑒定程序員知識廣度的一個重要指標。
在這里插入圖片描述

fork(多進程)

? Redis在持久化時會調用glibc的函數fork產生一個子進程,快照持久化完全交給子進程來處理,父進程繼續處理客戶端請求。子進程剛剛產生時,它和父進程共享內存里面的代碼段和數據段。這時你可以把父子進程想象成一個連體嬰兒,它們在共享身體。這是Linux操作系統的機制,為了節約內存資源,所以盡可能讓它們共享起來。在進程分離的一瞬間,內存的增長幾乎沒有明顯變化。

? 子進程做數據持久化,不會修改現有的內存數據結構,它只是對數據結構進行遍歷讀取,然后序列化寫到磁盤中。但是父進程不一樣,它必須持續服務客戶端請求然后對內存數據結構進行不間斷的修改。

? 這個時候就會使用操作系統的COW機制來進行數據段頁面的分離。如圖所示,數據段是由很多操作系統的頁面組合而成,當父進程對其中一個頁面的數據進行修改時,會將被共享的頁面復制一份分離出來,然后對這個復制的頁面進行修改。這時子進程相應的頁面是沒有變化的,還是進程產生時那一瞬間的數據。

在這里插入圖片描述

? 隨著父進程修改操作的持續進行,越來越多的共享頁面被分離出來,內存就會持續增長,但是也不會超過原有數據內存的2倍大小。另外,Redis實例里冷數據占的比例往往是比較高的,所以很少會出現所有的頁面都被分離的情況,被分離的往往只有其中一部分頁面。每個頁面的大小只有4KB,一個Redis實例里面一般都會有成千上萬個頁面。

? 子進程因為數據沒有變化,它能看到的內存里的數據在進程產生的一瞬間就凝固了,再也不會改變,這也是為什么Redis的持久化叫"快照"的原因。接下來子進程就可以非常安心地遍歷數據,進行序列化寫磁盤了。

RDB持久化的優點 RDB持久化的缺點
1.只有一個文件dumprdb(默認文件名為dump.rdb,可自定義),方便持久化 1.可能有數據丟失,不適合對高可用要求比較高的場景在兩次RDB持久化的時間間隔中,系統一旦出現宕機則這段時間內的數據因沒有寫入磁盤都將丟失
2.容災性好,一個文件可以保存到安全的磁盤 2.由于RDB是通過Fork子進程來協助完成數據持化作的,因此,如果當數據集較大時,可能會導致整個服務器間歇性暫停服務
3.實現了性能最大化它Fork單獨子進程來完成持久化,讓主進程繼續處理命令,主進程不進行任何IO操作以而保證了Redis的高性能
4.是一個緊湊壓縮的二進制文件,Redis重啟時的加載效率比AOF持久化更高,在數據量大時更加明顯

AOF持久化

AOF備份并不是一個默認開啟的方式,它以追加寫入命令日志的方式備份,打開redis.config文件,可以看到如下內容:

################APPENDONLYMODE################
#是否使用AOF方式備份,默認為否(no),如果需要可以修改為yes
appendonly no

#AOF方式的備份文件名
appendfilename "appendonly.aof"

####AOF備份頻率####
# 代表每次寫入命令后立即追加到AOF文件中,該方式消耗資源最多,也最安全
# appendfsync always
# 代表以每秒執行1次AOE的方式備份,消耗資源較多,也有較低概率丟失數據
appendfsync everysec
# 將寫入工作交給操作系統,由操作系統來判斷緩沖區大小
# 統一寫到AOF文件中(消耗資源少,但同步頻率低,易丟數據)
# appendfsync no.....

# 當進行SNAPSHOTTING備份數據時,是否執行AOF備份方式,若為yes則停止
no-appendfsync-on-rewrite no

# 當AOF文件擴展時,文件大小按什么百分比擴展
auto-aof-rewrite-percentage 100
# 默認AOF文件最小64MB
auto-aof-rewrite-min-size 64mb
# 當通過AOF方式導入數據時,如果發現備份命令錯誤是否忽略
# 如果不忽略,遇到錯誤命令則停止恢復數據
aof-load-truncated yes

# 是否使用和RDB文件混合的方式備份,這是Redis4.0以上版本擁有的方式
aof-use-rdb-preamble yes

上述的中文注釋比較清楚,這里需要理解的是配置項appendfsyn,它存在三個選置項:alwayseverysecno,關于它們的解釋注釋中已經講解清楚了。我們需要注意的是使用always會比較消耗資源,性能也較差,但是不會丟失數據,安全度高;everysec則是每秒備份一次。

AOF日志存儲的是Redis服務器的順序指令序列,AOF日志只記錄對內存進行修改的指令記錄。

假設AOF日志記錄了自Redis實例創建以來所有的修改性指令序列,那么就可以通過對一個空的Redis實例順序執行所有的指令一一也就是“重放”,來恢復Redis當前實例的內存數據結構的狀態。

Redis會在收到客戶端修改指令后,進行參數校驗、邏輯處理,如果沒問題,就立即將該指令文本存儲到AOF日志中,也就是說,先執行指令才將日志存盤。這點不同于leveldb、hbase等存儲引擎,它們都是先存儲日志再做邏輯處理。

Redis在長期運行的過程中,AOF的日志會越來越長。如果實例宕機重啟,重放整個AOF日志會非常耗時,導致Redis長時間無法對外提供服務,所以需要對AOF日志瘦身。

Redis執行AOF持久化時會調用lushAppendOnlyFile函數,這個函數執行以下兩個工作來寫入保存。

  • write:根據條件將aof_buf中的緩存寫入AOF文件
  • save:根據條件調用fsyncfdatasync函數,將AOF文件保存到磁盤中

AOF文件以日志的形式記錄Redis服務端每一個寫、刪除操作,不包括查詢操作。記錄內容是Redis通信協議(RESP)格式的命令文本。RESP是Redis客戶端和服務端之前使用的一種通信議,RESP實現簡單、快速解析、可讀性好。

AOF重寫

Redis提供了bgrewriteaof指令用于對AOF日志進行瘦身,其原理就是開辟一個子進程對內存進行遍歷,轉換成一系列Redis的操作指令,序列化到一個新的AOF日志文件中。序列化完畢后再將操作期間發生的增量AOF日志追加到這個新的AOF日志文件中,追加完畢后就立即替代舊的AOF日志文件了,瘦身工作就完成了。
在這里插入圖片描述

fsync

AOF日志是以文件的形式存在的,當程序對AOF日志文件進行寫操作時,實際上是將內容寫到了內核為文件描述符分配的一個內存緩存中,然后內核會異步將臟數據刷回到磁盤的。

這就意味著如果機器突然宕機,AOF日志內容可能還沒有來得及完全刷到磁盤中,這個時候就會出現日志丟失。那該怎么辦?

Linux的glibc提供了fsync(intfd)函數可以將指定文件的內容強制從內核緩存刷到磁盤。只要Redis進程實時調用fsync函數就可以保證AOF日志不丟失。但是fsync是一個磁盤IO操作,它很慢!如果Redis執行一條指令就要fsync一次,那么Redis高性能的地位就不保了。

所以在生產環境的服務器中,Redis通常是每隔1s左右執行一次fsyn操作,這個1s的周期是可以配置的。這是在數據安全性和性能之間做的一個折中,在保持高性能的同時,盡可能使數據少丟失。

Redis同樣也提供了另外兩種策略,一個是永不調用fsync一讓操作系統來決定何時同步磁盤,這樣做很不安全,另一個是來一個指令就調用fsync一次一-結果導致非常慢。這兩種策略在生產環境中基本不會使用,了解一下即可。

AOF持久化的優點 AOF持久化的缺點
1.實時持久化,數據安全,AOF持久化可以配置appendfsync屬性為always,每進行一次命令操作就記錄到AOF文件中一次,這樣數據最多丟失一次(推薦并且也是默認的措施為每秒fsync一次,這種fsync策略可以兼顧速度和安全性) 1.AOF持久化文件通常比RDB持久化文件大很多
2.它通過Append模式寫文件,即使中途服務器宕機,也可以通過Redis-check-aof工具解決數據一致性問題 2.比RDB持久化啟動效率低,數據集大時較為明顯
3.AOF機制的Rewrite模式。AOF文件過大觸碰到臨界點時,Rewrite模式會被運行,重寫內存中的所有數據,從而大大縮小文件體積 3.AOF文件體積可能迅速變大,需要定期執行重寫操作來降低文件體積

運維

快照是通過開啟子進程的方式進行的,它是一個比較耗資源的操作

  1. 遍歷整個內存,大塊寫磁盤會加重系統負載
  2. AOF的fsync是一個耗時的IO操作,它會降低Redis性能,同時也會增加系統IO負擔。

所以通常Redis的主節點不會進行持久化操作,持久化操作主要在從節點進行從節點是備份節點,沒有來自客戶端請求的壓力,它的操作系統資源往往比較充沛。

但是如果出現網絡分區,從節點長期連不上主節點,就會出現數據不一致的問題,特別是在網絡分區出現的情況下,主節點一旦不小心宕機了,那么數據就會丟失,所以在生產環境下要做好實時監控工作,保證網絡暢通或者能快速修復。另外還應該再增加一個從節點以降低網絡分區的概率,只要有一個從節點數據同步正常數據也就不會輕易丟失。

RDB-AOF混合持久化

重啟Redis時,我們很少使用rdb來恢復內存狀態,因為會丟失大量數據。我們通常使用AOF日志重放,但是重放AOF日志相對于使用rdb來說要慢很多,這樣在Redis實例很大的時候,啟動需要花費很長的時間。

Redis4.0為了解決這個問題,帶來了一個新的持久化選項一混合持久化。如圖所示,將rdb文件的內容和增量的AOF日志文件存在一起。這里的AOF日志不再是全量的日志,而是自持久化開始到持久化結束的這段時間發生的增量AOF日志,通常這部分AOF日志很小。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-krqWiEVz-1692199659371)(C:\Users\HUAWEI\AppData\Roaming\Typora\typora-user-images\image-20230816231647272.png)]

于是在Redis重啟的時候,可以先加載rdb的內容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,重啟效率因此得到大幅提升。

件存在一起。這里的AOF日志不再是全量的日志,而是自持久化開始到持久化結束的這段時間發生的增量AOF日志,通常這部分AOF日志很小。

在這里插入圖片描述

于是在Redis重啟的時候,可以先加載rdb的內容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,重啟效率因此得到大幅提升。

開啟混合模式,將aof-use-rdb-preamble參數值設置為yes便可。

原文鏈接:https://blog.csdn.net/Mr_VK/article/details/132331248

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新