Redis企業級數據備份與恢復方案

一、持久化配置

  • RBD和AOF建議同時打開(Redis4.0之後支援)

  • RDB做冷備,AOF做數據恢復(數據更可靠)

  • RDB採取默認配置即可,AOF推薦採取everysec每秒策略

AOF和RDB還不懂的,請轉移到如下幾篇:

看完這篇還不懂Redis的RDB持久化,你們來打我!

天天在用Redis,那你對Redis的AOF持久化到底了解多少呢?

二、數據備份方案

1、需求

我們需要定時備份rdb文件來做冷備,為什麼?不是有aof和rbd了嗎為什麼還要單獨寫定時任務去備份?因為Redis的aof和rdb是僅僅有一個最新的,比如誰手賤再Redis宕機的時候執行rm -rf aof/rdb了,那不就GG了嗎?或者rdb/aof文件損壞了等不可預期的情況。所以我們需要單獨備份rdb文件以防萬一。

為什麼不定時備份aof而是rdb?定時備份aof沒意義呀,定時本身就是冷備份,不是實時的,rdb文件又小恢復又快,她哪裡不香?

2、方案

  • 寫crontab定時調度腳本去做數據備份。

  • 每小時都copy一份redis的rdb文件到一個其他目錄中,這個目錄里的rdb文件僅僅保留48小時內的。也就是每小時都做備份,保留2天內的rdb,只保留48個rdb。

  • 每天0點0分copy一份redis的rdb文件到一個其他目錄中,這個保留一個月的。也就是按天備份。

  • 每天半夜找個時間將當前服務上的所有rdb備份都上傳到雲服務上。

3、實現

3.1、按小時

每小時copy一次備份,刪除48小時前的數據。

crontab -e
# 每小時都執行/usr/local/redis/copy/redis_rdb_copy_hourly.sh腳本
0 * * * * sh /usr/local/redis/copy/redis_rdb_copy_hourly.sh


# redis_rdb_copy_hourly.sh腳本的內容如下:

#!/bin/sh 
# +%Y%m%d%k == 年月日時
cur_date=`date +%Y%m%d%k`
rm -rf /usr/local/redis/rdb/$cur_date
mkdir /usr/local/redis/rdb/$cur_date
# 拷貝rdb到目錄
cp /var/redis/6379/dump.rdb /usr/local/redis/rdb/$cur_date
# date -d -48hour +%Y%m%d%k == 48小時前的日期,比如今天2020060214,這個結果就是2020053114
del_date=`date -d -48hour +%Y%m%d%k`
# 刪除48小時之前的目錄
rm -rf /usr/local/redis/rdb/$del_date

 

3.2、按天

每天copy一次備份,刪除一個月前的數據。

crontab -e
# 每天0點0分開始執行/usr/local/redis/copy/redis_rdb_copy_daily.sh腳本
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/rdb/$cur_date
mkdir /usr/local/redis/rdb/$cur_date
# 拷貝rdb到目錄
cp /var/redis/6379/dump.rdb /usr/local/redis/rdb/$cur_date

# 獲取一個月前的時間,比如今天是20200602,那麼del_date就是20200502
del_date=`date -d -1month +%Y%m%d`
# 刪除一個月前的數據
rm -rf /usr/local/redis/rdb/$del_date

 

3.3、傳到雲

沒法演示,最終目的就是磁碟備份完上傳到雲,雲保留多少天等策略自己看需求。

三、數據恢復方案

1、redis掛了

如果僅僅是redis進程掛了,那麼直接重啟redis進程即可,Redis會按照持久化配置直接基於持久化文件進行恢複數據。

如果有AOF則按照AOF,AOF和RDB一起開的話也走AOF。

2、持久化文件丟了

如果持久化文件(rdb/aof)損壞了,或者直接丟失了。那麼就要採取我們上面所做的rdb備份來進行恢復了。

不要腦子一熱想著很簡單,就以為直接把rdb拖過來重啟redis進程就完事了,這種想法有很多問題。慢慢道來。

2.1、問題

問題一:直接把備份的rdb扔到redis持久化目錄下然後重啟redis不行的原因在於:redis是按照先aof後rdb進行恢復的,所以都是開啟aof的,redis啟動後會重新生成新的aof文件,裡面是空的。所以不會進行任何數據恢復,也就是說雖然你把rdb丟給redis了,但是redis會按照aof來恢復,而aof是redis啟動的時候新生成的空文件,所以不會有任何數據進行恢復。

問題二:那麼我們把rdb文件丟給redis後,先將redis的aof關閉再啟動redis進程不就能按照rdb來進行恢復了嗎?是這樣的,沒毛病!但是新的問題來了,我們aof肯定要開的,aof對數據保障更可靠。那什麼我們按照rdb文件恢復完後再修改redis配置文件開啟aof然後重啟redis進程不就得了嘛?大哥…你打開aof然後重啟redis,這時候redis又會生成一個空的aof文件,這時候恢復的時候又是啥數據都沒了。

因為數據是存到記憶體里,你重啟後肯定沒了,需要持久化文件來恢復。這時候aof是空的,我恢復個雞毛啊。

2.2、具體方案

可能有人想到方案了,但是耐心看完,看看我的文采如何。

我不管你是持久化文件丟了還是壞了,我都先rm -rf * 給他刪了。

  • 停止redis進程

  • 刪除壞掉的rdb和aof持久化文件。

  • 修改配置文件關閉redis的aof持久化。

  • 找到最新備份的rdb文件扔到redis的持久化目錄里。(這裡最新的肯定是按照小時備份的最後一個)

  • 啟動Redis進程

  • 執行set appendonly yes動態打開aof持久化。

也就是說打開aof的操作不是修改配置文件然後重啟,而是先熱修改讓他生成aof,這次生成肯定是會帶著記憶體中完整的數據的。然後再修改配置文件重啟。

  • 等aof文件生成後再修改redis配置文件打開aof。

  • 重啟redis進程。

  • 完美收官。