Redis 企業(yè)級數(shù)據(jù)備份方案
企業(yè)級的持久化的配置策略
在實際生產(chǎn)環(huán)境,RDB 和 AOF 一定都要打開,RDB 和 AOF 的配置需要根據(jù)業(yè)務(wù)的數(shù)據(jù)量決定
Redis RDB 持久化配置和數(shù)據(jù)恢復(fù)實驗??
RDB 持久化配置
自動方式
RDB 持久化在 redis.conf 文件中配置,目前配置文件存放在?/etc/redis/6379.conf,打開配置文件,添加 save 屬性配置,定期生成 RDB 快照。
# 每隔15分鐘,如果有超過1個key發(fā)生了變更,那么就生成一個新的dump.rdb文件save 900 1# 每隔5分鐘,如果有超過300個key發(fā)生了變更,那么就生成一個新的dump.rdb文件save 300 10# 每隔1分鐘,如果有超過10000個key發(fā)生了變更,那么就生成一個新的dump.rdb文件save 60 10000
save 屬性可以設(shè)置多個,就是設(shè)置多個 SNAPSHOTTING 檢查點,每到一個檢查點,就會去 check 一下,是否有指定的 key 數(shù)量發(fā)生了變更,如果有,就生成一個新的 dump.rdb 文件。
手動方式
也可以在 redis-cli 命令中輸入 save 或者 bgsave 命令,手動同步或異步生成 RDB?快照。
RDB 持久化機(jī)制的工作流程
Redis 根據(jù)配置自己嘗試去生成 RDB 快照文件;
fork 一個子進(jìn)程出來;
子進(jìn)程嘗試將數(shù)據(jù) dump 到臨時的 RDB?快照文件中;
完成 RDB?快照文件的生成之后,就替換之前的舊的快照文件;
基于 RDB 持久化機(jī)制的數(shù)據(jù)恢復(fù)實驗
通過 redis-cli SHUTDOWN 這種方式去停掉 Redis,其實是一種安全退出的模式,Redis?在退出的時候會將內(nèi)存中的數(shù)據(jù)立即生成一份完整的 RDB 快照,存放在 /var/redis/6379/dump.rdb。
需要使用 kill -9 *** 強(qiáng)制殺死進(jìn)程的方式來模擬 Redis 異常退出。執(zhí)行步驟如下:
先往 Redis 中插入幾條數(shù)據(jù);
kill -9 強(qiáng)制殺死 Redis 進(jìn)程,刪除 /var/run/redis_6379.pid 文件,再重新啟動 Redis;
通過 redis-cli 客戶端查看剛剛插入的數(shù)據(jù),發(fā)現(xiàn)最新的幾條數(shù)據(jù)已經(jīng)丟失;
配置 save 檢查點,save 5 1(每隔5秒,如果有超過1個key發(fā)生了變更,那么就生成一個新的dump.rdb文件);
往 Redis 中插入幾條數(shù)據(jù),暫停5秒以上;
kill -9 強(qiáng)制殺死 Redis 進(jìn)程,刪除 /var/run/redis_6379.pid 文件,再重新啟動?Redis;
通過 redis-cli 客戶端查看剛剛插入的數(shù)據(jù),發(fā)現(xiàn)最新的幾條數(shù)據(jù)還在,查看?dump?文件,發(fā)現(xiàn)已經(jīng)更新為成最新的了;
Redis AOF 持久化配置和相關(guān)實驗
AOF 持久化配置
AOF 持久化配置,默認(rèn)是關(guān)閉的,默認(rèn)打開的是 RDB 持久化配置。AOF 持久化在?redis.conf 文件中配置,目前配置文件存放在 /etc/redis/6379.conf。
打開配置文件,修改 ?appendonly?屬性為 yes ,打開 AOF 持久化配置:
appendonly yesAOF 有三種 fsync 策略:
# 每次寫入一條數(shù)據(jù)就執(zhí)行一次 fsync# appendfsync always# 每隔一秒執(zhí)行一次 fsyncappendfsync everysec# 不主動執(zhí)行fsync# appendfsync no
always:每次寫入一條數(shù)據(jù),立即將這個數(shù)據(jù)對應(yīng)的寫日志 fsync 到磁盤上去,性能非常差,吞吐量很低;
everysec:每秒將 os cache 中的數(shù)據(jù) fsync 到磁盤,這個最常用的,生產(chǎn)環(huán)境一般都這么配置,性能很高,QPS還是可以上萬的;
no:Redis 只負(fù)責(zé)將數(shù)據(jù)寫入 os cache 就不管了,后面 os cache 根據(jù)自己的策略將數(shù)據(jù)刷入磁盤,不可控制;
基于 AOF 持久化機(jī)制的數(shù)據(jù)恢復(fù)實驗
設(shè)置 appendonly?屬性為 yes,打開 AOF 持久化,重啟 Redis;
往 Redis 中寫入幾條數(shù)據(jù),等待一秒;
kill -9 強(qiáng)制殺死 Redis 進(jìn)程,刪除 /var/run/redis_6379.pid 文件,再重新啟動 Redis;
通過 redis-cli 客戶端查看剛剛插入的數(shù)據(jù),發(fā)現(xiàn)最新的幾條數(shù)據(jù)還在,查看 /var/redis/6379 文件夾,發(fā)現(xiàn)已經(jīng)存在appendonly.aof 文件;
AOF rewrite 操作
Redis 中的內(nèi)存中的數(shù)據(jù)是有一定限量的,內(nèi)存到一定大小后,Redis 就會使用緩存淘汰算法(LRU)自動將一部分過期數(shù)據(jù)從內(nèi)存中清除。AOF 是存放沒有寫命令的,所以文件會不斷膨脹,當(dāng)大到一定的時候,AOF 會做 rewrite 操作。
在 redis.conf 文件中,可以配置 rewrite 策略。
# 如果 AOF 日志文件增長的比例,超過了之前的100%,就可能會去觸發(fā)一次 rewriteauto-aof-rewrite-percentage 100# 但是此時還要去跟min-size比較,大于64M才會去觸發(fā)一次 rewriteauto-aof-rewrite-min-size 64mb
AOF rewrite 操作步驟:
Redis?fork 一個子進(jìn)程;
子進(jìn)程基于當(dāng)前內(nèi)存中的數(shù)據(jù),構(gòu)建日志,開始往一個新的臨時的 AOF 文件中寫入日志;
Redis?主進(jìn)程,接收到 client 新的寫操作之后,在內(nèi)存中寫入日志,同時新的日志也繼續(xù)寫入舊的 AOF 文件;
子進(jìn)程寫完新的日志文件之后,Redis?主進(jìn)程將內(nèi)存中的新日志再次追加到新的 AOF 文件中;
用新的日志文件替換掉舊的日志文件;
AOF 破損文件的修復(fù)
如果 Redis?在 append 數(shù)據(jù)到 AOF 文件時,機(jī)器宕機(jī)了,可能會導(dǎo)致 AOF 文件破損,用 redis-check-aof --fix 命令來修復(fù)破損的 AOF 文件。
redis-check-aof --fix /usr/local/appendonly.aofAOF 和 RDB 同時工作
如果 RDB 在執(zhí)行 snapshotting 操作,那么 Redis?不會執(zhí)行 AOF rewrite; 如果 Redis?再執(zhí)行 AOF rewrite,那么就不會執(zhí)行 RDB snapshotting
如果 RDB 在執(zhí)行 snapshotting,此時用戶執(zhí)行 BGREWRITEAOF 命令,那么等 RDB 快照生成之后,才會去執(zhí)行 AOF rewrite
同時有 RDB snapshot 文件和 AOF 日志文件,那么 Redis?重啟的時候,會優(yōu)先使用 AOF 進(jìn)行數(shù)據(jù)恢復(fù),因為其中的日志更完整
企業(yè)級的數(shù)據(jù)備份方案
寫 crontab 定時調(diào)度腳本做數(shù)據(jù)備份
每小時都 copy 一份 rdb 的備份,到一個目錄中去,僅僅保留最近48小時的備份
每天都保留一份當(dāng)日的 rdb 的備份,到一個目錄中去,僅僅保留最近1個月的備份
每次 copy 備份的時候,都把太舊的備份給刪了
每天晚上將當(dāng)前服務(wù)器上所有的數(shù)據(jù)備份,發(fā)送一份到遠(yuǎn)程的云服務(wù)上去
按小時備份
redis_rdb_copy_hourly.sh
cur_date=`date +%Y%m%d%k`rm -rf /usr/local/redis/snapshotting/$cur_datemkdir /usr/local/redis/snapshotting/$cur_datecp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_datedel_date=`date -d -48hour +%Y%m%d%k`rm -rf /usr/local/redis/snapshotting/$del_date
每小時 copy 一次備份,刪除48小時前的數(shù)據(jù)。
crontab -e0 * * * * sh /usr/local/redis/copy/redis_rdb_copy_hourly.sh按天備份
redis_rdb_copy_daily.sh
cur_date=`date +%Y%m%d`rm -rf /usr/local/redis/snapshotting/$cur_datemkdir /usr/local/redis/snapshotting/$cur_datecp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_datedel_date=`date -d -1month +%Y%m%d`rm -rf /usr/local/redis/snapshotting/$del_date
每天 copy 一次備份,刪除一個月前的數(shù)據(jù)。
crontab -e0 * * * * sh /usr/local/redis/copy/redis_rdb_copy_hourly.sh0 0 * * * sh /usr/local/redis/copy/redis_rdb_copy_daily.sh
數(shù)據(jù)恢復(fù)方案
如果是 Redis?進(jìn)程掛掉,那么重啟 Redis?進(jìn)程即可,直接基于 AOF 日志文件恢復(fù)數(shù)據(jù);
如果是 Redis?進(jìn)程所在機(jī)器掛掉,那么重啟機(jī)器后,嘗試重啟 Redis?進(jìn)程,嘗試直接基于 AOF 日志文件進(jìn)行數(shù)據(jù)恢復(fù);
如果 Redis?當(dāng)前最新的 AOF 和 RDB 文件出現(xiàn)了丟失/損壞,那么可以嘗試基于該機(jī)器上當(dāng)前的某個最新的 RDB 數(shù)據(jù)副本進(jìn)行數(shù)據(jù)恢復(fù);
恢復(fù)步驟參考如下:
停止 Redis
在 Redis 配置文件中關(guān)閉 AOF?持久化配置
拷貝云服務(wù)上最新的 RDB 備份數(shù)據(jù)到?/var/redis/6379 文件夾下
重啟 Redis,確認(rèn)數(shù)據(jù)恢復(fù)
直接在命令行熱修改 Redis?配置,config set appendonly yes
確認(rèn)在?/var/redis/6379?文件夾下生成 AOF 持久化文件?appendonly.aof
停止 Redis
在 Redis 配置文件中打開 AOF 持久化配置
重啟 Redis,確認(rèn)數(shù)據(jù)情況
如果當(dāng)前機(jī)器上的所有RDB文件全部損壞,那么從遠(yuǎn)程的云服務(wù)上拉取最新的RDB快照回來恢復(fù)數(shù)據(jù)
如果是發(fā)現(xiàn)有重大的數(shù)據(jù)錯誤,比如某個小時上線的程序一下子將數(shù)據(jù)全部污染了,數(shù)據(jù)全錯了,那么可以選擇某個更早的時間點,對數(shù)據(jù)進(jìn)行恢復(fù)
舉個例子,12點上線了代碼,發(fā)現(xiàn)代碼有 bug,導(dǎo)致代碼生成的所有的緩存數(shù)據(jù)全部錯了,找到一份11點的 rdb 的冷備,然后按照上面的步驟,去恢復(fù)到11點的數(shù)據(jù),就可以了。
source: //www.yuque.com/yinjianwei/vyrvkf/hm1goc記得點「贊」和「在看」↓
愛你們
