Redis(5):Redis持久化配置和數(shù)據(jù)恢復實驗

? ? ? ? 在上一篇文章中對Redis的兩種持久化方式進行了介紹,還介紹了各自的優(yōu)缺點以及如何選擇,這篇文章就介紹一下redis的持久化應該怎么配置,數(shù)據(jù)恢復應該怎么操作。

1.RDB配置和數(shù)據(jù)恢復流程

(1).RDB的配置

????????首先找到redis的配置文件,我的redis裝在了centos上,配置文件的目錄為:/etc/redis/6379.conf,打開它找到snapshotting。


rdb配置redis

????????可以在snapshotting下配置多個save,這個save其實就是檢查點,redis可以配置多個檢查點,每到一個檢查點,就會去check一下,是否有指定的key數(shù)量發(fā)生了變更,如果有,就生成一個新的dump.rdb文件。當然,我們也可以通過手動調(diào)用save或者bgsave命令,同步或異步執(zhí)行rdb快照生成。

save 900 1:表示每隔900秒如果有1個key發(fā)生變化就會生成一個新的rdb文件

save 300 10:表示每隔300秒如果有10個key發(fā)生變化就會生成一個新的rdb文件

save 60 10000:表示每隔60秒如果有10000個key發(fā)生變化就會生成一個新的rdb文件

? ? ? ? save 5 1 是我們?yōu)榱藢嶒灧奖阍O(shè)置的一個檢查點

(2).RDB持久化機制的工作流程

(a).redis根據(jù)配置自己嘗試去生成rdb快照文件

(b).fork一個子進程出來

(c).子進程嘗試將數(shù)據(jù)dump到臨時的rdb快照文件中

(d).完成rdb快照文件的生成之后,就替換之前的舊的快照文件

同時只有一個dump.rdb,每次生成一個新的快照,都會覆蓋之前的老快照。

(3).rdb數(shù)據(jù)恢復實驗

????????首先我們打開redis-cli存儲一些數(shù)據(jù)(ps:此時我們還沒有在redis.conf中添加save 5 1):


????????現(xiàn)在我們把一些數(shù)據(jù)都已經(jīng)放在了redis里面,然后我們shut down redis,并且重啟redis:


????????那么現(xiàn)在就有點奇怪了,我們還沒有添加檢查點 save 5 1,為什么數(shù)據(jù)還是在redis中?其實在我們shutdown redis-cli的時候就已經(jīng)自動生成了一次快照文件了,所以上述操作是安全操作!(那你說個屁!);

????????好的,我們接下來就不shutdown 而是直接kill -9 來粗暴殺死redis的進程并且刪除掉/var/run 下面redis_6379.pid,模擬redis的故障場景:

????????這時就發(fā)現(xiàn)我們剛剛添加的三個值都拿不到了。

????????然后我們自己手動設(shè)置一個檢查點:save 5 1到redis的配置文件中。然后再次將剛剛?cè)齻€值保存到redis中,然后等待五秒,重復上面殺死redis進程的操作,然后在重啟redis,現(xiàn)在我們就發(fā)現(xiàn)之前的值沒有因為redis被殺死而丟失。


????????好的,以上就是我們使用RDB進行數(shù)據(jù)恢復的實驗,save 5 1這個檢查點記得注釋掉或者刪除,我們沒有必要這么頻繁的去生成快照。

2.AOF配置和數(shù)據(jù)恢復流程

(1).AOF的配置

????????我們在redis的配置文件中搜索appendonly就可以找到aof的相關(guān)配置了。

????????其實redis默認的持久化方式時rdb,rdb是默認打開的,我們要使用aof的話就需要單獨打開。


aof配置

????????在生產(chǎn)中,aof一般都是要打開的,除非你覺得丟失幾分鐘的數(shù)據(jù)無大礙。

????????設(shè)置 appendonly yes 后就打開了aof,打開aof之后,redis每接受到一條命令都會先寫入到日志文件中,當然不會直接寫到aof文件中,他會先寫入到ox cache中,然后每隔一段時間調(diào)用操作系統(tǒng)的fsync操作,將os cache中的數(shù)據(jù)同步到磁盤上的aof文件中。

????????而且,當rdb和aof同時開啟的時候,redis也會優(yōu)先aof來進行數(shù)據(jù)恢復,因為aof的數(shù)據(jù)相對來說比rdb完整。

aof有三種策略供君選擇:

appendfsync always:?

????????每次寫入一條數(shù)據(jù),立即將這個數(shù)據(jù)對應的寫日志fsync到磁盤上去,性能非常非常差,吞吐量很低; 如果說你要求redis里的數(shù)據(jù)一條都不丟,那就選擇此策略。

appendfsync everysec:

????????每秒將os cache中的數(shù)據(jù)fsync到磁盤,這個最常用的,生產(chǎn)環(huán)境一般都這么配置,性能很高,QPS還是可以上萬的。

appendfsync no:

? ? ? ?redis?僅僅負責將數(shù)據(jù)寫入os cache就不管了,然后os自己會時不時根據(jù)自己的策略將數(shù)據(jù)刷入磁盤,人為不可控。

(2).aof數(shù)據(jù)恢復實驗

????????首先我們打開aof的開關(guān),啟用aof,然后向redis中添加數(shù)據(jù),然后找到aof文件(我的持久化文件放在:/var/redis/6379),aof中按順序存放指令,如果你知道aof的規(guī)則的話是可以讀懂的,也就是說,aof文件是可讀的。

aof文件內(nèi)容

????????我使用的策略是everysec,也就是每秒調(diào)用一次fsync,redis先將數(shù)據(jù)寫入os cache中,一秒后才調(diào)用fsync操作將數(shù)據(jù)寫入磁盤中,數(shù)據(jù)沒有寫入磁盤的話是不安全的,也就是說,everysec還是有可能丟失一秒的數(shù)據(jù)。

????????我們將redis的進程殺死,看看數(shù)據(jù)恢復成功了沒:

aof數(shù)據(jù)恢復

? ? ? ? 數(shù)據(jù)成功的被恢復了,redis進程啟動的時候,直接就會從appendonly.aof中加載所有的日志,把內(nèi)存中的數(shù)據(jù)恢復回來。

(3).aof的rewrite機制

redis中的數(shù)據(jù)其實有限的,很多數(shù)據(jù)可能會自動過期,可能會被用戶刪除,可能會被redis用緩存清除的算法清理掉。redis中的數(shù)據(jù)會不斷淘汰掉舊的,就一部分常用的數(shù)據(jù)會被自動保留在redis內(nèi)存中。所以可能很多之前的已經(jīng)被清理掉的數(shù)據(jù),對應的寫日志還停留在AOF中,AOF日志文件就一個,會不斷的膨脹,變得很大很大。所以AOF會自動在后臺每隔一定時間做rewrite操作,比如日志里已經(jīng)存放了針對100w數(shù)據(jù)的寫日志了; redis內(nèi)存只剩下10萬; 基于內(nèi)存中當前的10萬數(shù)據(jù)構(gòu)建一套最新的日志,到AOF中; 覆蓋之前的老日志; 確保AOF日志文件不會過大,保持跟redis內(nèi)存數(shù)據(jù)量一致。

首先,我們先去配置文件中搜索一下rewrite,可以看看相關(guān)的說明。

rewrite配置

????????rewrite的策略我們使用默認的就好,有興趣的讀者可以去研究一下redis的rewrite策略,我在這里就講一下上圖對應的兩個參數(shù),這兩個參數(shù)相對來說比較重要。這兩個參數(shù)怎么解釋呢?比如說上一次AOF rewrite之后,是128mb。然后就會接著128mb繼續(xù)寫AOF的日志,如果發(fā)現(xiàn)增長的比例,超過了之前的100%,256mb,就可能會去觸發(fā)一次rewrite但是此時還要去跟min-size,64mb去比較,256mb > 64mb,才會去觸發(fā)rewrite。

(4).aof rewrite過程詳解

(a).redis fork一個子進程

(b).子進程基于當前內(nèi)存中的數(shù)據(jù),構(gòu)建日志,開始往一個新的臨時的AOF文件中寫入日志

(c).redis主進程,接收到client新的寫操作之后,在內(nèi)存中寫入日志,同時新的日志也繼續(xù)寫入舊的AOF文件

(d).子進程寫完新的日志文件之后,redis主進程將內(nèi)存中的新日志再次追加到新的AOF文件中

(e).用新的日志文件替換掉舊的日志文件


aofrewrite流程

(5).aof文件破損修復

????????當redis在append數(shù)據(jù)到aof文件中的時候,服務(wù)器宕機了,那么就可能造成aof文件的損壞,redis提供了相關(guān)的工具來修復破損的aof文件。使用redis-check-aof --fix命令來修復破損的AOF文件。

????????我們來做一個小實驗,我們把備份的aof文件copy出來一份,然后更改它,是他破損,然后使用redis的修復工具來修復它。

? ? ? ? 首先將aof文件copy出來

copy aof文件

我們編輯這個文件,然后更改這個文件:


更改后的文件

然后使用redis的修復工具修復這個文件:


修復之后的文件

redis修復工具就會把最后那行多余的指令刪除掉。

3.RDB和AOF同時工作

? ? ? ? 因為redis的持久化操作是非常消耗性能的,那么當他們倆發(fā)生沖突的時候會怎么辦?

(1)如果RDB在執(zhí)行snapshotting操作,那么redis不會執(zhí)行AOF rewrite; 如果redis再執(zhí)行AOF rewrite,那么就不會執(zhí)行RDB snapshotting

(2)如果RDB在執(zhí)行snapshotting,此時用戶執(zhí)行BGREWRITEAOF命令,那么等RDB快照生成之后,才會去執(zhí)行AOF rewrite

(3)同時有RDB snapshot文件和AOF日志文件,那么redis重啟的時候,會優(yōu)先使用AOF進行數(shù)據(jù)恢復,因為其中的日志更完整

(4)在有rdb的dump和aof的appendonly的同時,rdb里也有部分數(shù)據(jù),aof里也有部分數(shù)據(jù),這個時候其實會發(fā)現(xiàn),rdb的數(shù)據(jù)不會恢復到內(nèi)存中

大家也可做個小實驗,將aof中的數(shù)據(jù)刪除一條(這條數(shù)據(jù)已經(jīng)持久化到rdb中),然后用redis的修復工具進行修復,在用這個文件替換aof文件,重啟redis,最后會發(fā)現(xiàn)rdb中的數(shù)據(jù)不會被恢復到內(nèi)存中。

redis的數(shù)據(jù)恢復完全是依賴于底層的磁盤的持久化的,如果rdb和aof上都沒有數(shù)據(jù),那就真的沒了。

4.在實際項目的使用中,我們應該如何配置和使用呢?

(1).配置策略

????????在企業(yè)級的項目中,我們使用rdb的默認配置也無大礙,即:

save 900 1

save 300 10

save 60 10000

????????唯一可能要調(diào)整的就是 save 60 10000 這個檢查點,因為rdb的生成還是比較耗費資源的,如果說低峰期數(shù)據(jù)量很小,那么也沒太大必要。但是如果你要保證RDB最多丟一分鐘的數(shù)據(jù),那么剩下的就是你自己根據(jù)實際情況去配置,到底是一分鐘-10000生成rdb,還是說設(shè)置成1分鐘-1000生成rdb。

????aof的話這里推薦把他打開,調(diào)用fsync的策略推薦使用everysec,然后根據(jù)你項目的實際情況去設(shè)置以下兩個屬性:

auto-aof-rewrite-percentage 100 這個屬性改的必要也不是特別的大

auto-aof-rewrite-min-size 64mb 這個根據(jù)你的數(shù)據(jù)量來定

(2).數(shù)據(jù)備份方案

RDB的話是非常適合做冷備的,每次RDB生成完成之后就不會再修改了,備份的方案可以這樣:

(a).寫crontab定時調(diào)度腳本去做數(shù)據(jù)備份

(b).每小時都copy一份rdb的備份,到一個目錄中去,僅僅保留最近48小時的備份

(c).每天都保留一份當日的rdb的備份,到一個目錄中去,僅僅保留最近1個月的備份

(d).每次copy備份的時候,都把太舊的備份給刪了

(e).每天晚上將當前服務(wù)器上所有的數(shù)據(jù)備份,發(fā)送一份到遠程的云服務(wù)上去


每小時copy一次備份,刪除48小時前的數(shù)據(jù)

crontab -e

0 * * * * sh /usr/local/redis/copy/redis_rdb_copy_hourly.sh

redis_rdb_copy_hourly.sh

```

#!/bin/sh

cur_date=`date +%Y%m%d%k`

rm -rf /usr/local/redis/snapshotting/$cur_date

mkdir /usr/local/redis/snapshotting/$cur_date

cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date

del_date=`date -d -48hour +%Y%m%d%k`

rm -rf /usr/local/redis/snapshotting/$del_date

```

每天copy一次備份

crontab -e

0 0 * * * sh /usr/local/redis/copy/redis_rdb_copy_daily.sh

redis_rdb_copy_daily.sh

```

#!/bin/sh

cur_date=`date +%Y%m%d`

rm -rf /usr/local/redis/snapshotting/$cur_date

mkdir /usr/local/redis/snapshotting/$cur_date

cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date

del_date=`date -d -1month +%Y%m%d`

rm -rf /usr/local/redis/snapshotting/$del_date

```

每天一次將所有數(shù)據(jù)上傳一次到遠程的云服務(wù)器上去

(3).數(shù)據(jù)恢復方案

(a).如果是redis進程掛掉,那么重啟redis進程即可,直接基于AOF日志文件恢復數(shù)據(jù)。

(b).如果是redis進程所在機器掛掉,那么重啟機器后,嘗試重啟redis進程,嘗試直接基于AOF日志文件進行數(shù)據(jù)恢復。AOF沒有破損,也是可以直接基于AOF恢復的,如果AOF文件出現(xiàn)了破損,則用redis的修復工具修復之后在進行恢復。

(c).如果redis當前最新的AOF和RDB文件出現(xiàn)了丟失/損壞,那么可以嘗試基于該機器上當前的某個最新的RDB數(shù)據(jù)副本進行數(shù)據(jù)恢復。

(d).如果當前機器上的所有RDB文件全部損壞,那么從遠程的云服務(wù)上拉取最新的RDB快照回來恢復數(shù)據(jù)。

(e).如果是發(fā)現(xiàn)有重大的數(shù)據(jù)錯誤,比如某個小時上線的程序一下子將數(shù)據(jù)全部污染了,數(shù)據(jù)全錯了,那么可以選擇某個更早的時間點,對數(shù)據(jù)進行恢復。

(4).基于RDB冷備恢復數(shù)據(jù)

????????基于rdb冷備其實是有一些小坑的,這里拿出來記錄一下,如果你同時打開RDB和AOF,如果你使用的是AOF的冷備去恢復數(shù)據(jù),那么很簡單,將redis的aof文件替換成你的冷備然后重啟redis就行了。

????????但是要是你使用的是RDB的冷備,你首先要把redis現(xiàn)有的aof文件刪掉,然后把rdb文件替換成你的冷備,但是由于你開著aof,所以在aof啟動的時候會直接生成一份空的aof文件,而你的RDB冷備會被無視掉,過了一段時間可能會被重寫掉。你可能會想,那我們把AOF關(guān)掉不就行了嗎?我們把AOF關(guān)掉,重啟redis,確實,RDB的數(shù)據(jù)會被恢復到redis中,現(xiàn)在數(shù)據(jù)回來了,但是AOF不能關(guān)掉,所以你再次修改配置文件打開AOF重啟redis,這時你發(fā)現(xiàn)辛辛苦苦恢復的數(shù)據(jù)又沒了,其實還是因為打開AOF重新生成了一份空的AOF文件,RDB里面就算有數(shù)據(jù)也不會恢復到redis當中。那么怎么解決呢?我們可以通過熱修改redis屬性的方式進行恢復,我們先把redis的AOF關(guān)掉,用RDB冷備恢復數(shù)據(jù),在redis-cli 中使用 config set 指令來開啟AOF,等RDB冷備的數(shù)據(jù)全被寫入AOF后,再修改配置文件打開AOF,重啟redis即可。以下是具體的流程:

(a).停止redis

(b).關(guān)閉aof

(c).拷貝rdb備份

(d).重啟redis,確認數(shù)據(jù)恢復

(e).直接在命令行熱修改redis配置,打開aof,redis就會將內(nèi)存中的數(shù)據(jù)對應的日志,寫入aof文件中

(f).此時aof和rdb兩份數(shù)據(jù)文件的數(shù)據(jù)就同步了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 企業(yè)級redis集群架構(gòu)的特點 海量數(shù)據(jù) 高并發(fā) 高可用 要達到高可用,持久化是不可減少的,持久化主要是做災難恢復...
    lucode閱讀 2,280評論 0 7
  • 一、Redis高可用概述 在介紹Redis高可用之前,先說明一下在Redis的語境中高可用的含義。 我們知道,在w...
    空語閱讀 1,679評論 0 2
  • redis的 rdb 和 aof 持久化的區(qū)別 aof,rdb是兩種 redis持久化的機制。用于crash后,r...
    可可西里的星星閱讀 389評論 0 0
  • 李宗盛的《鬼迷心竅》,歌詞寫的真心不錯轉(zhuǎn)載欣賞。最喜歡其中“春風再美也比不上你的笑”,這種美,絕了!藍色連接是自己...
    楓之然閱讀 329評論 12 11
  • 【讀書要玩味】 純屬個人感受,勿喜勿噴,小小的分享 1.《月亮和六便士》——毛姆 正如文章前言所道,毛姆的小說...
    一個黃油醬閱讀 320評論 0 1

友情鏈接更多精彩內(nèi)容