天天用Redis,持久化方案你又知道哪些?
來源 |碼猿技術(shù)專欄
責(zé)編 | Carol
頭圖 | CSDN 下載自視覺中國
Redis目前已經(jīng)成為主流的內(nèi)存數(shù)據(jù)庫了,但是大部分人僅僅是停留在會(huì)用的階段,你真的了解Redis內(nèi)部的工作原理嗎?
今天這篇文章將為大家介紹Redis持久化的兩種方案,文章將會(huì)從以下五個(gè)方面介紹:
什么是RDB,RDB如何實(shí)現(xiàn)持久化?
什么是AOF,AOF如何實(shí)現(xiàn)持久化?
AOF和RDB的區(qū)別。
如何重啟恢復(fù)數(shù)據(jù)?
持久化性能問題和解決方案
RDB
RDB持久化是把當(dāng)前進(jìn)程數(shù)據(jù)生成快照保存到硬盤的過程, 觸發(fā)RDB持久化過程分為手動(dòng)觸發(fā)和自動(dòng)觸發(fā)。
RDB完成后會(huì)自動(dòng)生成一個(gè)文件,保存在dir配置的指定目錄下,文件名是dbfileName指定。
Redis默認(rèn)會(huì)采用LZF算法對(duì)生成的RDB文件做壓縮處理,壓縮后的文件遠(yuǎn)遠(yuǎn)小于內(nèi)存大小,默認(rèn)開啟。
手動(dòng)觸發(fā)
手動(dòng)觸發(fā)的命令有save和bgsave。
save:該命令會(huì)阻塞Redis服務(wù)器,直到RDB的過程完成,已經(jīng)被廢棄,因此線上不建議使用。
bgsave:每次進(jìn)行RDB過程都會(huì)fork一個(gè)子進(jìn)程,由子進(jìn)程完成RDB的操作,因此阻塞只會(huì)發(fā)生在fork階段,一般時(shí)間很短。
自動(dòng)觸發(fā)
除了手動(dòng)觸發(fā)RDB,Redis服務(wù)器內(nèi)部還有如下幾個(gè)場景能夠自動(dòng)觸發(fā)RDB:
根據(jù)我們的?save m n?配置規(guī)則自動(dòng)觸發(fā)。
如果從節(jié)點(diǎn)執(zhí)行全量復(fù)制操作, 主節(jié)點(diǎn)自動(dòng)執(zhí)行bgsave生成RDB文件并發(fā)送給從節(jié)點(diǎn)。
執(zhí)行debug reload命令重新加載Redis時(shí), 也會(huì)自動(dòng)觸發(fā)save操作。
默認(rèn)情況下執(zhí)行shutdown命令時(shí), 如果沒有開啟AOF持久化功能則自動(dòng)執(zhí)行bgsave。
RDB執(zhí)行流程
RDB的主流方式就是bgsave,通過下圖我們來看看RDB的執(zhí)行流程:
?
通過上圖可以很清楚RDB的執(zhí)行流程,如下:
執(zhí)行bgsave命令后,會(huì)先判斷是否存在AOF或者RDB的子進(jìn)程,如果存在,直接返回。
父進(jìn)程fork操作創(chuàng)建一個(gè)子進(jìn)程,fork操作中父進(jìn)程會(huì)被阻塞。
fork完成后,子進(jìn)程開始根據(jù)父進(jìn)程的內(nèi)存生成臨時(shí)快照文件,完成后對(duì)原有的RDB文件進(jìn)行替換。執(zhí)行l(wèi)astsave命令可以查看最近一次的RDB時(shí)間。
子進(jìn)程完成后發(fā)送信號(hào)給父進(jìn)程,父進(jìn)程更新統(tǒng)計(jì)信息。
RDB的優(yōu)點(diǎn)
RDB是一個(gè)緊湊壓縮的二進(jìn)制文件, 代表Redis在某個(gè)時(shí)間點(diǎn)上的數(shù)據(jù)快照。非常適用于備份, 全量復(fù)制等場景。比如每6小時(shí)執(zhí)行bgsave備份,并把RDB文件拷貝到遠(yuǎn)程機(jī)器或者文件系統(tǒng)中,用于災(zāi)難恢復(fù)。
Redis加載RDB恢復(fù)數(shù)據(jù)遠(yuǎn)遠(yuǎn)快于AOF的方式。
RDB的缺點(diǎn)
RDB方式數(shù)據(jù)沒辦法做到實(shí)時(shí)持久化/秒級(jí)持久化。因?yàn)閎gsave每次運(yùn)行都要執(zhí)行fork操作創(chuàng)建子進(jìn)程,屬于重量級(jí)操作,頻繁執(zhí)行成本過高。
RDB文件使用特定二進(jìn)制格式保存, Redis版本演進(jìn)過程中有多個(gè)格式的RDB版本, 存在老版本Redis服務(wù)無法兼容新版RDB格式的問題。
AOF
AOF(append only file) 持久化:以獨(dú)立日志的方式記錄每次寫命令,重啟時(shí)再重新執(zhí)行AOF文件中的命令達(dá)到恢復(fù)數(shù)據(jù)的目的。AOF的主要作用是解決了數(shù)據(jù)持久化的實(shí)時(shí)性, 目前已經(jīng)是Redis持久化的主流方式。
如何開啟AOF
開啟AOF功能需要設(shè)置配置:appendonly yes, 默認(rèn)不開啟。AOF文件名通過appendfilename配置設(shè)置, 默認(rèn)文件名是appendonly.aof。保存路徑同RDB持久化方式一致,通過dir配置指定。
AOF整體的執(zhí)行流程
AOF執(zhí)行的流程大致分為命令寫入、文件同步、文件重寫、重啟加載四個(gè)步驟,如下圖:
從上圖大致了解了AOF的執(zhí)行流程,下面一一分析上述的四個(gè)步驟。
命令寫入
AOF命令寫入的內(nèi)容直接是文本協(xié)議格式。例如set hello world這條命 令, 在AOF緩沖區(qū)會(huì)追加如下文本:
命令寫入是直接寫入到AOF的緩沖區(qū)中,至于為什么?原因很簡單,Redis使用單線程響應(yīng)命令,如果每次寫AOF文件命令都直接追加到硬盤, 那么性能完全取決于當(dāng)前硬盤負(fù)載。先寫入緩沖區(qū)aof_buf中, 還有另一個(gè)好處, Redis可以提供多種緩沖區(qū) 同步硬盤的策略,在性能和安全性方面做出平衡。
文件同步
Redis提供了多種AOF緩沖區(qū)同步文件策略, 由參數(shù)appendfsync控制,如下:
配置為always時(shí), 每次寫入都要同步AOF文件, 在一般的SATA硬盤上,Redis只能支持大約幾百TPS寫入, 顯然跟Redis高性能特性背道而馳,不建議配置。
配置為no,由于操作系統(tǒng)每次同步AOF文件的周期不可控,而且會(huì)加大每次同步硬盤的數(shù)據(jù)量,雖然提升了性能,但數(shù)據(jù)安全性無法保證。
配置為everysec(默認(rèn)的配置),是建議的同步策略, 也是默認(rèn)配置,做到兼顧性能和數(shù)據(jù)安全性。理論上只有在系統(tǒng)突然宕機(jī)的情況下丟失1秒的數(shù)據(jù)(當(dāng)然,這是不太準(zhǔn)確的)。
文件重寫機(jī)制
隨著命令不斷寫入AOF, 文件會(huì)越來越大, 為了解決這個(gè)問題, Redis引入AOF重寫機(jī)制壓縮文件體積。AOF文件重寫是把Redis進(jìn)程內(nèi)的數(shù)據(jù)轉(zhuǎn)化為寫命令同步到新AOF文件的過程。
為什么要文件重寫呢??因?yàn)槲募貙懩軌蚴沟肁OF文件的體積變得更小,從而使得可以更快的被Redis加載。
重寫過程分為手動(dòng)觸發(fā)和自動(dòng)觸發(fā)。
手動(dòng)觸發(fā)直接使用bgrewriteaof命令。
根據(jù)auto-aof-rewrite-min-size和auto-aof-rewrite-percentage參數(shù)確定自動(dòng)觸發(fā)時(shí)機(jī)。
auto-aof-rewrite-min-size:表示運(yùn)行AOF重寫時(shí)文件最小體積, 默認(rèn)為64MB。
auto-aof-rewrite-percentage:代表當(dāng)前AOF文件空間(aof_current_size) 和上一次重寫后AOF文件空間(aof_base_size) 的比值。
自動(dòng)觸發(fā)時(shí)機(jī)相當(dāng)于aof_current_size>auto-aof-rewrite-minsize&&(aof_current_size-aof_base_size) /aof_base_size>=auto-aof-rewritepercentage。其中aof_current_size和aof_base_size可以在info Persistence統(tǒng)計(jì)信息中查看。
那么文件重寫后的AOF文件為什么會(huì)變小呢??有如下幾個(gè)原因:
進(jìn)程內(nèi)已經(jīng)超時(shí)的數(shù)據(jù)將不會(huì)再次寫入AOF文件中。
舊的AOF文件含有無效命令,如del key1、?hdel key2等。重寫使用進(jìn)程內(nèi)數(shù)據(jù)直接生成,這樣新的AOF文件只保留最終數(shù)據(jù)的寫入命令。
多條寫命令可以合并為一個(gè), 如:lpush list a、?lpush list b、lpush listc可以轉(zhuǎn)化為:lpush list a b c。為了防止單條命令過大造成客戶端緩沖區(qū)溢出,對(duì)于list、?set、?hash、?zset等類型操作,以64個(gè)元素為界拆分為多條。
介紹了文件重寫的系列知識(shí),下面來看看Redis內(nèi)部是如何進(jìn)行文件重寫的,如下圖:
看完上圖,大致了解了文件重寫的流程,對(duì)于重寫的流程,補(bǔ)充如下:
重寫期間,主線程并沒有阻塞,而是在執(zhí)行其他的操作命令,依然會(huì)向舊的AOF文件寫入數(shù)據(jù),這樣能夠保證備份的最終完整性,如果數(shù)據(jù)重寫失敗,也能保證數(shù)據(jù)不會(huì)丟失。
為了把重寫期間響應(yīng)的寫入信息也寫入到新的文件中,因此也會(huì)為子進(jìn)程保留一個(gè)緩沖區(qū),防止新寫的文件丟失數(shù)據(jù)。
重寫是直接把當(dāng)前內(nèi)存的數(shù)據(jù)生成對(duì)應(yīng)命令,并不需要讀取老的AOF文件進(jìn)行分析、命令合并。
AOF文件直接采用的文本協(xié)議,主要是兼容性好、追加方便、可讀性高可認(rèn)為修改修復(fù)。
無論是RDB還是AOF都是先寫入一個(gè)臨時(shí)文件,然后通過重命名完成文件的替換。
使用 AOF 持久化會(huì)讓 Redis 變得非常耐久:你可以設(shè)置不同的 fsync 策略,比如無 fsync ,每秒鐘一次 fsync ,或者每次執(zhí)行寫入命令時(shí) fsync 。AOF 的默認(rèn)策略為每秒鐘 fsync 一次,在這種配置下,Redis 仍然可以保持良好的性能,并且就算發(fā)生故障停機(jī),也最多只會(huì)丟失一秒鐘的數(shù)據(jù)( fsync 會(huì)在后臺(tái)線程執(zhí)行,所以主線程可以繼續(xù)努力地處理命令請(qǐng)求)。
對(duì)于相同的數(shù)據(jù)集來說,AOF 文件的體積通常要大于 RDB 文件的體積。根據(jù)所使用的 fsync 策略,AOF 的速度可能會(huì)慢于 RDB。在一般情況下, 每秒 fsync 的性能依然非常高, 而關(guān)閉 fsync 可以讓 AOF 的速度和 RDB 一樣快, 即使在高負(fù)荷之下也是如此。不過在處理巨大的寫入載入時(shí),RDB 可以提供更有保證的最大延遲時(shí)間。
數(shù)據(jù)恢復(fù)速度相對(duì)于RDB比較慢。
優(yōu)先使用物理機(jī)或者高效支持fork操作的虛擬化技術(shù)。
控制Redis實(shí)例最大可用內(nèi)存, fork耗時(shí)跟內(nèi)存量成正比, 線上建議每個(gè)Redis實(shí)例內(nèi)存控制在10GB以內(nèi)。
合理配置Linux內(nèi)存分配策略,避免物理內(nèi)存不足導(dǎo)致fork失敗。
降低fork操作的頻率,如適度放寬AOF自動(dòng)觸發(fā)時(shí)機(jī),避免不必要的全量復(fù)制等。
如何保證 HBase 服務(wù)的高可用?看看這份 HBase 可用性分析與高可用實(shí)踐吧!
一文帶你認(rèn)識(shí)keepalived,再帶你通關(guān)LVS+Keepalived!
那個(gè)分分鐘處理 10 億節(jié)點(diǎn)圖計(jì)算的 Plato,現(xiàn)在怎么樣了?
“谷歌殺手”發(fā)明者,科學(xué)天才 Wolfram
數(shù)據(jù)庫激蕩 40 年,深入解析 PostgreSQL、NewSQL 演進(jìn)歷程
超詳細(xì)!一文告訴你 SparkStreaming 如何整合 Kafka !附代碼可實(shí)踐
5分鐘!就能學(xué)會(huì)以太坊 JSON API 基礎(chǔ)知識(shí)!
真香,朕在看了!
AOF的優(yōu)點(diǎn)
AOF的缺點(diǎn)
AOF和RDB的區(qū)別
RDB持久化是指在指定的時(shí)間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤,實(shí)際操作過程是fork一個(gè)子進(jìn)程,先將數(shù)據(jù)集寫入臨時(shí)文件,寫入成功后,再替換之前的文件,用二進(jìn)制壓縮存儲(chǔ)。
AOF持久化以日志的形式記錄服務(wù)器所處理的每一個(gè)寫、刪除操作,查詢操作不會(huì)記錄,以文本的方式記錄,可以打開文件看到詳細(xì)的操作記錄。
重啟加載
無論是RDB還是AOF都可用于服務(wù)器重啟時(shí)的數(shù)據(jù)恢復(fù),執(zhí)行流程如下圖:
上圖很清晰的分析了Redis啟動(dòng)恢復(fù)數(shù)據(jù)的流程,先檢查AOF文件是否開啟,文件是否存在,再檢查RDB是否開啟,文件是否存在。
性能問題與解決方案
通過上面的分析,我們都知道RDB的快照、AOF的重寫都需要fork,這是一個(gè)重量級(jí)操作,會(huì)對(duì)Redis造成阻塞。因此為了不影響Redis主進(jìn)程響應(yīng),我們需要盡可能降低阻塞。
那么如何減少fork操作的阻塞呢?
總結(jié)
本文介紹了Redis持久化的兩種不同的策略,大部分內(nèi)容是運(yùn)維人員需要掌握的,當(dāng)然作為后端人員也是需要了解一下,畢竟小公司都是一人搞全棧,哈哈。
推薦閱讀
總結(jié)
以上是生活随笔為你收集整理的天天用Redis,持久化方案你又知道哪些?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 音视频应用驶入快车道 开发者如何快速追赶
- 下一篇: 针对提高48V 配电性能的诸多思考!