Redis提供了將數(shù)據(jù)定期自動(dòng)持久化至硬盤(pán)的能力狰挡,包括RDB和AOF兩種方案鹅龄,兩種方案分別有其長(zhǎng)處和短板吴趴,可以配合起來(lái)同時(shí)運(yùn)行漆诽,確保數(shù)據(jù)的穩(wěn)定性。
RDB
保存數(shù)據(jù)快照至一個(gè)RDB文件中锣枝,用于持久化厢拭。RDB操作和Mysql Dump相似。
執(zhí)行方式
- save撇叁。同步操作蚪腐,會(huì)阻塞Redis。
- bgsave税朴。調(diào)用linux的fork()回季,然后使用新的線(xiàn)程執(zhí)行復(fù)制。但是fork期間也會(huì)阻塞Redis正林,但是阻塞時(shí)間通常很短泡一。
- 自動(dòng)保存。Redis配置文件中設(shè)置了自動(dòng)保存的觸發(fā)機(jī)制觅廓,可以自定義修改鼻忠,運(yùn)行原理同bgsave。
save和bgsave的對(duì)比
注意:
- 如果機(jī)器上運(yùn)行多個(gè)Redis杈绸,需要配置RDB文件名稱(chēng)帖蔓,否則多個(gè)Redis的RDB文件會(huì)相互覆蓋。
除了上述三種執(zhí)行方式瞳脓,以下情況也會(huì)生成RDB文件:
- 主從的全量復(fù)制時(shí)塑娇,主機(jī)會(huì)生成RDB文件。
- Redis中的debug reload提供debug級(jí)別的重啟劫侧,不清空內(nèi)存的一種重啟埋酬,這種方式也會(huì)觸發(fā)RDB文件的生成。
- 執(zhí)行shutdown時(shí)烧栋,會(huì)觸發(fā)RDB文件的生成写妥。
RDB的缺點(diǎn)
- 全量數(shù)據(jù)存儲(chǔ),耗時(shí)审姓。
- 雖然fork()采用copy-on-write策略珍特,但仍消耗內(nèi)存
- 寫(xiě)RDB文件消耗大量IO性能。
AOF
采用AOF持久方式時(shí)魔吐,Redis會(huì)把每一個(gè)寫(xiě)請(qǐng)求都記錄在一個(gè)日志文件里扎筒,AOF操作和Mysql Binlog相似呼猪。通過(guò)AOF重寫(xiě)機(jī)制減少AOF文件的體積,從而減少恢復(fù)時(shí)間砸琅。
執(zhí)行方式
- always宋距。Redis的每條寫(xiě)命令都寫(xiě)入到系統(tǒng)緩沖區(qū),然后每條寫(xiě)命令都使用fsync“寫(xiě)入”硬盤(pán)症脂。
- everysec谚赎。過(guò)程與always相同,只是fsync的頻率為1秒鐘一次诱篷。這個(gè)是Redis默認(rèn)配置壶唤,如果系統(tǒng)宕機(jī),會(huì)丟失一秒左右的數(shù)據(jù)
- no棕所。由操作系統(tǒng)決定什么時(shí)候從系統(tǒng)緩沖區(qū)刷新到硬盤(pán)闸盔。
AOF重寫(xiě)
為了解決AOF文件體積膨脹的問(wèn)題,Redis提供了AOF重寫(xiě)功能:Redis服務(wù)器可以創(chuàng)建一個(gè)新的AOF文件來(lái)替代現(xiàn)有的AOF文件琳省,新舊兩個(gè)文件所保存的數(shù)據(jù)庫(kù)狀態(tài)是相同的迎吵,但是新的AOF文件不會(huì)包含任何浪費(fèi)空間的冗余命令,通常體積會(huì)較舊AOF文件小很多针贬。
AOF重寫(xiě)方式
- bgrewriteaof(流程與bgsave相似)
- AOF重寫(xiě)配置(與RDB自動(dòng)保存相似)
AOF重寫(xiě)并不需要對(duì)原有AOF文件進(jìn)行任何的讀取击费,寫(xiě)入,分析等操作桦他,這個(gè)功能是通過(guò)讀取服務(wù)器當(dāng)前的數(shù)據(jù)庫(kù)狀態(tài)來(lái)實(shí)現(xiàn)的蔫巩。
RDB vs AOF
Redis啟動(dòng)時(shí)的數(shù)據(jù)加載
Redis啟動(dòng)數(shù)據(jù)加載流程:
- AOF持久化開(kāi)啟且存在AOF文件時(shí),優(yōu)先加載AOF文件快压。
- AOF關(guān)閉或者AOF文件不存在時(shí)圆仔,加載RDB文件。
- 加載AOF/RDB文件成功后蔫劣,Redis啟動(dòng)成功坪郭。
- AOF/RDB文件存在錯(cuò)誤時(shí),Redis啟動(dòng)失敗并打印錯(cuò)誤信息拦宣。
開(kāi)發(fā)運(yùn)維中常見(jiàn)的問(wèn)題
fork操作
fork()的實(shí)際開(kāi)銷(xiāo)就是復(fù)制父進(jìn)程的頁(yè)表以及給子進(jìn)程創(chuàng)建一個(gè)進(jìn)程描述符截粗,所以速度一般比較快
內(nèi)存量越大,耗時(shí)越長(zhǎng)鸵隧;物理機(jī)相對(duì)較快,虛擬機(jī)相對(duì)較慢意推。
優(yōu)化方法
- 優(yōu)先使用物理機(jī)或者高效支持fork操作的虛擬化技術(shù)
- 控制Redis實(shí)例最大可用內(nèi)存maxmemory
- 合理配置Linux內(nèi)存分配策略:vm.overcommit_memory=1豆瘫。默認(rèn)值為0,會(huì)使Linux在內(nèi)存分配時(shí)菊值,發(fā)現(xiàn)不夠內(nèi)存不足時(shí)外驱,不會(huì)進(jìn)行分配育灸,進(jìn)而造成fork阻塞
- 降低fork頻率。例如放寬AOF重寫(xiě)自動(dòng)觸發(fā)時(shí)機(jī)或者減少不必要的主從全量復(fù)制
進(jìn)程外開(kāi)銷(xiāo)
- CPU昵宇。RDB和AOF文件生成磅崭,屬于CPU密集型。不要將Redis進(jìn)程綁定在某個(gè)CPU上,防止單核過(guò)載瓦哎;同時(shí)Redis不和CPU密集型應(yīng)用一起部署砸喻。
- 內(nèi)存。fork內(nèi)存開(kāi)銷(xiāo)蒋譬,copy-on-write割岛。
- 硬盤(pán)。AOF和RDB文件的寫(xiě)入犯助⊙⑵幔可以結(jié)合iostat和iotop進(jìn)行分析。
優(yōu)化方法
- 不要和高硬盤(pán)負(fù)載服務(wù)部署在一起:存儲(chǔ)服務(wù)剂买、消息隊(duì)列等
- 配置no-appendfsync-on-rewrite=yes惠爽。這樣在AOF重寫(xiě)的期間,不要進(jìn)行AOF追加操作(主線(xiàn)程只將數(shù)據(jù)寫(xiě)入緩沖區(qū))瞬哼,可以減少內(nèi)存的開(kāi)銷(xiāo)疆股。
但如果AOF重寫(xiě)期間,Redis宕機(jī)的話(huà)倒槐,在Linux的系統(tǒng)默認(rèn)配置下旬痹,最多會(huì)丟失30s的數(shù)據(jù)。如果無(wú)法忍受數(shù)據(jù)丟失讨越,no-appendfsync-on-rewrite配置no两残;如果應(yīng)用系統(tǒng)無(wú)法忍受延遲,而可以容忍少量的數(shù)據(jù)丟失把跨,則設(shè)置為yes人弓。
- 根據(jù)寫(xiě)入量決定磁盤(pán)類(lèi)型:例如ssd
- 單機(jī)多實(shí)例持久化文件目錄可以考慮分盤(pán),或者使用類(lèi)似cgroups機(jī)制進(jìn)行硬盤(pán)資源的合理分配
AOF追加阻塞
例如在AOF的everysec策略中着逐,主線(xiàn)程會(huì)對(duì)比上次fsync的時(shí)間崔赌,如果距離上次fsync時(shí)間超過(guò)兩秒,就會(huì)造成主線(xiàn)程阻塞(等待同步線(xiàn)程同步完成)耸别。
日常開(kāi)發(fā)可以使用info persistence
命令健芭,查看歷史發(fā)生AOF阻塞的次數(shù);然而需要了解AOF追加阻塞的發(fā)生時(shí)間則需要查看Redis日志秀姐。
發(fā)送AOF追加阻塞的時(shí)候慈迈,日志如下:
Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
優(yōu)化方法(參考其他方面的優(yōu)化點(diǎn))