文章首發(fā):Redis的持久化堡赔、數(shù)據(jù)備份方案和數(shù)據(jù)恢復(fù)
redis的持久化
RDB持久化
redis會(huì)fork創(chuàng)建一個(gè)子進(jìn)程來(lái)進(jìn)行持久化廓啊。將數(shù)據(jù)寫(xiě)進(jìn)一個(gè)臨時(shí)文件,持久化結(jié)束之后會(huì)替換上一個(gè)持久化好的RDB文件牛曹。在這期間redis主進(jìn)程不會(huì)參與持久化,以保證redis的高性能醇滥。
觸發(fā):
客戶(hù)端在執(zhí)行shutdown命令時(shí)黎比,如果沒(méi)有開(kāi)啟AOF持久化,那么就會(huì)觸發(fā)RDB的持久化鸳玩。
-
在redis的配置文件中有以下默認(rèn)配置阅虫。在一下的條件成立時(shí),就會(huì)觸發(fā)RDB的持久化不跟,而且是使用save命令完成的颓帝。但是save命令會(huì)阻塞主進(jìn)程。一般使用bgsave命令窝革,會(huì)fork出一個(gè)子進(jìn)程進(jìn)行持久化操作购城。
save 900 1 #after 900 sec (15 min) if at least 1 key changed save 300 10 #after 300 sec (5 min) if at least 10 keys changed save 60 10000 #after 60 sec if at least 10000 keys changed
執(zhí)行flushall命令清空內(nèi)存中的數(shù)據(jù)時(shí),同時(shí)觸發(fā)持久化虐译,清空磁盤(pán)工猜。
優(yōu)點(diǎn)和缺點(diǎn)
優(yōu)點(diǎn):數(shù)據(jù)恢復(fù)比較快,適合大規(guī)模的數(shù)據(jù)恢復(fù)菱蔬,適合當(dāng)作冷備的方案篷帅。
缺點(diǎn):如果是突然宕機(jī)史侣,丟失的數(shù)據(jù)比較多。數(shù)據(jù)量大時(shí)魏身,持久化生成快照RDB文件會(huì)影響redis的性能惊橱。
AOF持久化
開(kāi)啟了AOF之后,會(huì)將所有命令追加到AOF緩沖區(qū)中箭昵,根據(jù)對(duì)應(yīng)的寫(xiě)入策略寫(xiě)入到磁盤(pán)的AOF的持久化文件中税朴。可以說(shuō)就是redis的一個(gè)日志文件家制,里面記錄的是redis的寫(xiě)操作正林。但是由于記錄的是一條條命令,AOF文件會(huì)膨脹的很快颤殴,達(dá)到一定量的時(shí)候觅廓,就會(huì)觸發(fā)rewrite操作,重寫(xiě)AOF文件涵但,來(lái)達(dá)到壓縮的目的(fork子進(jìn)程來(lái)完成)杈绸。
redis 使用單線程響應(yīng)命令,如果每次寫(xiě) AOF 文件命令都直接追加到硬盤(pán)矮瘟,那么性能瓶頸完全取于當(dāng)前硬盤(pán)負(fù)載瞳脓。先寫(xiě)入緩沖區(qū) aof_buf 中,還有另一好處澈侠,redis 可以提供多種緩沖區(qū)同步硬盤(pán)的策略劫侧,在性能和安全性方面做出權(quán)衡。
觸發(fā):
- redis的配置文件中默認(rèn)是沒(méi)有開(kāi)啟AOF的哨啃,要開(kāi)啟在配置文件中打開(kāi)即可
appendonly no
--->appendonly yes
板辽。也可以在redis已經(jīng)運(yùn)行時(shí)設(shè)置:CONFIG SET appendonly yes
,不過(guò)這樣當(dāng)redis重啟時(shí)棘催,設(shè)置會(huì)失效劲弦。 - 配置的寫(xiě)入策略觸發(fā)。
-
appendfsync everysec
(默認(rèn)):每秒同步一次命令到AOF持久化文件中醇坝,效率很高邑跪,可能會(huì)丟失1秒的數(shù)據(jù)。 -
appendfsync no
:從不同步呼猪,只需將數(shù)據(jù)交給操作系統(tǒng)即可画畅。更快,更不安全的方法宋距。通常轴踱,Linux將使用此配置每30秒刷新一次數(shù)據(jù),但這取決于內(nèi)核的精確調(diào)整谚赎。 -
appendfsync always
:每次觸發(fā)數(shù)據(jù)變更的時(shí)候立即追加到AOF文件中淫僻,效率很低诱篷,但是很安全。
-
重寫(xiě)機(jī)制:
-
默認(rèn)配置雳灵。比如說(shuō)上一次AOF rewrite之后棕所,是128mb。然后就會(huì)接著128mb繼續(xù)寫(xiě)AOF的日志悯辙,如果發(fā)現(xiàn)增長(zhǎng)的比例琳省,超過(guò)了之前的100%,256mb躲撰,就可能會(huì)去觸發(fā)一次rewrite针贬。但是此時(shí)還要去跟min-size,64mb去比較拢蛋,256mb > 64mb桦他,才會(huì)去觸發(fā)rewrite。
因?yàn)锳OF文件的重寫(xiě)會(huì)fork出一個(gè)子進(jìn)程進(jìn)行重寫(xiě)瓤狐,為了減少重寫(xiě)次數(shù)需要調(diào)大下面的參數(shù)瞬铸,但是都是要基于自身使用的redis的存放的數(shù)據(jù)量來(lái)決定批幌。
auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
優(yōu)點(diǎn)和缺點(diǎn):
優(yōu)點(diǎn):以更好的保護(hù)數(shù)據(jù)不丟失础锐,一般AOF會(huì)每隔1秒(默認(rèn)的同步策略),通過(guò)一個(gè)后臺(tái)線程執(zhí)行一次fsync操作荧缘,最多丟失1秒鐘的數(shù)據(jù)皆警。
AOF日志文件以append-only模式寫(xiě)入,所以沒(méi)有任何磁盤(pán)尋址的開(kāi)銷(xiāo)截粗,寫(xiě)入性能非常高信姓,而且文件不容易破損,即使文件尾部破損绸罗,也很容易修復(fù)(使用redis提供的工具可以修復(fù):redis-check-aof --fix
)意推。
日志文件即使過(guò)大的時(shí)候,出現(xiàn)后臺(tái)重寫(xiě)操作珊蟀,也不會(huì)影響客戶(hù)端的讀寫(xiě)菊值。因?yàn)樵趓ewrite log的時(shí)候,會(huì)對(duì)其中的指導(dǎo)進(jìn)行壓縮育灸,創(chuàng)建出一份需要恢復(fù)數(shù)據(jù)的最小日志出來(lái)腻窒。再創(chuàng)建新日志文件的時(shí)候,老的日志文件還是照常寫(xiě)入磅崭。當(dāng)新的merge后的日志文件ready的時(shí)候儿子,再交換新老日志文件即可。
AOF日志文件的命令通過(guò)非吃矣鳎可讀的方式進(jìn)行記錄柔逼,這個(gè)特性非常適合做災(zāi)難性的誤刪除的緊急恢復(fù)蒋譬。比如某人不小心用flushall命令清空了所有數(shù)據(jù),只要這個(gè)時(shí)候后臺(tái)rewrite還沒(méi)有發(fā)生卒落,那么就可以立即拷貝AOF文件羡铲,將最后一條flushall命令給刪了,然后再將該AOF文件放回去儡毕,就可以通過(guò)恢復(fù)機(jī)制也切,自動(dòng)恢復(fù)所有數(shù)據(jù)
缺點(diǎn):對(duì)于同一份數(shù)據(jù)來(lái)說(shuō),AOF日志文件通常比RDB數(shù)據(jù)快照文件更大腰湾。
AOF開(kāi)啟后雷恃,支持的寫(xiě)QPS會(huì)比RDB支持的寫(xiě)QPS低,因?yàn)锳OF一般會(huì)配置成每秒fsync一次日志文件费坊,當(dāng)然倒槐,每秒一次fsync,性能也還是很高的附井。
類(lèi)似AOF這種較為復(fù)雜的基于命令日志/merge/回放的方式讨越,比基于RDB每次持久化一份完整的數(shù)據(jù)快照文件的方式,更加脆弱一些永毅,容易有bug把跨。不過(guò)AOF就是為了避免rewrite過(guò)程導(dǎo)致的bug,因此每次rewrite并不是基于舊的指令日志進(jìn)行merge的沼死,而是基于當(dāng)時(shí)內(nèi)存中的數(shù)據(jù)進(jìn)行指令的重新構(gòu)建着逐,這樣健壯性會(huì)好很多。
RDB和AOF到底該如何選擇
不要僅僅使用RDB意蛀,因?yàn)槟菢訒?huì)導(dǎo)致你丟失很多數(shù)據(jù)
也不要僅僅使用AOF耸别,因?yàn)槟菢佑袃蓚€(gè)問(wèn)題,第一县钥,你通過(guò)AOF做冷備秀姐,沒(méi)有RDB做冷備,來(lái)的恢復(fù)速度更快; 第二若贮,RDB每次簡(jiǎn)單粗暴生成數(shù)據(jù)快照省有,更加健壯,可以避免AOF這種復(fù)雜的備份和恢復(fù)機(jī)制的bug
綜合使用AOF和RDB兩種持久化機(jī)制兜看,用AOF來(lái)保證數(shù)據(jù)不丟失锥咸,作為數(shù)據(jù)恢復(fù)的第一選擇; 用RDB來(lái)做不同程度的冷備,在AOF文件都丟失或損壞不可用的時(shí)候细移,還可以使用RDB來(lái)進(jìn)行快速的數(shù)據(jù)恢復(fù)
所以說(shuō)成年人搏予,全都要!
AOF和RDB同時(shí)工作:
- 如果RDB在執(zhí)行snapshotting操作弧轧,那么redis不會(huì)執(zhí)行AOF rewrite; 如果redis再執(zhí)行AOF rewrite雪侥,那么就不會(huì)執(zhí)行RDB snapshotting
- 如果RDB在執(zhí)行snapshotting碗殷,此時(shí)用戶(hù)執(zhí)行BGREWRITEAOF命令,那么等RDB快照生成之后速缨,才會(huì)去執(zhí)行AOF rewrite
- 同時(shí)有RDB snapshot文件和AOF日志文件锌妻,那么redis重啟的時(shí)候,會(huì)優(yōu)先使用AOF進(jìn)行數(shù)據(jù)恢復(fù)旬牲,因?yàn)槠渲械娜罩靖暾?/li>
redis持久化文件加載流程
- 首先是會(huì)去判斷是否開(kāi)啟了AOF仿粹,如果存在存在AOF文件,則直接加載AOF文件
- 如果找不到AOF文件原茅,則直接啟動(dòng)吭历,不會(huì)加載RDB文件
- 如果沒(méi)有開(kāi)啟AOF,會(huì)去加載RDB文件擂橘,通過(guò)RDB恢復(fù)數(shù)據(jù)
數(shù)據(jù)備份方案
- 寫(xiě)crontab定時(shí)調(diào)度腳本去做數(shù)據(jù)備份
- 每小時(shí)都copy一份rdb的備份晌区,到一個(gè)目錄中去,僅僅保留最近48小時(shí)的備份
- 每天都保留一份當(dāng)日的rdb的備份通贞,到一個(gè)目錄中去朗若,僅僅保留最近1個(gè)月的備份
- 每次copy備份的時(shí)候,都把太舊的備份給刪了(是否刪除舊的備份昌罩,看具體情況而定)
- 每天晚上將當(dāng)前服務(wù)器上所有的數(shù)據(jù)備份哭懈,發(fā)送一份到遠(yuǎn)程的云服務(wù)器(用于存放備份即可,也可以存放在本地)上去峡迷。
每小時(shí)備份一次:redis_rdb_backup_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
# 備份發(fā)送到備份服務(wù)器银伟,注意免密碼登錄
# scp -rq /var/redis/6379/dump.rdb root@192.168.129.100:/opt
# 刪除最近48小時(shí)的rdb文件
del_date=`date -d -48hour +%Y%m%d%k`
rm -rf /usr/local/redis/snapshotting/$del_date
每小時(shí)執(zhí)行一次該腳本:0 0 * * * ? sh /usr/local/redis/shell/redis_rdb_backup_hourly.sh
每天備份一次:redis_rdb_backup_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 -1day +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$del_date
每天執(zhí)行一次備份腳本:0 0 0 * * ? sh /usr/local/redis/shell/redis_rdb_backup_daily.sh
數(shù)據(jù)恢復(fù)方案
(1)如果是redis進(jìn)程掛掉你虹,那么重啟redis進(jìn)程即可绘搞,直接基于AOF日志文件恢復(fù)數(shù)據(jù)
(2)如果是redis進(jìn)程所在機(jī)器掛掉,那么重啟機(jī)器后傅物,嘗試重啟redis進(jìn)程夯辖,嘗試直接基于AOF日志文件進(jìn)行數(shù)據(jù)恢復(fù)。AOF沒(méi)有破損董饰,也是可以直接基于AOF恢復(fù)的蒿褂。AOF append-only,順序?qū)懭胱湓荩绻鸄OF文件破損啄栓,那么用redis-check-aof fix
(3)如果redis當(dāng)前最新的AOF和RDB文件出現(xiàn)了丟失/損壞,那么可以嘗試基于該機(jī)器上當(dāng)前的某個(gè)最新的RDB數(shù)據(jù)副本進(jìn)行數(shù)據(jù)恢復(fù)也祠。
當(dāng)前最新的AOF和RDB文件都出現(xiàn)了丟失/損壞到無(wú)法恢復(fù)昙楚,一般不是機(jī)器的故障,人為诈嘿。那就把破損的文件給刪除了堪旧。去備份服務(wù)器找到RDB最新的一份備份削葱,小時(shí)級(jí)的備份可以了,小時(shí)級(jí)的肯定是最新的淳梦,copy到redis里面去析砸,就可以恢復(fù)到某一個(gè)小時(shí)的數(shù)據(jù)
停止redis,關(guān)閉aof爆袍,拷貝rdb備份首繁,重啟redis,確認(rèn)數(shù)據(jù)恢復(fù)陨囊,直接在命令行熱修改redis配置蛮瞄,打開(kāi)aof,這個(gè)redis就會(huì)將內(nèi)存中的數(shù)據(jù)對(duì)應(yīng)的日志谆扎,寫(xiě)入aof文件中
此時(shí)aof和rdb兩份數(shù)據(jù)文件的數(shù)據(jù)就同步了
redis config set熱修改配置參數(shù)挂捅,可能配置文件中的實(shí)際的參數(shù)沒(méi)有被持久化的修改,再次停止redis堂湖,手動(dòng)修改配置文件闲先,打開(kāi)aof的命令,再次重啟redis
(4)如果當(dāng)前機(jī)器上的所有RDB文件全部損壞无蜂,那么從遠(yuǎn)程的云服務(wù)上拉取最新的RDB快照回來(lái)恢復(fù)數(shù)據(jù)
(5)如果是發(fā)現(xiàn)有重大的數(shù)據(jù)錯(cuò)誤伺糠,比如某個(gè)小時(shí)上線的程序一下子將數(shù)據(jù)全部污染了,數(shù)據(jù)全錯(cuò)了斥季,那么可以選擇某個(gè)更早的時(shí)間點(diǎn)训桶,對(duì)數(shù)據(jù)進(jìn)行恢復(fù)
舉個(gè)例子,12點(diǎn)上線了代碼酣倾,發(fā)現(xiàn)代碼有bug舵揭,導(dǎo)致代碼生成的所有的緩存數(shù)據(jù),寫(xiě)入redis躁锡,全部錯(cuò)了
找到一份11點(diǎn)的rdb的冷備午绳,然后按照上面的步驟,去恢復(fù)到11點(diǎn)的數(shù)據(jù)映之。