通過redis實(shí)現(xiàn)服務(wù)器崩潰宕機(jī)的數(shù)據(jù)恢復(fù)

由于redis存儲(chǔ)在內(nèi)存中且提供一般編程語言常用的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)類型隶糕,所以經(jīng)常被用于做服務(wù)器崩潰宕機(jī)的數(shù)據(jù)恢復(fù)處理茂浮。

服務(wù)器可以在某些指定過程中將需要保存的數(shù)據(jù)以json對(duì)象等方式存儲(chǔ)到redis中租冠,也就是我們常說的快照,當(dāng)服務(wù)器運(yùn)行時(shí)讀取redis來判斷是否有待需要恢復(fù)數(shù)據(jù)繼續(xù)處理的業(yè)務(wù)。

當(dāng)一次業(yè)務(wù)處理結(jié)束后再刪除redis的數(shù)據(jù)即可甜害。

redis提供兩種將內(nèi)存數(shù)據(jù)導(dǎo)出到硬盤實(shí)現(xiàn)數(shù)據(jù)備份的方法:

RDB方式(默認(rèn))

RDB方式的持久化是通過快照(snapshotting)完成的咱枉,當(dāng)符合一定條件時(shí)Redis會(huì)自動(dòng)將內(nèi)存中的所有數(shù)據(jù)進(jìn)行快照并存儲(chǔ)在硬盤上卑硫。進(jìn)行快照的條件可以由用戶在配置文件中自定義,由兩個(gè)參數(shù)構(gòu)成:時(shí)間和改動(dòng)的鍵的個(gè)數(shù)庞钢。當(dāng)在指定的時(shí)間內(nèi)被更改的鍵的個(gè)數(shù)大于指定的數(shù)值時(shí)就會(huì)進(jìn)行快照拔恰。RDB是redis默認(rèn)采用的持久化方式,在配置文件中已經(jīng)預(yù)置了3個(gè)條件:

save 900 1? ? # 900秒內(nèi)有至少1個(gè)鍵被更改則進(jìn)行快照

save 300 10? ?# 300秒內(nèi)有至少10個(gè)鍵被更改則進(jìn)行快照

save 60 10000 # 60秒內(nèi)有至少10000個(gè)鍵被更改則進(jìn)行快照

可以存在多個(gè)條件基括,條件之間是“或”的關(guān)系颜懊,只要滿足其中一個(gè)條件,就會(huì)進(jìn)行快照。 如果想要禁用自動(dòng)快照河爹,只需要將所有的save參數(shù)刪除即可匠璧。

Redis默認(rèn)會(huì)將快照文件存儲(chǔ)在當(dāng)前目錄(可CONFIG GET dir來查看)的dump.rdb文件中,可以通過配置dir和dbfilename兩個(gè)參數(shù)分別指定快照文件的存儲(chǔ)路徑和文件名咸这。

Redis實(shí)現(xiàn)快照的過程

Redis使用fork函數(shù)復(fù)制一份當(dāng)前進(jìn)程(父進(jìn)程)的副本(子進(jìn)程)夷恍;

父進(jìn)程繼續(xù)接收并處理客戶端發(fā)來的命令,而子進(jìn)程開始將內(nèi)存中的數(shù)據(jù)寫入硬盤中的臨時(shí)文件媳维;

當(dāng)子進(jìn)程寫入完所有數(shù)據(jù)后會(huì)用該臨時(shí)文件替換舊的RDB文件酿雪,至此一次快照操作完成。

在執(zhí)行fork的時(shí)候操作系統(tǒng)(類Unix操作系統(tǒng))會(huì)使用寫時(shí)復(fù)制(copy-on-write)策略侄刽,即fork函數(shù)發(fā)生的一刻父子進(jìn)程共享同一內(nèi)存數(shù)據(jù)指黎,當(dāng)父進(jìn)程要更改其中某片數(shù)據(jù)時(shí)(如執(zhí)行一個(gè)寫命令

),操作系統(tǒng)會(huì)將該片數(shù)據(jù)復(fù)制一份以保證子進(jìn)程的數(shù)據(jù)不受影響州丹,所以新的RDB文件存儲(chǔ)的是執(zhí)行fork一刻的內(nèi)存數(shù)據(jù)醋安。

Redis在進(jìn)行快照的過程中不會(huì)修改RDB文件,只有快照結(jié)束后才會(huì)將舊的文件替換成新的墓毒,也就是說任何時(shí)候RDB文件都是完整的吓揪。這使得我們可以通過定時(shí)備份RDB文件來實(shí)

現(xiàn)Redis數(shù)據(jù)庫備份。RDB文件是經(jīng)過壓縮(可以配置rdbcompression參數(shù)以禁用壓縮節(jié)省CPU占用)的二進(jìn)制格式所计,所以占用的空間會(huì)小于內(nèi)存中的數(shù)據(jù)大小柠辞,更加利于傳輸。

除了自動(dòng)快照醉箕,還可以手動(dòng)發(fā)送SAVE或BGSAVE命令讓Redis執(zhí)行快照钾腺,兩個(gè)命令的區(qū)別在于,前者是由主進(jìn)程進(jìn)行快照操作讥裤,會(huì)阻塞住其他請(qǐng)求放棒,后者會(huì)通過fork子進(jìn)程進(jìn)行快照操作。

Redis啟動(dòng)后會(huì)讀取RDB快照文件己英,將數(shù)據(jù)從硬盤載入到內(nèi)存间螟。根據(jù)數(shù)據(jù)量大小與結(jié)構(gòu)和服務(wù)器性能不同,這個(gè)時(shí)間也不同损肛。通常將一個(gè)記錄一千萬個(gè)字符串類型鍵厢破、大小為1GB的快照文件載入到內(nèi)

存中需要花費(fèi)20~30秒鐘。

通過RDB方式實(shí)現(xiàn)持久化治拿,一旦Redis異常退出摩泪,就會(huì)丟失最后一次快照以后更改的所有數(shù)據(jù)。這就需要開發(fā)者根據(jù)具體的應(yīng)用場(chǎng)合劫谅,通過組合設(shè)置自動(dòng)快照條件的方式來將可能發(fā)生的數(shù)據(jù)損失控制在能夠接受的范圍见坑。如果數(shù)據(jù)很重要以至于無法承受任何損失嚷掠,則可以考慮使用AOF方式進(jìn)行持久化。

AOF方式

默認(rèn)情況下Redis沒有開啟AOF(append only file)方式的持久化荞驴,可以在redis.conf中通過appendonly參數(shù)開啟:

appendonly yes

在啟動(dòng)時(shí)Redis會(huì)逐個(gè)執(zhí)行AOF文件中的命令來將硬盤中的數(shù)據(jù)載入到內(nèi)存中不皆,載入的速度相較RDB會(huì)慢一些

開啟AOF持久化后每執(zhí)行一條會(huì)更改Redis中的數(shù)據(jù)的命令,Redis就會(huì)將該命令寫入硬盤中的AOF文件熊楼。AOF文件的保存位置和RDB文件的位置相同霹娄,都是通過dir參數(shù)設(shè)置的,默認(rèn)的文件名是appendonly.aof鲫骗,可以通過appendfilename參數(shù)修改:

appendfilename appendonly.aof

配置redis自動(dòng)重寫AOF文件的條件

auto-aof-rewrite-percentage 100? # 當(dāng)目前的AOF文件大小超過上一次重寫時(shí)的AOF文件大小的百分之多少時(shí)會(huì)再次進(jìn)行重寫犬耻,如果之前沒有重寫過,則以啟動(dòng)時(shí)的AOF文件大小為依據(jù)

auto-aof-rewrite-min-size 64mb? ?# 允許重寫的最小AOF文件大小

配置寫入AOF文件后执泰,要求系統(tǒng)刷新硬盤緩存的機(jī)制

# appendfsync always? ?# 每次執(zhí)行寫入都會(huì)執(zhí)行同步香追,最安全也最慢

appendfsync everysec? ?# 每秒執(zhí)行一次同步操作

# appendfsync no? ? ? ?# 不主動(dòng)進(jìn)行同步操作,而是完全交由操作系統(tǒng)來做(即每30秒一次)坦胶,最快也最不安全

Redis允許同時(shí)開啟AOF和RDB,既保證了數(shù)據(jù)安全又使得進(jìn)行備份等操作十分容易晴楔。此時(shí)重新啟動(dòng)Redis后Redis會(huì)使用AOF文件來恢復(fù)數(shù)據(jù)顿苇,因?yàn)锳OF方式的持久化可能丟失的數(shù)據(jù)更少

redis?=?require('redis'),//導(dǎo)入js模塊

RDS_PORT?=?,????????//端口號(hào)

RDS_HOST?=?'',????//服務(wù)器IP

RDS_OPTS?=?{},????????????//設(shè)置項(xiàng)

redisdb?=?redis.createClient(RDS_PORT,?RDS_HOST,?RDS_OPTS);//創(chuàng)建連接

redisdb.select(20);//指定分區(qū)庫

redisdb.on('ready',?function?(res)?{

console.log('ready');

});

redisdb.on('connect',?function?()?{

console.log('connect');

});

exports.redisdb?=?redisdb;

function?redis_opt(opt,?key,?value,?callback)?{

if?(opt?==?'get')?{

redisdb.get(key,?function?(err,?data)?{

if?(err?==?null)?{

callback(data);

}

else?{

callback(err);

}

});

}

else?if?(opt?==?'set')

{

redisdb.set(key,value,?function?(err,result)?{

if?(err?==?null)?{

callback(result);

}

else?{

callback(err);

}

});

}

else?if?(opt?==?'del')

{

redisdb.del(key,?function?(err,?result)?{

if?(err?==?null)?{

callback(result);

}

else?{

callback(err);

}

});

}

else

{

callback("error?opt!");

}

}

function?update(key)

{

redis_opt("get",?key,?null,?function?(data)?{

console.log("the?redis?data?is?"?+?data);

if?(data)?{

count?=?parseInt(data);

redis_opt("set",?key,?++count?,?function?(data)?{

console.log("set?"?+?count??+?"?"?+?data);

});

}

else?{

redis_opt("set",?key,?10000,?function?(data)?{

console.log("set?"?+?10000?+?"?"?+?data);

});

}

});

}

function?clear(key)

{

redis_opt("del",?key,?null,?function?(ret)?{

console.log("del?"?+?key?+?"?"?+?ret);

});

}

function?main()

{

var?key?=?"count_test";

setInterval(function?()?{?clear(key)?},?5000);

setInterval(function?()?{?update(key)?},?1000);

}

//testmain();

main();

以上代碼為簡單的計(jì)時(shí)器函數(shù),即服務(wù)器啟動(dòng)后定時(shí)讀取redis的數(shù)據(jù)税弃,如果存在則累加修改纪岁,不存在則初始化,同時(shí)為了方便說明则果,又設(shè)置了一個(gè)定時(shí)刪除數(shù)據(jù)的定時(shí)器幔翰。

本文來自PHP中文網(wǎng)的redis教程?欄目:https://www.php.cn/redis/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市西壮,隨后出現(xiàn)的幾起案子遗增,更是在濱河造成了極大的恐慌,老刑警劉巖款青,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件做修,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡抡草,警方通過查閱死者的電腦和手機(jī)饰及,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來康震,“玉大人燎含,你說我怎么就攤上這事⊥榷蹋” “怎么了屏箍?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铣除。 經(jīng)常有香客問我谚咬,道長,這世上最難降的妖魔是什么尚粘? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任择卦,我火速辦了婚禮,結(jié)果婚禮上郎嫁,老公的妹妹穿的比我還像新娘秉继。我一直安慰自己,他們只是感情好泽铛,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布尚辑。 她就那樣靜靜地躺著,像睡著了一般盔腔。 火紅的嫁衣襯著肌膚如雪杠茬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天弛随,我揣著相機(jī)與錄音瓢喉,去河邊找鬼。 笑死舀透,一個(gè)胖子當(dāng)著我的面吹牛栓票,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播愕够,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼走贪,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了惑芭?” 一聲冷哼從身側(cè)響起坠狡,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎遂跟,沒想到半個(gè)月后擦秽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漩勤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年感挥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片越败。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡触幼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出究飞,到底是詐尸還是另有隱情置谦,我是刑警寧澤堂鲤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站媒峡,受9級(jí)特大地震影響瘟栖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谅阿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一半哟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧签餐,春花似錦寓涨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至冠摄,卻和暖如春糯崎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背河泳。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國打工拇颅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乔询。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像韵洋,于是被迫代替她去往敵國和親竿刁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359