有學習的小伙伴可以一起討論,微信 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