1. 程式人生 > >Redis 之持久化

Redis 之持久化

目錄

一.前言

二.持久化型別之 RDB

三.持節化型別之AOF

四.Redis 持久化型別的抉擇

五.持久化的恢復

六.持久化問題的分析定位與優化

七.回顧總結


一.前言

首先,來回顧下前面文章的知識.Redis的特性之一就是讀取速度快,因為它的資料是儲存在記憶體中的,但是這樣還有它的不足之處,那就是當你伺服器斷電時或者程序產生進退後,那麼你所儲存在記憶體中的資料也就蕩然無存了,可是這樣會給我們帶來丟失資料的危險.而Redis正是考慮到了這一點,所以便有了持久化的功能.而持久化的作用正像它的名稱一樣,便是為了保持資料的持久.

Redis的持久化型別有兩種,一種是全量(RDB),一種是增量(AOF),今天這篇文章中便來聊聊這兩種型別的特性和他們的優缺點,以及我們在這兩種型別中如何做選擇.

 

二.持久化型別之 RDB

 

1.什麼事RDB?

RDB是把Redis中的完整的資料生成一個快照,然後儲存到硬碟當中,那麼這就是一個RDB檔案了,不過這個RDB檔案是一個二進位制的檔案.當你的Redis服務重啟時,它會去載入這樣的RDB檔案.其作用便是為了備份資料和恢復資料,當然它也是一個複製的媒介,對於Redis的主從複製正式利用這個檔案來完成的.

2.觸發機制

RDB的觸發方式有兩種,分別是:save(同步)和bgsave(非同步).因為save的觸發方式是同步的,那麼它會阻塞當前的Redis伺服器,直到RDB的過程完成為止,如果你的記憶體比較大的話,那麼會造成長時間的阻塞,所以這在生產環境是不建議使用的.而bgsave是非同步的,使用它時Redis的程序會執行fork操作來建立子程序,在RDB持久化的過程便交給子程序去負責了,完成後就回自動結束.對bgsave而言,它的阻塞只會發生在fork階段,時間一般較短,但也有極少的情況下,會阻塞程序.

我們還需要注意以下幾點:

1.save 可以在客戶端顯式觸發,也可以在 shutdown 時自動觸發;bgsave 可以在客戶端顯式觸發,也可以通過配置由定時任務觸發,也可以在 slave 節點觸發.

2.預設執行 shutdown 時,如果沒有開啟 AOF,則自動執行 bgsave

3.因為RDB是全量的,所以每次使用RDB的時候 RDB 檔案都是替換的.

3.RDB的優缺點

優點:

  1. RDB是緊湊壓縮的二進位制檔案,是Redis某個時間點上的資料快照,比較適合用於備份和全量複製,例如每 6 小時執行 bgsave,儲存到檔案系統之類的.
  2. Redis 載入 RDB 恢復資料遠遠快於 AOF.

缺點:

  1. 無法實現到實時持久化/秒級持久化.因為bgsave每次都要執行fork操作子程序,這是重量級操作,執行成本過高.
  2. 老版本 Redis 無法相容新版本 RDB檔案.

RDB流程圖:

 

 

三.持節化型別之AOF

1.什麼事AOF?

AOF是一獨立日誌方式記錄每次命令,其主要作用也是為了解決資料持久化的實時性,目前是Redis持久化的主流方式.

2.AOF的特性

  1. 使用AOF是需要設定配置:appendonly yes,預設是不開啟的.AOF檔名是通過appendfilename配置的,預設檔名是:appendonly.aof. 儲存的路徑和RDB方式一致,通過dir配置指定.
  2. AOF每次都是append卸乳命令,因此實時性更高.
  3. AOF其實並不是直接把資料寫入磁碟檔案中,而是寫在緩衝區(aof_bug)中,這也是為了提高寫入效率,它可以根據不同的策略(always,everysec,no)向磁碟中做同步操作.
  4. 隨著AOF寫入的檔案越來越大(因為AOF是增量的),所以需要定期對AOF進行重寫,需要進行優化,稱之為“重寫機制”,以達到壓縮的目的.

3.AOF緩衝區同步策略

AOF緩衝區同步策略,由引數 appendfsync 控制,一共3種:

1.alwayss:呼叫sync函式,操作同步到AOF檔案,直到寫入硬碟後返回,這將嚴重影響redis效能.(配置always時,每次都需要同步AOF檔案,一般的SATA硬碟,Redis只有大約幾百的TPS,顯然是與Redis高效能背道而馳的,所以不建議配置)

2.everysec:呼叫系統write 函式,寫入到快取區後,直接返回.而fsync同步檔案操作有專門的執行緒,每秒呼叫一次,推薦配置.(理論上系統宕機也就是丟失下一秒的資料)

3.no: 只執行 write OS 函式,不對AOF檔案做fsync操作同步,具體同步硬碟策略由 OS 決定,通常週期最長為30秒,不推薦,資料不安全,容易丟失資料.

4.AOF重寫機制

  1. 執行AOF重寫請求,父程序fork子程序,開銷等同於bgsave.
  2. 主程序會寫到2個緩衝區,一個是原有的 “AOF 快取區”,一個是專門為子程序準備的 “AOF 重寫緩衝區”,用來儲存部分新資料,防止新的AOF檔案生成期間丟失這部分資料.
  3. 子程序根據內脣快照,按照命令合併規則寫入到新的AOF檔案,每次寫入是批量的(寫入的資料量可配置aof-rewrite-incremental-fsync),預設是30MB,防止單次刷入的資料量過多,造成阻塞.新的AOF檔案寫入完成後,子程序會通知父程序.
  4. 父程序吧AOF重寫快取區的資料寫入新的AOF檔案.
  5. 然後使用新的AOF替換老檔案,至此完成重寫.

重寫流程圖:

 

四.Redis 持久化型別的抉擇

命令 RDB AOF
啟動優先順序
體積
恢復速度
資料安全性 丟資料 根據策略決定
輕重

 

RDB的最佳策略:

  1. 建議“關”掉RDB(這裡的關用引號,是因為對於Redis的主從複製的全量複製是要我們的主節點執行一次bgsave,然後吧RDB檔案傳給從節點來實現一個複製的過程.)
  2. 集中管理(雖然RDB是一個很重的操作,但是對於資料備份是有一定作用的,如果按天/小時這樣一個比較大的量級來備份資料,這樣RDB是一個不錯的選擇,因為RDB檔案比較小,這樣傳輸速度會比較快,對於集中管理的備份比較有優勢.
  3. 主從,從開?因為有時候需要在從節點開一下RDB,這樣可以在本地去儲存這樣一個歷史的RDB檔案,這樣有一定的優勢但是一定要控制他的力度不要是save自動生成的頻率會很頻繁,這樣的話從節點不進入Redis的讀寫,但是所有的Redis都是一個混合部署,就是單機多部署,因為RDB是一個很重的操作,可能仍然對機器本身,例如硬碟/CPU以及記憶體有一定的影響,所以要根據實際開發中的實際需求來進行設定

AOF的最佳策略

  1. “開”:快取和儲存,在大部分情況先建議開啟AOF,這樣能特別的體現出Redis的一個特點,就是可以實時持久化,並且在大部分情況下只會丟一秒資料,大部分情況下會設定每秒區重新整理磁碟.但是例如有些時候,有些快取的場景,完全使用Redis做快取的功能,其實裡面的資料丟失了,對系統並沒有任何影響,只需要下次載入的時候從資料來源重新載入進來就可以,而且它對資料來源的壓力也沒有那麼大,加入你的訪問對資料來源沒有太大的壓力,這個時候其實是可以關閉掉的.畢竟 AOF確實需要一定開銷的,寫緩衝區等都有一定的開銷的.
  2. AOF重寫集中管理:單機多部署的情況下AOF集中發生,就是產生大量的fork,但是機器的記憶體比如是16G,我們將會分配百分之六十到七十記憶體給Redis,剩餘20-30來給fork做一個操作用的空間,但是這部分空間並不是很大的,假如集中做fork,就可能出現記憶體爆滿,會出現swap的情況.
  3. everysec(每秒1是重新整理)

最佳策略:小分片,快取或者儲存,監控(硬碟,記憶體,負載,網路),足夠記憶體

 

五.持久化的恢復

RDB 和 AOF 檔案都可以用於伺服器重啟時來做資料恢復,具體恢復流程如圖:

 

六.持久化問題的分析定位與優化

Redis持久化的功能一直是影響Redis效能的高發地,這也是我們日常工作與面試中常遇到的.

1.fork操作

當Redis做 RDB 或者 AOF 重寫時,必不可少的是要進行 fork 操作,對於 大多數作業系統 來說,fork 都是一個重量級操作.雖然不會拷貝父程序所有的物理空間,但會複製父程序的空間記憶體頁表.對於 10GB 的 Redis 程序,需要複製大約 20MB 的記憶體頁表,因此 fork 操作耗時跟程序總記憶體量息息相關,如果還使用虛擬化技術,例如 Xen 虛擬機器,fork 操作會更加耗時.

對於一個 Redis 例項的 OPS 在 5 萬以上,如果 fork 操作耗時在秒級,那麼將會拖慢幾萬條命令的執行,對生產環境影響明顯.在正常情況下,fork操作的耗時應該是1GB/20ms左右,這個可以在 Info stats 統計中查詢 latest_fork_usec 指標獲取最近一次 fork 操作耗時,單位微秒.

 

優化方案:

  1. 優先使用物理機或者高效支援 fork 的虛擬化技術,避免使用 Xen.
  2. 控制 redis 例項最大可用記憶體,foek耗時跟記憶體量成正比,所以線上建議控制實力記憶體在 10GB 以內.
  3. 合理配置 Linux 記憶體分配策略,避免記憶體不足導致 fork 失敗.
  4. 降低 fork操作 的頻率,如適度放寬 AOF 自動觸發時機,避免不必要的全量複製.

2.子程序開銷和優化

fork 完畢之後,會建立子程序,子程序會負責 RDB 或者 AOF 重寫,這部分過程主要涉及到 CPU,記憶體,硬碟三個地方的優化.

1)cpu

cpu開銷分析與優化

子程序負責吧程序內的資料分批寫入檔案,這個寫入檔案的過程是 CPU 密集的過程,通常子程序對單核 CPU 利用率接近 90%. 優化方法:Redis是 CPU 密集型服務,不要繫結單核 CPU,由於子程序會非常消耗CPU,所以這樣會和父 CPU 進行競爭.同時,不要和其他 CPU 密集型服務部署在一個機器上。如果部署了多個 Redis 例項,盡力保證統一時刻只有一個子程序執行重寫工作.

2)記憶體

子程序通過 fork 操作產生,佔用記憶體大小等同於父程序,理論上需要兩倍的記憶體完成持久化操作,但 Linux 有複製機制 (copy on write ).父子程序會共享相同的實體記憶體頁,當父程序處理寫操作時,會把要修改的頁建立對應的副本,而子程序在 fork 操作過程中,共享整個父程序記憶體快照. 如果重寫過程中存在記憶體修改操作,父程序負責建立所修改記憶體頁的副本.這裡就是記憶體消耗的地方. 優化方法:和cpu一樣,如果部署多個Redis例項,儘量保證同一時刻只有一個子程序在工作;避免大量寫入時做子程序重寫操作,這樣會導致父程序維護大量的快照副本,造成記憶體消耗.

3)硬碟開銷分析

程序主要職責是將 RDB 或者 AOF 檔案寫入硬碟進行持久化,勢必造成對硬碟造成壓力,可通過工具例如 iostat,iotop 等工具分析重寫期間硬碟負載情況.

優化方法:

(a).不要和其他高硬碟負載的服務放在一臺機器上,例如 MQ,儲存服務.

(b)AOF 重寫時會消耗大量硬碟 IO,可以開啟配置 no-appendfsync-on-rewrite,預設關閉。表示在 AOF 重寫期間不做 fsync 操作.

(c)當開啟 AOF 的 Redis 在高併發場景下,如果使用普通機械硬碟,每秒的寫速率是 100MB左右,這時,Redis 的效能瓶頸在硬碟上,建議使用 SSD.

(d)對於單機配置多個 Redis 例項的情況,可以配置不同例項分盤儲存 AOF 檔案,分攤硬碟的寫入壓力.

3. AOF 追加阻塞

當開啟 AOF 持久化時,常用的同步硬碟的策略是everysec,用於平衡效能和資料安全性.對於這種方式,Redis 使用另一條執行緒每秒執行 fsync 同步硬碟.當系統資源繁忙時,將造成 Redis 主執行緒阻塞.

如圖所示:

 

從上圖中可以發現:everysec 配置最多可能丟失 2 秒資料,不是 1 秒;如果系統 fsync 緩慢,將會導致 Redis 主執行緒阻塞影響效率.

問題定位:

  1. 發生 AOF 阻塞時,會輸入日誌。用於記錄 AOF fsync 阻塞導致拖慢 Redis 服務的行為.
  2. 每當 AOF 追加阻塞事件發生時,在 info Persistence 統計中,aof_delayed_fsync 指標會累加,檢視這個指標方便定位 AOF 阻塞問題.
  3. AOF 同步最多執行 2 秒的延遲,當延遲發生時說明硬碟存在效能問題,可通過監控工具 iotop 檢視,定位消耗 IO 的程序.

4. 單機多例項部署

Redis 單執行緒架構無法充分利用多核CPU,通常的做法是一臺機器上部署多個例項,當多個例項開啟 AOF 後,彼此之間就會產生CPU 和 IO 的競爭.

解決方法:讓所有例項的 AOF 序列執行.我們通過 info Persistence 中關於 AOF 的資訊寫出 Shell 指令碼,然後序列執行例項的 AOF 持久化.

info Persistence片段度量指標表:

屬性名

屬性值
rdb_bgsave_in_progress bgsave子程序是否正在執行
rdb_current_bgsave_time_sec 當前執行bgsave的時間,-1表示未執行
aof_enabled 是否開啟AOF功能
aof_rewrite_in_progress AOF重寫子程序是否正在執行
aof_rewrite_scheduled 在bgsave結束後是否執行AOF重寫
aof_current_rewrite_time_sec 當前執行AOF重寫的時間,-1表示未執行
aof_current_size AOF檔案當前位元組數
aof_base_size AOF上次重寫rewrite位元組數

基於以上指標,可以通過外部輪詢控制AOF的重寫操作的執行,整個過程如圖:

 

七.回顧總結

本文講了 Redis 的持久化相關功能,例如持久化的型別,持久化每種型別的優缺點,Redis 持久化型別的選擇,持久化溼如何恢復的,還有持久化問題的分析定位與優化.

 

 

參考:《redis開發與運維》,《深入分散式快取》

版權宣告:尊重博主原創文章,轉載請註明出處 https://blog.csdn.net/zfy163520