redis持久化的認識和使用注意點


 有學習的小伙伴可以一起討論,微信 15321502296

        持久化

redis支持rdb和aof 倆種持久化機制,持久化功能有效地避免因進程退出造成的數據丟失問題,當下重啟時利用之前持久化的文件即可實現數據恢復。理解掌握持久化機制對於redis運維非常重要。

 

AOF

持久化:避免進程退出而造成數據丟失,瑕疵重啟時利用持久化文件實現·數據恢復

RDB

把當前的進程數據生成快照保存到硬盤的過程,有手動觸發,和自動觸發

手動觸發

分別對應save bgsave 命令

 阻塞當前redis,直到rdb過程完成位置

bgsave : redis過程執行fork操作創建子進程,rdb持久化過程有子進程負責,完成自動退出。

 

自動觸發  夜間執行

save   m  n

 四種情況

1、m秒內數據集存在n次的修改時,自動觸發bgsave

 2、如果從節點執行全量操作,主節點自動執行bgsave,形成RDB的文件發給其他節點

3、執行 debug reload命令重新加載redis時,也會自動觸發save操作

4、執行shtudown時,如果AOF持久化沒有開啟,則自動執行bgsave

 

bgsave    全量復制

 lastsave   獲取最后一次生成RDB的時間

info persistence統計時間

 

rdis自動觸發的過程

1、判斷當前是否存在rdb文件

2、選擇rdb作自動觸發時,執行fork操作會產生子進程,會阻塞

可以通過 info stats命令查看 latest_fork_usec  獲取最近fork的耗時,單位為微妙

3、父進程forke完成之后,bgsave命令返回 “Backgroup  saving started”信息,並不在阻塞父進程,可以進行響應其他命令。

4、父進程一直執行其他響應,子進程生成rdb文件(臨時快照文件),完成對原有文件進行原子替換。執行lastsave命令可以獲取最后一次生成rdb的時間,對應info統計的 rdb_last_save_time選項

5、子進程發送信號給父進程,表示完成,父進程更新統計信息。

 

RDB文件的三種處理

1、配置文件

在壓縮包下 可以在redis.conf下修改

查找rdb

可以修改文件名

和文件路徑

重啟生效

 

2、命令修改config set 生成文件名跟路徑,

config dbfilename 名字+.rdb

默認保存在dump.rdb 的二進制文件里面

3、lzf算法進行壓縮   特別消耗cpu

config set rdbcompression(yes | no)  默認為開啟

動態進行修改

 

RDB的優缺點

 

優點

1、RDB是一個緊湊壓縮的二進制文件,代表的實在某個時間的數據快照。 非常適合 備份,全量復制。比如數據丟失可以使用rdb 進行數據恢復

2、redis加載RDB恢復數據速度快於aof

 

缺點:

1、RDB數據沒辦法實現實時的持久化/秒級的持久化

2、rdb文件使用特定的二進制格式保存,存在老版本redis無法兼容新版本redis格式的問題

針對rdb不適合實時持久化的問題,redis提供了 AOF持久化方式來解決

 

 

 

AOF(append only file)持久化

以獨立日至的方式記錄每次寫命令,重啟時再重新執行AOF文件中的命令,恢復數據、

主要作用是: 解決了數據持久化的實時性。

vim redis.conf

 

aof使用的流程:

1、append 命令寫入 aof_buf(緩沖區)

2、sync 同步到緩沖區,根據對應的策略,向磁盤中同步

3、rewirte 重寫功能     對AOF文件進行重寫,打到壓縮的目的

4、load  重新加載,當服務器重啟時,可以加載AOF文件進行數據恢復

appensync

AOF像磁盤同步的三種策略

always  :懂事

命令寫入aof buf 后條用系統fsync操作同步到AOF文件,fsync完成后線程返回

一般不采用 always

everysec  :每次

命令寫入aof——buf后條用一同write操作,write完成后線程返回,fsync同步文件操作由

專門線程每秒調用一次,寫入磁盤

(一般建議選這個,數據性安全的平衡)

no :不

命令寫入aof——buf后調用系統write操作,不對AOF文件做fsync同步,同步硬盤操作有操作系統負責、通常同步周期最長30秒(對線上不采用no)

用文本 格式 是兼容性問題

注意

rsync : 針對單個文件操作,做強制硬盤同步,fsync將阻塞直到寫入磁盤完成后返回,保證數據持久化:

write : 觸發延遲寫機制

重寫機制  目的是壓縮

實際上是吧redis進程內的數據轉化為寫命令同步到AOF

文件的該過程

重寫后文件變小的原因

1、進程內已經超時的數據不在寫入文件

2、舊的AOF文件含有無效命令。重寫使用進程內數據直接和生成,這樣新的的AOF文件愛只保留最終數據的寫入命令

3、多條寫入命令可以合並成一個

為了防止多條命令過大造成客戶端緩沖溢出,對於list、set、hash、zset等類型操作,以64各元素為界限

 

AOF重寫降低了文件占用空間,更小的AOF文件可以更快地被redis加載

AOF觸發方式

手動觸發  :直接調用 bgrewriteaof命令

自動觸發    根據

 auto-aof-rewrite-min-size 64MB  : 表示AOF重寫文件最小的體積,默認64MB

suto-aof-rewrite-percentage   : 代表 AOF文件空間和上次重寫后文件空間的比值

參數確定自動觸發時機

 

 

AOF持久化的過程 :

 

1、執行AOF請求命令

2、會把任務交給一個進程 父進程

父進程需要通過 fork生成 一個子進程來實現自己下級任務

3、緩沖區     和rewrite 重寫   產生AOF文件 和 新文件

4、然后父進程通過aof 實行   壓縮的命令與子進程共同生成一個新的文件,並且合並

然后刪除掉原來的舊文件 寫入新的緩存文件。(覆蓋、替換、均可)

5、子進程返回父進程完成任務的信息

查看信息  info persistennce

AOF重啟加載

1、重啟完成redis

2、判斷是否開啟

3、判斷是否存在RDB文件

4、如果存在則執行,並且啟動成功,如果不存在,則啟動失敗。執行第5 步

5、判斷AOF文件是否存在

6、如果存在則執行,啟動成功

問題定位於優化

持久化文件的優化

fork操作 :

fork  耗時時間問題定位

如何改善

1、優先使用物理機 或者高效操作的虛擬化技術,避免使用xen

2、控制redis實例最大可用內存,fork耗時跟內存量成正比,線上建議每個redis實例內控制在10GB左右

3、合理配置linux內存分配策略,避免物理村村不足導致fork失敗

4、降低fork操作的頻率,如適度放寬AOF自動觸發時機,避免不必要的全量復制等

CPU

(1)、開銷分析 子進程負責吧進程內的數據分批寫入文件,這個過程屬於cpu秘籍操作,通常子進程對單核

(2)cpu消耗優化 : redis是cpu密集型服務,不要做綁定單核cpu操作

內存

硬盤

 

 

 

fork耗時問題定位:

正常耗時是每GB20毫秒左右

如何改善fork操作的耗時:

1)優先使用物理機或者高效支持fork操作的虛擬化技術,避免使用Xen。

2)控制Redis實例最大可用內存,fork耗時跟內存量成正比,線上建議每個Redis實例內存控制在10GB以內。

3)合理配置Linux內存分配策略,避免物理內存不足導致fork失敗。

4)降低fork操作的頻率,如適度放寬AOF自動觸發時機,避免不必要的全量復制等。

 

子進程的開銷與監控和優化:

子進程負責AOF或者RDB文件的重寫,它的運行過程主要涉及CPU、內存、硬盤三部分的消耗。

1.·CPU開銷分析。

子進程負責把進程內的數據分批寫入文件,這個過程屬於CPU密集操作,通常子進程對單核CPU利用率接近90%.

·CPU消耗優化。

Redis是CPU密集型服務,不要做綁定單核CPU操作。

由於子進程非常消耗CPU,會和父進程產生單核資源競爭。 不要和其他CPU密集型服務部署在一起,造成CPU過度競爭。

如果部署多個Redis實例,盡量保證同一時刻只有一個子進程執行。

2內存

·內存消耗分析。子進程通過fork操作產生,占用內存大小等同於父進程,理論上需要兩倍的內存來完成持久化操作,但Linux有寫時復制機制(copy-on-write)。父子進程會共享相同的物理內存頁,當父進程處理寫請求時會把要修改的頁創建副本,而子進程在fork操作過程中共享整個父進程內存快照。

運維提示

編寫shell腳本根據Redis日志可快速定位子進程重寫期間內存過度消耗情況。

內存消耗優化:

1)同CPU優化一樣,如果部署多個Redis實例,盡量保證同一時刻只有一個子進程在工作。

2)避免在大量寫入時做子進程重寫操作,這樣將導致父進程維護大量頁副本,造成內存消耗。

Linux kernel在2.6.38內核增加了Transparent Huge Pages(THP),支持huge page(2MB)的頁分配,默認開啟。當開啟時可以降低fork創建子進程的速度,但執行fork之后,如果開啟THP,復制頁單位從原來4KB變為2MB,會大幅增加重寫期間父進程內存消耗。建議設置“sudo echo never>/sys/kernel/mm/transparent_hugepage/enabled”關閉THP

3硬盤 ·

硬盤開銷分析。子進程主要職責是把AOF或者RDB文件寫入硬盤持久化。勢必造成硬盤寫入壓力。根據Redis重寫AOF/RDB的數據量,結合系統工具如sar、iostat、iotop等,可分析出重寫期間硬盤負載情況。 ·硬盤開銷優化。優化方法

a)不要和其他高硬盤負載的服務部署在一起。如:存儲服務、消息隊列服務等。

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

c)當開啟AOF功能的Redis用於高流量寫入場景時,如果使用普通機械磁盤,寫入吞吐一般在100MB/s左右,這時Redis實例的瓶頸主要在AOF同步硬盤上。

d)對於單機配置多個Redis實例的情況,可以配置不同實例分盤存儲AOF文件,分攤硬盤寫入壓力。

 

AOF追加阻塞

阻塞流程分析:

1)主線程負責寫入AOF緩沖區。

2)AOF線程負責每秒執行一次同步磁盤操作,並記錄最近一次同步時間。

3)主線程負責對比上次AOF同步時間: ·如果距上次同步成功時間在2秒內,主線程直接返回。

·如果距上次同步成功時間超過2秒,主線程將會阻塞,直到同步操作完成。

通過對AOF阻塞流程可以發現兩個問題:

1)everysec配置最多可能丟失2秒數據,不是1秒。

2)如果系統fsync緩慢,將會導致Redis主線程阻塞影響效率。

AOF阻塞問題定位: 1)發生AOF阻塞時,Redis輸出如下日志,用於記錄AOF fsync阻塞導致拖慢Redis服務的行為: Asynchronous AOF fsync is taking too long (disk is busy). Writing the AOF buffer

without waiting for fsync to complete, this may slow down Redis

2)每當發生AOF追加阻塞事件發生時,在info Persistence統計中,aof_delayed_fsync指標會累加,查看這個指標方便定位AOF阻塞問題。

3)AOF同步最多允許2秒的延遲,當延遲發生時說明硬盤存在高負載問題,可以通過監控工具如iotop,定位消耗硬盤IO資源的進程。

優化在上方紅字體,磁盤

 

 

 

 

 

多實例的部署

單機多實例的部署,如果同一時刻運行多個子進程,對當前系統影響將非常明顯,因此需要采取措施,把子進程進行工作隔離。

流程說明:

1。外部程序定時輪詢監控機器。

2.對於開啟aof實例的查看:(aof_current_size-aof_base_size) / aof_base_size 確認增長率

3.當增長率超過特定閥值,執行bgrewriteaof命令手動觸發當前實例的重寫。

4.運行期間循環檢查,aof_rewirte_in_progress and aof_current_rewrite_time_sec指標,確認知道aof重寫結束

5.確認實例aof重寫完成后,在堅持其他實例在repeat2-4操作。從而確保機器內每一個實例aof重寫串行化執行。

 

 

 

 

 

定義:

AOF(append only file)持久化:以獨立日志的方式記錄每次寫命令,重啟時再重新執行AOF文件中的命令達到恢復數據的目的。AOF的主要作用是解決了數據持久化的實時性,目前已經是Redis持久化的主流方式。

 

配置:

開啟AOF功能需要設置配置:appendonly yes,默認不開啟。AOF文件名通過appendfilename配置設置,默認文件名是appendonly.aof。保存路徑同RDB持久化方式一致,通過dir配置指定。AOF的工作流程操作:命令寫入(append)、文件同步(sync)、文件重寫(rewrite)、重啟加載(load)

流程如下:

一)所有的寫入命令會追加到aof_buf(緩沖區)中。

1)AOF為什么直接采用文本協議格式?可能的理由如下:

·文本協議具有很好的兼容性。

·開啟AOF后,所有寫入命令都包含追加操作,直接采用協議格式,避免了二次處理開銷。

·文本協議具有可讀性,方便直接修改和處理。

2)AOF為什么把命令追加到aof_buf中?Redis使用單線程響應命令,如果每次寫AOF文件命令都直接追加到硬盤,那么性能完全取決於當前硬盤負載。先寫入緩沖區aof_buf中,還有另一個好處,Redis可以提供多種緩沖區同步硬盤的策略,在性能和安全性方面做出平衡。

 

二)AOF緩沖區根據對應的策略向硬盤做同步操作。

Redis提供了多種AOF緩沖區同步文件策略,由參數appendfsync控制

可選配置

說明

always

命令寫入aof buf后調用系統fsync操作同步到aof文件,fsync完成后線程返回

everysync

命令寫入aof buf后調用系統write操作,write完成后線程返回,fsync同步文件操作有專門線程每秒調用一次

no

命令寫入aof buf后調用系統write操作,不對aof文件坐fsync同步,同步硬盤操作由操作系統負責,通常同步周期最長30s

系統調用write和fsync說明:

·write操作會觸發延遲寫(delayed write)機制。Linux在內核提供頁緩沖區用來提高硬盤IO性能。write操作在寫入系統緩沖區后直接返回。同步硬盤操作依賴於系統調度機制,例如:緩沖區頁空間寫滿或達到特定時間周期。同步文件之前,如果此時系統故障宕機,緩沖區內數據將丟失。

·fsync針對單個文件操作(比如AOF文件),做強制硬盤同步,fsync將阻塞直到寫入硬盤完成后返回,保證了數據持久化。

·配置為always時,每次寫入都要同步AOF文件,在一般的SATA硬盤上,Redis只能支持大約幾百TPS寫入,顯然跟Redis高性能特性背道而馳,不建議配置。

·配置為no,由於操作系統每次同步AOF文件的周期不可控,而且會加大每次同步硬盤的數據量,雖然提升了性能,但數據安全性無法保證。

·配置為everysec,是建議的同步策略,也是默認配置,做到兼顧性能和數據安全性。理論上只有在系統突然宕機的情況下丟失1秒的數據。

三)隨着AOF文件越來越大,需要定期對AOF文件進行重寫,達到壓縮的目的。

重寫后的AOF文件為什么可以變小?有如下原因:

1)進程內已經超時的數據不再寫入文件。 2)舊的AOF文件含有無效命令,如del key1、hdel key2、srem keys、set a111、set a222等。重寫使用進程內數據直接生成,這樣新的AOF文件只保留最終數據的寫入命令。

3)多條寫命令可以合並為一個,如:lpush list a、lpush list b、lpush list c可以轉化為:

lpush list a b c。為了防止單條命令過大造成客戶端緩沖區溢出,對於list、set、hash、zset等類型操作,以64個元素為界拆分為多條。 AOF重寫降低了文件占用空間,除此之外,另一個目的是:

更小的AOF文件可以更快地被Redis加載。

AOF重寫過程可以手動觸發和自動觸發:

·手動觸發:直接調用bgrewriteaof命令。

·自動觸發:根據auto-aof-rewrite-min-size和auto-aof-rewrite-percentage參數確定自動觸發時機。

·auto-aof-rewrite-min-size:表示運行AOF重寫時文件最小體積,默認為64MB。

·auto-aof-rewrite-percentage:代表當前AOF文件空間(aof_current_size)和上一次重寫后AOF文件空間(aof_base_size)的比值。 自動觸發時機=aof_current_size>auto-aof-rewrite-min-size&&(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewrite-percentage 其中aof_current_size和aof_base_size可以在info Persistence統計信息中查看。

當觸發AOF重寫時,內部做了哪些事呢?

流程說明: 1)執行AOF重寫請求。 如果當前進程正在執行AOF重寫,請求不執行並返回如下響應:

ERR Background append only file rewriting already in progress

如果當前進程正在執行bgsave操作,重寫命令延遲到bgsave完成之后再執行,返回如下響應:

Background append only file rewriting scheduled

2)父進程執行fork創建子進程,開銷等同於bgsave過程。

3.1)主進程fork操作完成后,繼續響應其他命令。所有修改命令依然寫入AOF緩沖區並根據appendfsync策略同步到硬盤,保證原有AOF機制正確性。

3.2)由於fork操作運用寫時復制技術,子進程只能共享fork操作時的內存數據。由於父進程依然響應命令,Redis使用“AOF重寫緩沖區”保存這部分新數據,防止新AOF文件生成期間丟失這部分數據。

4)子進程根據內存快照,按照命令合並規則寫入到新的AOF文件。每次批量寫入硬盤數據量由配置aof-rewrite-incremental-fsync控制,默認為32MB,防止單次刷盤數據過多造成硬盤阻塞。

5.1)新AOF文件寫入完成后,子進程發送信號給父進程,父進程更新統計信息,具體見info persistence下的aof_*相關統計。

5.2)父進程把AOF重寫緩沖區的數據寫入到新的AOF文件。

5.3)使用新AOF文件替換老文件,完成AOF重寫。

4)當Redis服務器重啟時,可以加載AOF文件進行數據恢復。

流程說明:

1)AOF持久化開啟且存在AOF文件時,優先加載AOF文件,打印如下日志:

* DB loaded from append only file: 5.841 seconds

2)AOF關閉或者AOF文件不存在時,加載RDB文件,打印如下日志:

* DB loaded from disk: 5.586 seconds

3)加載AOF/RDB文件成功后,Redis啟動成功。

4)AOF/RDB文件存在錯誤時,Redis啟動失敗並打印錯誤信息。

運維提示

對於錯誤格式的AOF文件,先進行備份,然后采用redis-check-aof--fix命令進行修復,修復后使用diff-u對比數據的差異,找出丟失的數據,有些可以人工修改補全。

AOF文件可能存在結尾不完整的情況,比如機器突然掉電導致AOF尾部文件命令寫入不全。Redis為我們提供了aof-load-truncated配置來兼容這種情況,默認開啟。加載AOF時,當遇到此問題時會忽略並繼續啟動,同時打印如下警告日志:

# !!! Warning: short read while loading the AOF file !!!

# !!! Truncating the AOF at offset 397856725 !!!

# AOF loaded anyway because aof-load-truncated is enabled

  有學習的小伙伴可以一起討論有問題可以問我,微信 15321502296


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM