redis学习笔记-持久化
redis學(xué)習(xí)筆記-持久化
前言
redis持久化有兩種方式:RDB和AOF。分別對應(yīng)著全量復(fù)制和增量復(fù)制。深刻理解各自的實(shí)現(xiàn)方式及適用場景對redis的使用和運(yùn)維十分重要。下面就分別介紹。
RDB持久化
RDB持久化即將當(dāng)前Redis實(shí)例中的數(shù)據(jù)快照全部保存的磁盤的過程。可手動(dòng)觸發(fā),也可根據(jù)配置自動(dòng)觸發(fā)。
手動(dòng)觸發(fā)
手動(dòng)觸發(fā)有兩個(gè)命令可以選擇: save和bgsave。兩者區(qū)別在于save是阻塞的,復(fù)制完成前會(huì)阻塞客戶端命令執(zhí)行,目前已經(jīng)廢棄。bgsave是非阻塞的。執(zhí)行過程中redis進(jìn)程會(huì)fork出一個(gè)子進(jìn)程負(fù)責(zé)復(fù)制任務(wù),而主進(jìn)程依然響應(yīng)客戶端請求命令。對應(yīng)bgsave命令,阻塞只存在于fork過程中。大大減小了阻塞的時(shí)間。
如圖,上次rdb同步時(shí)間在17:20
執(zhí)行命令bgsave后, 返回 Background saving started ,
查看rdb文件更新時(shí)間,已變?yōu)楫?dāng)前時(shí)間。
自動(dòng)觸發(fā)
若使用自動(dòng)觸發(fā),需配置save參數(shù)。格式 save m n。查看redis配置文件可看到相關(guān)配置。
save 900 1save 300 10save 60 10000復(fù)制代碼配置 save m n 含義為當(dāng)數(shù)據(jù)在m秒內(nèi)發(fā)生n次修改,自動(dòng)執(zhí)行bgsave命令進(jìn)行RDB持久化。如save 900 1 表示在900秒(15分鐘內(nèi))數(shù)據(jù)有至少1次修改,則觸發(fā)RDB。多個(gè)配置情況下,只要符合任一條件即可。
具體在實(shí)現(xiàn)上,redis服務(wù)器會(huì)記錄自上次RDB備份后,有多少次修改。每100ms檢查一次,看是否有符合條件的save配置,有則再次執(zhí)行DRB.
另外,當(dāng)在客戶端執(zhí)行關(guān)閉服務(wù)器命令shutdown,若redis沒有開啟AOF,則自動(dòng)執(zhí)行bgsave進(jìn)行備份。
RDB流程
由于save的持久化命令會(huì)發(fā)送阻塞,所以目前基本是用bgsave命令觸發(fā)的RDB,關(guān)于bgsave的流程如下圖所示。
簡要流程如下
簡要來說是父進(jìn)程fork出了一個(gè)子進(jìn)程用于持久化任務(wù),父進(jìn)程仍響應(yīng)客戶端請求,耗時(shí)的RDB讓子進(jìn)程來做。這樣的確可以大大減少阻塞時(shí)間,可有一個(gè)問題是,主進(jìn)程還在接受請求,子進(jìn)程怎樣進(jìn)行復(fù)制?難道子進(jìn)程再復(fù)制一份主進(jìn)程的內(nèi)存用于復(fù)制,這樣內(nèi)存豈不是要翻倍?肯定不能這樣。要是子進(jìn)程共享父進(jìn)程的內(nèi)存,那怎樣保證邊接受請求邊復(fù)制呢?
事實(shí)上,fork操作使用寫時(shí)復(fù)制(copy-on-write)技術(shù)實(shí)現(xiàn)。創(chuàng)建的子進(jìn)程共享父進(jìn)程地址空間,當(dāng)只有需要寫入時(shí)才會(huì)復(fù)制地址空間。也就是說,redis的子進(jìn)程使用共享的內(nèi)存快照完成RDB備份,而主進(jìn)程當(dāng)收到寫請求后,會(huì)將涉及到的內(nèi)存頁復(fù)制出一份副本,在此副本進(jìn)行修改。當(dāng)子進(jìn)程RDB完成后,通知主進(jìn)程更換副本,RDB就此完成。
RDB參數(shù)設(shè)置及注意點(diǎn)
以下是redis配置文件有關(guān)rdb的默認(rèn)配置
## 是否開啟rdb文件壓縮 rdbcompression yes## rdb文件效驗(yàn) rdbchecksum yes## rdb文件名 dbfilename redis-dump-127.0.0.1-6379.rdb## 備份文件儲(chǔ)存目錄 dir /usr/local/var/db/redis/復(fù)制代碼AOF持久化
AOF主要用于解決redis實(shí)時(shí)持久化的問題。方式為實(shí)時(shí)將redis所有寫命令記錄下來,用于以后恢復(fù)及備份。
開啟AOF
aof默認(rèn)是關(guān)閉的,使用appendonly yes開啟。用appendfilename設(shè)置aof文件名。同rdb一樣,dir表示aof儲(chǔ)存目錄。
在配置文件設(shè)好后重啟redis,即開啟了aof功能。可使用info persistence可查看redis持久化的參數(shù),如下
aof_enabled:1
表示已開啟aof功能。
AOF流程
AOF寫入日志的直接就是文本格式。如set hello world這個(gè)命令,在appendonly.aof文件中儲(chǔ)存的就是
*3 $3 SET $5 hello $5 world 復(fù)制代碼這就是Redis客戶端與服務(wù)器通信的的序列化協(xié)議(RESP),每行用\r\n分割,*n表示參數(shù)個(gè)數(shù),$n表示字節(jié)數(shù),十分簡單明了。AOF直接使用協(xié)議格式可讓redis直接識(shí)別。無需特殊處理,避免二次處理的開銷,也方便修改。
AOF的流程如下
用流程圖表示就是
為什么不直接將命令寫入磁盤很容易理解,這里需關(guān)注的是以什么策略從緩沖區(qū)寫到磁盤。redis提供了3種策略。
| always | 每次命令寫入緩沖區(qū)后都同步刷新到硬盤(使用fsync命令刷新磁盤),此方式最安全,但也是最慢的,因?yàn)槊看螌憯?shù)據(jù)都要同步硬盤 |
| everysec | 每次寫命令調(diào)用系統(tǒng)命令write操作,write只會(huì)將數(shù)據(jù)寫入系統(tǒng)緩沖區(qū),然后由專門的線程每秒同步刷盤 |
| no | 每次寫命令調(diào)用系統(tǒng)命令write操作寫入系統(tǒng)緩沖區(qū),具體刷盤時(shí)間由操作系統(tǒng)決定,性能是最高的,但數(shù)據(jù)安全性不能保證 |
通常,我們選擇everysec作為刷盤策略,也是redis默認(rèn)配置,可以兼顧性能和數(shù)據(jù)安全。
AOF追加阻塞
一般我們使用everysec的同步刷盤策略。此時(shí)會(huì)有一個(gè)專門的線程每秒執(zhí)行一次刷盤操作。為保證數(shù)據(jù)安全性,redis主進(jìn)程會(huì)比對上次刷盤時(shí)間與當(dāng)前時(shí)間的差值,如果大于2秒,則阻塞以等待刷盤完成。
也就是說,如果硬盤性能很差,fsync執(zhí)行太慢,會(huì)造成redis阻塞。以保證硬盤的數(shù)據(jù)不被真實(shí)內(nèi)存數(shù)據(jù)落的太遠(yuǎn)(最大2秒的數(shù)據(jù)差)。
AOF重寫機(jī)制
剛才提到,AOF直接使用redis的序列化協(xié)議進(jìn)行備份,一段時(shí)間后,aof文件會(huì)很大。為解決此問題,可配置aof重寫機(jī)制對原aof文件進(jìn)行瘦身。
AOF重寫的實(shí)質(zhì)即把redis進(jìn)程的內(nèi)存數(shù)據(jù)轉(zhuǎn)為寫命令重新生成一份aof文件,以替代原aof文件。
重寫后比原aof體積小的原因有以下幾點(diǎn)
觸發(fā)方式
AOF可有手動(dòng)觸發(fā)和自動(dòng)觸發(fā)。
手動(dòng)觸發(fā)使用bgrewriteaof命令觸發(fā)。
自動(dòng)觸發(fā)有關(guān)參數(shù)及含義如下
## aof重寫時(shí)此時(shí)aof文件與上次aof文件大小百分比 auto-aof-rewrite-percentage 100## aof重寫時(shí)文件最小大小,默認(rèn)64M auto-aof-rewrite-min-size 64mb復(fù)制代碼如按默認(rèn)配置,則發(fā)生重寫的條件為aof文件大于64M且此時(shí)aof文件比上次重寫時(shí)大100%,即是上次的2倍。
重寫流程
aof重寫雖然比較復(fù)雜,但對比圖,也能很容易明白其中流程。這這里有個(gè)疑問是為什么主進(jìn)程在子進(jìn)程重寫時(shí)為什么要維護(hù)兩個(gè)緩沖區(qū)?只維護(hù)一個(gè)不行嗎?畢竟原有aof文件等到新aof文件生成后也是要替換的。
仔細(xì)想想就可知,有必要維護(hù)兩個(gè)緩沖區(qū)。主要是需要維護(hù)原有aof邏輯不變,以防aof重寫失敗導(dǎo)致數(shù)據(jù)丟失。另一點(diǎn)兩個(gè)緩沖區(qū)目的也不同,不宜混淆。
注意:
為防止資源過于競爭,同一時(shí)刻只能進(jìn)行一個(gè)AOF重寫任務(wù),當(dāng)進(jìn)行重寫時(shí)發(fā)現(xiàn)有RDB任務(wù)時(shí),也會(huì)等RDB完成后進(jìn)行。
RDB與AOF
加載順序
在重啟時(shí),redis會(huì)首先判斷是否開啟aof,若開啟aof且aof文件存在,則加載aof文件進(jìn)行數(shù)據(jù)恢復(fù)以啟動(dòng)。否則判斷rdb文件存在并加載rdb以啟動(dòng)。
性能開銷
在進(jìn)行RDB備份或是AOF重寫時(shí),都需要fork出子進(jìn)程運(yùn)行任務(wù)。此期間會(huì)大量消耗CPU,通常子進(jìn)程對單核CPU的利用率達(dá)到90%,因此在有RDB或需AOF重寫任務(wù)的redis,不要做綁定單核CPU操作,這會(huì)導(dǎo)致父子進(jìn)程對CPU產(chǎn)生競爭。
RDB與AOF比較
參考文章
總結(jié)
以上是生活随笔為你收集整理的redis学习笔记-持久化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从0到1学C++ 第3篇 从结构到类的演
- 下一篇: MySQL学习(十五)