Redis数据持久化
總的來說有兩種持久化方案:RDB和AOF
RDB方式按照一定的時(shí)間間隔對數(shù)據(jù)集創(chuàng)建基于時(shí)間點(diǎn)的快照。
AOF方式記錄Server收到的寫操作到日志文件,在Server重啟時(shí)通過回放這些寫操作來重建數(shù)據(jù)集。該方式類似于MySQL中基于語句格式的binlog。當(dāng)日志變大時(shí)Redis可在后臺重寫日志。
若僅期望數(shù)據(jù)在Server運(yùn)行期間存在則可禁用兩種持久化方案。在同一Redis實(shí)例中同時(shí)開啟AOF和RDB方式的數(shù)據(jù)持久化方案也是可以的。該情況下Redis重啟時(shí)AOF文件將用于重建原始數(shù)據(jù)集,因?yàn)榻蠷DB方式而言,AOF方式能最大限度的保證數(shù)據(jù)完整性。
兩鐘方案各自的優(yōu)缺點(diǎn)
RDB優(yōu)點(diǎn)
RDB是Redis數(shù)據(jù)集的基于時(shí)間點(diǎn)的緊湊的副本,非常適合于備份場景。比如每個小時(shí)對RDB文件做一次小的歸檔,每天對RDB文件做一次大的歸檔,每月對RDB文件做一次更大的歸檔。這樣可以在必要的時(shí)刻選擇不同的備份版本進(jìn)行數(shù)據(jù)恢復(fù)。
由于是一個緊湊的文件,易于傳輸?shù)竭h(yuǎn)程數(shù)據(jù)中心或Amazon S3,因此RDB非常適合于災(zāi)難恢復(fù)。
RDB方式的開銷較低,在該種方式下Redis父進(jìn)程所要做的僅是開辟一個子進(jìn)程來做剩下的事情。
與AOF相比RDB在數(shù)據(jù)集較大時(shí)能夠以更快的速度恢復(fù)。
RDB缺點(diǎn)
若需在Redis停止工作時(shí)(例如意外斷電)盡可能保證數(shù)據(jù)不丟失,那么RDB不是最好的方案。例如,通常會每隔5分鐘或者更長的時(shí)間來創(chuàng)建一次快照,如若Redis沒有被正確的關(guān)閉就可能丟失最近幾分鐘的數(shù)據(jù)。
RDB方式需經(jīng)常調(diào)用fork()函數(shù)以開辟子進(jìn)程來實(shí)現(xiàn)持久化。在數(shù)據(jù)集較大、CPU性能不夠強(qiáng)悍時(shí)fork()調(diào)用可能很耗時(shí)從而會導(dǎo)致Redis在幾毫秒甚至一秒中的時(shí)間內(nèi)不能服務(wù)clients。AOF也需要調(diào)用fork()但卻可以在不影響數(shù)據(jù)持久性的條件下調(diào)整重寫logs的頻率。
AOF優(yōu)點(diǎn)
使用AOF方式時(shí)Redis持久化更可靠:有三種不同的fsync策略供選擇:no fsync at all、fsync every second、 fsync at every query。默認(rèn)為fsync every second此時(shí)的寫性能仍然很好,且最壞的情況下可能丟失一秒鐘的寫操作。
AOF日志是append only方式產(chǎn)生的日志,因此不存在隨機(jī)訪問問題以及意外斷電時(shí)造成的損毀問題。即使出于某種原因(如磁盤滿)日志以一個寫了一半的命令結(jié)尾,仍可以使用redis-check-aof工具快速進(jìn)行修復(fù)。
當(dāng)AOF日志逐漸變大后,Redis可在后臺自動的重寫AOF日志。當(dāng)Redis在繼續(xù)追加舊的AOF日志文件時(shí)重寫日志是完全安全的。Redis利用可以重建當(dāng)前數(shù)據(jù)集的最少的命令產(chǎn)生一個全新的日志文件,一旦新的日志文件創(chuàng)建完成Redis開始向新的日志文件追加日志。
AOF日志的格式易于理解易于解析。這在某些場景非常有用。比如,不下心使用FLUSHALL命令清空了所有的數(shù)據(jù),同時(shí)AOF日志沒有發(fā)生重寫操作,那么就可以簡單的通過停止Redis Server移除日志中的最后一條FLUSHALL命令重啟Redis Server來恢復(fù)數(shù)據(jù)。
AOF缺點(diǎn)
同樣的數(shù)據(jù)集AOF文件要比RDB文件大很多。
根據(jù)使用的fsync方式不同AOF可能比RDB慢很多。在使用no fsync at all時(shí)AOF的性能基本與RDB持平,在使用fsync every second時(shí)性能有所下降但仍然較高,在使用 fsync at every query時(shí)性能較低。然而RDB方式卻能在高負(fù)載的情況下保證延遲盡可能小。
一些特定的命令可能存在bug從而導(dǎo)致重載AOF日志時(shí)不能重建出完全一樣的數(shù)據(jù)集。這樣的bugs非常非常罕見,已經(jīng)通過測試套件做了充分的測試。這種類型的bugs對于RDB來說幾乎是不可能的。說的更清晰一點(diǎn):Redis AOF增量的更新既存的狀態(tài)而RDB快照每次都重新創(chuàng)建,從概念上講RDB方式更加健壯。然而,需要注意兩點(diǎn):每次AOF日志被Redis重寫的時(shí)候日志由包含數(shù)據(jù)集的實(shí)際數(shù)據(jù)重新生成,與追加AOF文件的方式相比該方式能有效減少bugs出現(xiàn)的概率;現(xiàn)實(shí)的應(yīng)用場景中還未收到過任何用戶關(guān)于AOF損毀的報(bào)告。
如何選擇持久化方式?
取決于具體的應(yīng)用場景,通常,兩種方式可同時(shí)使用。若比較關(guān)心數(shù)據(jù)但仍能忍受幾分鐘的數(shù)據(jù)丟失,那么可以簡單的使用RDB方式。有許多用戶只使用AOF方式,不建議這種做法,一方面以一定時(shí)間間隔創(chuàng)建RDB快照是創(chuàng)建數(shù)據(jù)備份并快速恢復(fù)數(shù)據(jù)的極好的辦法,一方面可以避免AOF方式可能存在的bugs。出于上述原因,將來可能將AOF和RDB方式合二為一。
RDB持久化設(shè)置
默認(rèn)情況下Redis在磁盤上創(chuàng)建二進(jìn)制格式的命名為dump.rdb的數(shù)據(jù)快照。可以通過配置文件配置每隔N秒且數(shù)據(jù)集上至少有M個變化時(shí)創(chuàng)建快照、是否對數(shù)據(jù)進(jìn)行壓縮、快照名稱、存放快照的工作目錄。redis 2.4.10的默認(rèn)配置如下:
關(guān)于配置參數(shù)的詳細(xì)信息可參閱redis.conf中的說明。
除了通過配置文件進(jìn)行設(shè)置外也可以通過手工執(zhí)行命令來創(chuàng)建快照
SAVE命令執(zhí)行一個同步操作,以RDB文件的方式保存實(shí)例中所有數(shù)據(jù)的快照。一般不在生產(chǎn)環(huán)境直接使用SAVE 命令,因?yàn)闀枞械目蛻舳说恼埱?#xff0c;可以使用BGSAVE命令代替。BGSAVE后臺創(chuàng)建數(shù)據(jù)快照。命名執(zhí)行結(jié)果的狀態(tài)碼會立即返回。Redis開辟一個子進(jìn)程,父進(jìn)程繼續(xù)相應(yīng)客戶端請求,子進(jìn)程保存DB到磁盤后退出。客戶端可通過執(zhí)行LASTSAVE命令檢查操作是否成功。
創(chuàng)建RDB快照的工作流程
Redis需dump數(shù)據(jù)集到磁盤時(shí)會執(zhí)行下列過程:
Redis forks一個子進(jìn)程;
子進(jìn)程寫數(shù)據(jù)集到臨時(shí)的RDB文件;
子進(jìn)程寫完新的RDB文件后替換舊的RDB文件。
該方式使Redis可以利用copy-on-write機(jī)制的好處。
AOF持久化設(shè)置
利用快照的持久化方式不是非常可靠,當(dāng)運(yùn)行Redis的計(jì)算機(jī)停止工作、意外掉電、意外殺掉了Redis進(jìn)程那么最近寫入Redis的數(shù)據(jù)將會丟。對于某些應(yīng)用這或許不成問題,但對于持久化要求非常高的應(yīng)用場景快照方式不是理想的選擇。AOF文件是一個替代方案,用以最大限度的持久化數(shù)據(jù)。同樣,可以通過配置文件來開閉AOF:
當(dāng)設(shè)置appendonly為yes后,每次Redis接收到的改變數(shù)據(jù)集的命令都會被追加到AOF文件。重啟Redis后會重放AOF文件來重建數(shù)據(jù)。
?
還可以通過配置文件配置AOF文件名、調(diào)用fsync的頻率、調(diào)用fsync的行為、重寫AOF的條件。redis 2.4.10的默認(rèn)配置如下:
#默認(rèn)AOF文件名 appendfilename appendonly.aof #每秒調(diào)用一次fsync刷新數(shù)據(jù)到磁盤 appendfsync everysec #當(dāng)進(jìn)程中BGSAVE或BGREWRITEAOF命令正在執(zhí)行時(shí)不阻止主進(jìn)程中的fsync()調(diào)用(默認(rèn)為no,當(dāng)存在延遲問題時(shí)需調(diào)整為yes) no-appendfsync-on-rewrite no #當(dāng)AOF增長率為100%且達(dá)到了64mb時(shí)開始自動重寫AOF auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb各參數(shù)含義可參閱redis.conf中詳細(xì)說明。
幾點(diǎn)說明
日志重寫
隨著Redis接收到的命令的增加AOF文件會變得越來越大。Redis支持日志重寫特性,可以在不影響響應(yīng)客戶端的前提下在后臺重構(gòu)AOF文件。當(dāng)在Redis中執(zhí)行BGREWRITEAOF后Redis將使用構(gòu)建數(shù)據(jù)集所需的最少的命令來重構(gòu)日志文件。Redis2.2中需要經(jīng)常手動運(yùn)行BGREWRITEAOF,Redis2.2開始支持自動觸發(fā)日志重寫。
日志重寫同樣使用copy-on-write機(jī)制,流程大致如下:
Redis開辟一個子進(jìn)程;
子進(jìn)程在臨時(shí)文件中寫新的AOF文件;
父進(jìn)程將所有新的更改緩存在memory中(同時(shí)新更改被寫入舊的AOF,這樣即使重寫操作失敗了也是安全的);
在子進(jìn)程重寫好臨時(shí)AOF后父進(jìn)程收到一個信號并追加memory中緩沖的更改到子進(jìn)程產(chǎn)生的臨時(shí)文件的末尾;
Redis進(jìn)行文件重命名用新的文件替換舊的文件并開始追加新的數(shù)據(jù)到新文件。
fsync調(diào)用模式
該模式?jīng)Q定了Redis刷新數(shù)據(jù)到磁盤的頻率,有三個可選項(xiàng):
no fsync at all 全由操作系統(tǒng)決定刷數(shù)據(jù)的時(shí)機(jī)。最快但最不安全。
fsync every second 每秒一次刷新。足夠快,最多可丟失一秒的數(shù)據(jù)。
fsync at every query 每次記錄一條新的命令到AOF便刷一次數(shù)據(jù)到磁盤。最慢但最安全。
默認(rèn)策略(也是默認(rèn)策略)為fsync every second
AOF損壞時(shí)的對策
若在寫AOF文件時(shí)Server崩潰則可能導(dǎo)致AOF文件損壞而不能被Redis載入。可通過如下步驟修復(fù):
創(chuàng)建一個AOF文件的備份;
使用redis-check-aof工具修復(fù)原始的AOF文件;
$ redis-check-aof --fix
使用diff -u 檢查備份文件和修復(fù)后文件的異同(可選步驟);
使用修復(fù)后的AOF文件重啟Redis。
如何由RDB持久化轉(zhuǎn)換到AOF持久化?
Redis >=2.2時(shí)
創(chuàng)建最近的RDB文件的備份;
將備份保存在安全的位置;
發(fā)起如下命令;
$redis-cli config set appendonly yes
$redis-cli config set save ""(可選,若不執(zhí)行RDB和AOF方式將并存)
確認(rèn)數(shù)據(jù)庫包含相同的keys;
確認(rèn)write操作被正確追加到了AOF文件。
注意事項(xiàng):記得修改redis.conf中對應(yīng)的配置以免Redis Server重啟后通過命令進(jìn)行的配置更新丟失而重新使用舊的配置文件中配置。
Redis2.0時(shí)
創(chuàng)建最近的RDB文件的備份;
將備份存放在安全的位置;
停止數(shù)據(jù)庫上的所有寫操作;
發(fā)起 redis-cli bgrewriteaof命令創(chuàng)建AOF文件;
當(dāng)AOF文件生成后停止Redis Server;
編輯redis.conf開啟AOF持久化;
重啟Redis Server;
確認(rèn)數(shù)據(jù)庫包含相同的keys;
確認(rèn)write操作被正確追加到了AOF文件。
AOF與RDB之間的相互影響
Redis2.4以上的版本會確保在RDB快照創(chuàng)建時(shí)不觸發(fā)AOF重寫或者在AOF重寫時(shí)不允許BGSAVE操作,以避免Redis后臺進(jìn)程同時(shí)做繁重的磁盤I/O操作。
當(dāng)創(chuàng)建RDB快照時(shí)對于用戶使用BGREWRITEAOF明確發(fā)起的日志重寫操作server會立刻回應(yīng)一個ok狀態(tài)碼告知用戶操作將回被執(zhí)行,當(dāng)且僅當(dāng)快照創(chuàng)建完成后重寫操作開始被執(zhí)行。
在同時(shí)使用了AOF和RDB方式的情況下,Redis重啟后會優(yōu)先使用AOF文件來重構(gòu)原始數(shù)據(jù)集。
備份Redis 數(shù)據(jù)
務(wù)必做好數(shù)據(jù)備份以防意外丟失。Redis是備份友好的,可在數(shù)據(jù)庫運(yùn)行時(shí)拷貝RDB文件。建議的備份方案:
創(chuàng)建一個cron作業(yè)在一個目錄中每小時(shí)創(chuàng)建一次RDB快照在另一目錄中每天創(chuàng)建一次RDB快照;
cron作業(yè)每次運(yùn)行的時(shí)候使用find命令確保過時(shí)的RDB快照文件被清理掉(可以通過在快照命中包含數(shù)據(jù)和時(shí)間信息來進(jìn)行標(biāo)記);
確保將RDB快照轉(zhuǎn)移到外部的數(shù)據(jù)中心或者至少是運(yùn)行Redis實(shí)例的物理機(jī)之外的機(jī)器(至少每天一次)。
災(zāi)難恢復(fù)
在Redis中災(zāi)難恢復(fù)和數(shù)據(jù)備份基本上是同樣的過程。可考慮將備份分布到不同的遠(yuǎn)程數(shù)據(jù)中心以最大限度的避免數(shù)據(jù)丟失。幾種低成本的災(zāi)難恢復(fù)計(jì)劃:
Amazon S3或其它類似服務(wù)是很好的選擇。可將每天會每小時(shí)的RDB快照以加密的方式(可使用gpg -c加密)傳輸?shù)絊3。確保將密碼存儲在不同的安全的地方。建議使用不同的存儲服務(wù)以提高數(shù)據(jù)安全性。
使用SCP命令將快照傳輸?shù)竭h(yuǎn)程服務(wù)器。最簡單和安全的方式:獲取一個小的遠(yuǎn)程VPS,在其上安裝ssh,生成無密碼的ssh client key添加到VPS的authorized_keys文件,此后便可使用SCP傳輸備份到VPS了。建議搞兩個不同的VPS以提高安全性。
需要注意的是,文件傳輸完成后一定要校驗(yàn)文件的完整性正確性。可通過MD5或SHA1進(jìn)行驗(yàn)證。另外需要搭建一套告警系統(tǒng),當(dāng)備份傳輸發(fā)生問題時(shí)能及時(shí)的告知。
轉(zhuǎn)載于:https://my.oschina.net/vshcxl/blog/869074
總結(jié)
以上是生活随笔為你收集整理的Redis数据持久化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android AsyncTask 的分
- 下一篇: MySQL 架构组成—存储引擎