Redis持久化-深入理解AOF,RDB
生活随笔
收集整理的這篇文章主要介紹了
Redis持久化-深入理解AOF,RDB
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
持久化
- Redis數據全部在內存中,如果宕機,數據必然丟失,因此必須有一種機制保證Redis數據不會因為故障丟失,這就是Redis的持久化機制
- 持久化方式兩種:AOF,RDB,如下圖
- RDB快照模式是一次全量備份,是內存數據的二進制序列化形式,存儲緊湊
- AOF日志方式是連續增量的備份。是內存數據修改指令的記錄文本。AOF日志長期運行下來會異常龐大,Redis重啟后加載AOF日志會很慢需要定期重寫AOF日志。
RDB快照原理
- Redis單線程,需要同時負責N個客戶端套接字讀寫,內存數據結構邏輯讀寫,定時任務處理(上一節中說明),現在還需要內存快照,而且RDB是必須進行IO操作,此處IO操作是不能用底層select的多路復用。
- 以上如果都是單線程完成那么肯會有兩個問題:
- 第一RDB的IO操作的時候回嚴重拖慢服務器性能。因為需要一邊IO操作,一邊響應客戶端socket
- 第二IO持久化同時,內存還在修改,比如大型hash結構,持久化一半修改了怎么處理?
- Redis使用操作系統的多進程COW(Copy on write) 機制來實現快照持久化。
fork多進程
- Redis在持久化時候會調用glibc函數,fork產生一個子進程,持久化是由子進程完成,父進程處理客戶端請求。
- 子進程產生和父進程共享內存中代碼段與數據段,這是linux操作系統機制,為節約內存,可以盡可能讓他們共享,分離瞬間內存增長幾乎不變。
- 用如下偽代碼來說明fork過程,fork時候在父進程中返回子進程pid,子進程返回0,資源不足返回error。
子進程持久化流程
-
fork的模式解決了上文中第一個問題IO高效性問題,那么第二個問題如何解決
-
子進程在做數據RDB時候,不會修改現有內存結構,只對據結構進行遍歷讀取。父進程必須響應客戶端,修改內存數據。
-
這個時候才是使用操作系統的copy on write 機制的時候,在fork之后,子進程就認為當前的內存中所有數據都算做此次需要RDB到磁盤的快照,而一旦父進程在此期間需要修改某個數據段,會將共享的當前數據段分離出來,單做現在最新的內存數據,而老的數據當老版本的數據。這時候子進程的相應的數據段頁面是不會變化的,還是fork瞬間的那個版本。如下示意圖。
-
如上圖示意,隨著父進程的修改操作越多,只會COW出更多數據頁而已,占用部分內存,但是也不可能超過原內存2倍(不可能所有頁都在修改)。另外Redis冷數據占比更大,所以Redis實例中被COW的數據頁只有一小部分而已。每個頁大小4KB,一個Redis實例一般有成千上萬個頁面。
-
子進程沒有因為數據變化影響,他們看到內存中數據就是fork產生的瞬間的那個內存中的所有數據,我們將這瞬間的數據看成是一個SNASHOP,所以RDB也叫快照的原因。
AOF原理
- AOF日志存儲的是Redis服務器的順序指令執行序列,AOF日志只記錄內存進行修改的指令記錄
- 例如有一份AOF日志記錄了Redis實例從創建以來的所有修改性指令,那么就可以通過對一個空Redis實例順序執行所有指令的方式來復刻當前Redis的狀態。
- Redis收到客戶端指令,先進行校驗,邏輯處理,沒有問題,在存儲AOF日志。先執行在存盤。
- 缺點,AOF日志隨著Redis不斷運行逐漸變大,加入宕機,加載AOF文件可能需要非常久時間,期間無法對外提供服務。
AOF重寫
- Redis提供了bgrewriteaof指令對AOF日志瘦身。原理如下:
- fork一個子進程對內存進行遍歷,轉換成一些列Redis的操作指令例如set, hset等,重寫序列化到新的AOF文件中
- 完成存量的AOF之后,在操作期間的增量AOF日志追加到新的AOF日志文件中,然后替代原有AOF文件。
fsync
- 還回歸到IO操作的問題上,在AOF日志寫入時候,實際上是將內容寫到內核為文件描述符分配的的一個內存緩沖區中。然后內核在異步將數據刷回磁盤,這時候宕機,AOF日志可能丟失
- Linux的glibc提供了fsync(int fd)函數可以指定文件的內容強制從內核緩沖區刷新到磁盤。Redis調用fsync就可以保證不丟失,但是IO一次很慢,每次一條命令都一次IO操作性能會很受影響。
- Redis提供兩種策略:
- 一個永不主動調用fsync,讓系統決定何時同步磁盤,非安全性的操作
- 另一個每個指令都調用fsync一次,會導致Redis延遲變得異常大,影響效率,不推薦
生產做法
- 快照是通過開啟子進程方式進行,他比較消耗資源的操作
- 遍歷整個內存,大塊寫磁盤家中系統負載
- AOF的fsync是耗時的IO操作,會降低Redis性能,同時頻繁IO增加系統負擔。
- 利用從節點進行持久化,在備份節點沒有來自客戶端壓力,操作系統資源充沛,問題在于需要保證從節點的數據完整性,例如異地多活導致的網絡分區,造成數據延遲,會導致一部分數據延遲此時持久化就丟了這部分數據量。應該增加數據監控,保證完了暢通或者能快速恢復
Redis4.0 混合持久化
- 重啟Redis時候,很少使用RDB恢復,因為會丟失大量數據。我們通常用AOF回放,但是AOF回放啟動時候加載太慢,導致啟動時間變長。
- Redis4.0 解決了這個問題,兼具AOF,RDB的長處-----混合持久化
- 將RDB文件的內容與RDB之后的增量修改AOF文件保存在一起
- 此處AOF日志不是全量日志,而是RDB結束后的AOF日志信息,這樣日志量就少太多
- Redis重啟后,先加載Rdb內容,在回放AOF日志,可以完全替代之前的AOF全量,重啟效率增加
- 如下圖。
上一篇:Redis高效性探索–管道
下一篇:Redis–事務
總結
以上是生活随笔為你收集整理的Redis持久化-深入理解AOF,RDB的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ki67正常指标是多少
- 下一篇: Redis高效性探索--管道