對(duì)長(zhǎng)期奮戰(zhàn)在一線的后端開發(fā)人員來說,,都知道redis有兩種持久化方式RDB和AOF,,雖說大家都知道這兩種方式大概運(yùn)作方式,但想必有實(shí)操的人不會(huì)太多,。 這里是自己實(shí)操兩種持久化方式的一點(diǎn)點(diǎn)記錄,。 先看以下摘錄自redis官網(wǎng)原文解釋(原文是English,這里用google翻譯,。) Redis持久性 Redis提供了不同的持久性選項(xiàng)范圍:
RDB持久性按指定的時(shí)間間隔執(zhí)行數(shù)據(jù)集的時(shí)間點(diǎn)快照,。 AOF持久性會(huì)記錄服務(wù)器接收的每個(gè)寫入操作,這些操作將在服務(wù)器啟動(dòng)時(shí)再次播放,,以重建原始數(shù)據(jù)集,。 使用與Redis協(xié)議本身相同的格式記錄命令,并且僅采用追加方式,。 當(dāng)日志太大時(shí),,Redis可以在后臺(tái)重寫日志,。 如果希望,只要您的數(shù)據(jù)在服務(wù)器運(yùn)行時(shí)就一直存在,,則可以完全禁用持久性,。 可以在同一實(shí)例中同時(shí)合并AOF和RDB。 請(qǐng)注意,,在這種情況下,,當(dāng)Redis重新啟動(dòng)時(shí),AOF文件將用于重建原始數(shù)據(jù)集,,因?yàn)樗梢员WC是最完整的,。 要理解的最重要的事情是RDB與AOF持久性之間的不同權(quán)衡。 讓我們從RDB開始:
RDB的優(yōu)勢(shì) RDB是Redis數(shù)據(jù)的非常緊湊的單文件時(shí)間點(diǎn)表示,。 RDB文件非常適合備份,。 例如,您可能希望在最近的24小時(shí)內(nèi)每小時(shí)存檔一次RDB文件,,并在30天之內(nèi)每天保存一次RDB快照,。 這使您可以在發(fā)生災(zāi)難時(shí)輕松還原數(shù)據(jù)集的不同版本。 RDB對(duì)于災(zāi)難恢復(fù)非常有用,,它是一個(gè)緊湊的文件,,可以傳輸?shù)竭h(yuǎn)程數(shù)據(jù)中心或Amazon S3(可能已加密)上。 RDB最大限度地提高了Redis的性能,,因?yàn)?span id="3squ974rb" class="s3">Redis父進(jìn)程為了持久化所需要做的唯一工作就是分叉一個(gè)孩子,,其余的都將做。 父實(shí)例將永遠(yuǎn)不會(huì)執(zhí)行磁盤I / O或類似操作,。 與AOF相比,,RDB允許大型數(shù)據(jù)集更快地重啟。
RDB的缺點(diǎn) 如果您需要在Redis停止工作(例如斷電后)的情況下最大程度地減少數(shù)據(jù)丟失的機(jī)會(huì),,則RDB不好,。 您可以在生成RDB的位置配置不同的保存點(diǎn) (例如,在至少五分鐘之后,,對(duì)數(shù)據(jù)集進(jìn)行100次寫入,,但是您可以有多個(gè)保存點(diǎn))。 但是,,通常會(huì)每隔五分鐘或更長(zhǎng)時(shí)間創(chuàng)建一次RDB快照,,因此,如果Redis出于任何原因在沒有正確 關(guān)閉的情況下停止工作,,則應(yīng)該準(zhǔn)備丟失最新的數(shù)據(jù)分鐘。 RDB需要經(jīng)常使用fork()才能使用子進(jìn)程將其持久化在磁盤上,。 如果數(shù)據(jù)集很大,,Fork()可能很耗時(shí),,并且如果數(shù)據(jù)集很大且CPU性能不佳,則可能導(dǎo)致Redis停止為客戶端服務(wù)幾毫秒甚至一秒鐘,。 AOF還需要fork(),,但您可以調(diào)整要重寫日志的頻率,而無需在持久性上進(jìn)行權(quán)衡,。
AOF的優(yōu)勢(shì) 使用AOF Redis更加持久:您可以有不同的fsync策略:完全沒有fsync,,每秒fsync,每個(gè)查詢fsync,。 使用默認(rèn)策略fsync時(shí),,每秒的寫入性能仍然很好(fsync是使用后臺(tái)線程執(zhí)行的,并且在沒有進(jìn)行fsync的情況下,,主線程將盡力執(zhí)行寫入操作,。)但是您只能損失一秒鐘的寫入時(shí)間。 AOF日志僅是一個(gè)追加日志,,因此,,如果斷電,也不會(huì)出現(xiàn)尋道或損壞問題,。 即使由于某種原因(磁盤已滿或其他原因)以半寫命令結(jié)束日志,,redis-check-aof工具也可以輕松修復(fù)它。 Redis太大時(shí),,Redis可以在后臺(tái)自動(dòng)重寫AOF,。 重寫是完全安全的,因?yàn)?span id="3squ974rb" class="s3">Redis繼續(xù)追加到舊文件時(shí),,會(huì)生成一個(gè)全新的文件,,其中包含創(chuàng)建當(dāng)前數(shù)據(jù)集所需的最少操作集,一旦準(zhǔn)備好第二個(gè)文件,,Redis會(huì)切換這兩個(gè)文件并開始追加到新的那一個(gè),。 AOF以易于理解和解析的格式包含所有操作的日志。 您甚至可以輕松導(dǎo)出AOF文件,。 例如,,即使您使用FLUSHALL命令刷新了所有錯(cuò)誤文件 ,如果在此期間未執(zhí)行任何日志重寫操作,,您仍然可以保存數(shù)據(jù)集,,只是停止服務(wù)器,刪除最新命令并重新啟動(dòng)Redis,。
AOF的缺點(diǎn) 對(duì)于相同的數(shù)據(jù)集,,AOF文件通常大于等效的RDB文件。 根據(jù)確切的fsync策略,,AOF可能比RDB慢,。 通常,,在將fsync設(shè)置為每秒的情況下,性能仍然很高,,并且在禁用fsync的情況下,,即使在高負(fù)載下,它也應(yīng)與RDB一樣快,。 即使在巨大的寫負(fù)載情況下,,RDB仍然能夠提供有關(guān)最大延遲的更多保證。
過去,,我們?cè)谔囟钪杏龅竭^罕見的錯(cuò)誤(例如,,其中有一個(gè)涉及阻塞命令,例如BRPOPLPUSH ),導(dǎo)致生成的AOF在重載時(shí)無法重現(xiàn)完全相同的數(shù)據(jù)集,。 這些錯(cuò)誤很少見,,我們?cè)跍y(cè)試套件中進(jìn)行了測(cè)試,自動(dòng)創(chuàng)建了隨機(jī)的復(fù)雜數(shù)據(jù)集,,然后重新加載它們以檢查一切是否正常,。 但是,RDB持久性幾乎是不可能的,。 更明確地說:Redis AOF通過增量更新現(xiàn)有狀態(tài)來工作,,就像MySQL或MongoDB一樣,而RDB快照一次又一次地創(chuàng)建所有內(nèi)容,,從概念上講更健壯,。 但是 1)應(yīng)該注意的是,每次Redis重寫AOF時(shí),,都會(huì)從數(shù)據(jù)集中包含的實(shí)際數(shù)據(jù)開始從頭開始重新創(chuàng)建AOF,,與始終附加AOF文件相比(或重寫后的讀數(shù)),對(duì)錯(cuò)誤的抵抗力更強(qiáng)舊的AOF,,而不是讀取內(nèi)存中的數(shù)據(jù)),。 2)我們從未收到過有關(guān)真實(shí)環(huán)境中檢測(cè)到的AOF損壞的用戶報(bào)告。
以上所述就是RDB會(huì)根據(jù)配置文件的配置信息定時(shí)全量備份時(shí)間點(diǎn)的數(shù)據(jù); AOF則是根據(jù)同步策略追加寫入備份文件,。 一. RDB快照持久化#首先我們看下配置文件的信息 [root@guangzhou data]# systemctl status redis ● redis.service - Redis 6379 Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled) Active: active (running) since 六 2020-01-18 16:26:42 CST; 18h ago Process: 344 ExecStop=/usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 -a jcon shutdown (code=exited, status=0/SUCCESS) Process: 348 ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf (code=exited, status=0/SUCCESS) Main PID: 349 (redis-server) CGroup: /system.slice/redis.service └─349 /usr/local/redis/bin/redis-server *:6379 1月 18 16:26:42 guangzhou systemd[1]: Starting Redis 6379... 1月 18 16:26:42 guangzhou systemd[1]: Started Redis 6379. #更改/usr/local/redis/etc/redis.conf中配置 #10秒鐘內(nèi)2次更改寫入RDB二進(jìn)制文件 save 10 2 # RDB持久化文件名 dbfilename dump.rdb # 數(shù)據(jù)持久化文件存儲(chǔ)目錄 dir /usr/local/redis/data # bgsave發(fā)生錯(cuò)誤時(shí)是否停止寫入,,通常為yes stop-writes-on-bgsave-error yes # rdb文件是否使用壓縮格式 rdbcompression yes # 是否對(duì)rdb文件進(jìn)行校驗(yàn)和檢驗(yàn),通常為yes rdbchecksum yes 127.0.0.1:6379> flushdb
#操作前清空RDB文件 [root@guangzhou data]# pwd && ll /usr/local/redis/data
#set兩條數(shù)據(jù) 127.0.0.1:6379> set a 100 OK #重命名RDB文件 [root@guangzhou data]# pwd && mv dump.rdb dump.rdb2 && ll
#再次set兩條數(shù)據(jù) 127.0.0.1:6379> set c 300
#查看RDB文件,可以發(fā)現(xiàn)新的dump.rdb文件大于dump.rdb2,因?yàn)镽DB是全量備份,dump.rdb比dump.rdb2多了key=c和key=d [root@guangzhou data]# ll 總用量 8
#現(xiàn)在我們將文件重命名 [root@guangzhou data]# pwd && mv dump.rdb dump.rdb3 && ll -rw-r--r-- 1 root root 108 1月 19 15:42 dump.rdb2
#清空數(shù)據(jù) 127.0.0.1:6379> flushdb #停止redis服務(wù) [root@guangzhou data]# systemctl stop redis #刪除最新生成的rdb文件,,重命名僅含有key=a和key=b的dump.rdb2為dump.rdb [root@guangzhou data]# pwd && rm -rf dump.rdb && mv dump.rdb2 dump.rdb && ll #重啟redis服務(wù)(正常的話重啟后redis僅含有key=a和key=b兩個(gè)數(shù)據(jù)) [root@guangzhou data]# systemctl restart redis #重連redis列出所有key,果然如我們所料,,只有a和b 127.0.0.1:6379> keys * #如果對(duì)數(shù)據(jù)完整性要求較高,,可以采用RDB快照,啟用定時(shí)任務(wù)備份指定時(shí)間點(diǎn)的數(shù)據(jù)文件,這樣一旦發(fā)生生產(chǎn)事故,,可以很方便數(shù)據(jù)回滾,;另外單個(gè)RDB二進(jìn)制文件,,方便文件分散存儲(chǔ),,數(shù)據(jù)遷移挪到其他服務(wù)器。 二. AOF方式持久化#更改/usr/local/redis/etc/redis.conf中配置 #注釋上面RDB快照持久方式的配置,,并更改aof配置 #開啟AOF日志追加 appendonly yes #日志追加的文件名 appendfilename "appendonly.aof" #寫入頻率,,為了便于觀察,這里使用更新立即更新日志文件 appendfsync always #redis服務(wù)重啟 [root@guangzhou etc]# systemctl restart redis [root@guangzhou etc]# systemctl status redis ● redis.service - Redis 6379 Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled) Active: active (running) since 一 2020-01-20 15:40:17 CST; 9s ago Process: 5493 ExecStop=/usr/local/redis/bin/redis-cli -h 127.0.0.1 -p 6379 -a jcon shutdown (code=exited, status=0/SUCCESS) Process: 5497 ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf (code=exited, status=0/SUCCESS) Main PID: 5498 (redis-server) CGroup: /system.slice/redis.service └─5498 /usr/local/redis/bin/redis-server 127.0.0.1:6379 1月 20 15:40:17 guangzhou systemd[1]: Starting Redis 6379... 1月 20 15:40:17 guangzhou systemd[1]: Started Redis 6379. #轉(zhuǎn)到/usr/local/redis/data目錄,,自動(dòng)生成空文件,appendonly.aof [root@guangzhou data]# ll 總用量 0 -rw-r--r-- 1 root root 0 1月 20 15:42 appendonly.aof #命令行下錄入數(shù)據(jù) 127.0.0.1:6379> keys * (empty list or set) 127.0.0.1:6379> set a 1 OK 127.0.0.1:6379> set b 2 OK 127.0.0.1:6379> set c 3 OK 127.0.0.1:6379> #打印日志文件 [root@guangzhou data]# ll 總用量 8 -rw-r--r-- 1 root root 104 1月 20 15:43 appendonly.aof [root@guangzhou data]# cat appendonly.aof *2 $6 SELECT $1 0 *3 $3 set $1 a $1 1 *3 $3 set $1 b $1 2 *3 $3 set $1 c $1 3 #文件輸出可見每次操作詳情, #現(xiàn)在我們模擬異常情況,先重命名appendonly.aof文件為appendonly.aof2,,停止redis服務(wù) [root@guangzhou data]# pwd && mv appendonly.aof appendonly.aof2 && systemctl stop redis && rm -rf ./appendonly.aof && ll /usr/local/redis/data 總用量 8 -rw-r--r-- 1 root root 104 1月 20 15:43 appendonly.aof2 #在更改appendonly.aof2文件中c的數(shù)值為999, appendonly.aof2重命名為appendonly.aof,重啟redis服務(wù) 127.0.0.1:6379> keys * 1) "c" 2) "b" 3) "a" 127.0.0.1:6379> get c "993" #可見key=c的數(shù)據(jù)已改變 $3 set $1 c $3(更改時(shí)這里需要從1變?yōu)?) 993
生產(chǎn)環(huán)境我們可以RDB快照和AOF兩種方式結(jié)合起來使用,,RDB快照文件可以定時(shí)備份 注意: 1) auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb 意思啟用AOF時(shí),,redis會(huì)在AOF比上次完成重寫AOF時(shí)的容量大至少100%時(shí)開啟一個(gè) 2) 只配置 AOF ,,重啟時(shí)加載 AOF 文件恢復(fù)數(shù)據(jù) 同時(shí)配置了 RDB 和 AOF ,,啟動(dòng)是只加載 AOF 文件恢復(fù)數(shù)據(jù) 只配置 RDB,啟動(dòng)是將加載 dump 文件恢復(fù)數(shù)據(jù) 3) 命令行下save命令保存當(dāng)前時(shí)間點(diǎn)全量數(shù)據(jù)快照, bgsave異步保存快照 |
|