教你如何讓Redis更持久!
本文轉(zhuǎn)載自微信公眾號(hào)「小菜良記」,作者蔡不菜丶。轉(zhuǎn)載本文請(qǐng)聯(lián)系小菜良記公眾號(hào)。
大家好,我是小菜。一個(gè)希望能夠成為 吹著牛X談架構(gòu) 的男人!如果你也想成為我想成為的人,不然點(diǎn)個(gè)關(guān)注做個(gè)伴,讓小菜不再孤單!
最近在面試的路上愈走愈遠(yuǎn)了,Redis肯定是一個(gè)熱門面試方向。像有幾種數(shù)據(jù)結(jié)構(gòu)?如何實(shí)現(xiàn)延遲隊(duì)列?淘汰機(jī)制是怎么樣的?都快問(wèn)到麻木,這些問(wèn)題還常繞腦梁。那我們這篇就舉一個(gè)比較常見(jiàn)且難度適中的面試題來(lái)聊聊。Redis 的持久化策略是怎么樣的?
開(kāi)局問(wèn)個(gè)問(wèn)題,相信被問(wèn)到 Redis 持久化 的同學(xué)肯定不在少數(shù),答對(duì)的同學(xué)肯定也不在少數(shù),有些小伙伴說(shuō)到 Redis持久化 肯定張口就來(lái),畢竟也就 AOF 和 RDB 兩個(gè)概念,只要你準(zhǔn)備了面試,就不會(huì)被問(wèn)的太慘。但是你是真的懂還是只是為了應(yīng)付面試而去應(yīng)付記憶?你知道 AOF 和 RDB 兩個(gè)詞是什么單詞的縮寫嗎?你落地實(shí)施過(guò)嗎?你真以為面試官聽(tīng)不出來(lái)你是背題還是實(shí)操嗎?如果 4 個(gè)問(wèn)題你中了一半,那不妨往下看看,也許會(huì)有些收獲,起碼答面試題的時(shí)候心中有小菜~!
Redis 持久化
什么是Redis持久化?
咱們先別記得往解決方向前行,先明白這道題的意思。
持久化 就是要讓數(shù)據(jù)永久的保存下去。那什么是 Redis 持久化 ?那就是把Redis保存在內(nèi)存的數(shù)據(jù)寫到磁盤中,防止服務(wù)宕機(jī)了內(nèi)存數(shù)據(jù)丟失問(wèn)題。那有些小伙伴就說(shuō)了,那磁盤損壞了,數(shù)據(jù)怎么持久化?就算多點(diǎn)備份能解決磁盤損壞問(wèn)題,那如果來(lái)個(gè)多點(diǎn)丟失怎么整?停住停住,咱們這篇講的是Redis內(nèi)存數(shù)據(jù)->磁盤的持久化問(wèn)題,可別指望靠這個(gè)問(wèn)題跟面試官扯半個(gè)小時(shí)~!
咱們這篇從幾個(gè)點(diǎn)來(lái)說(shuō)明 Redis持久化 問(wèn)題。
也就三點(diǎn)大的方向,三步走戰(zhàn)略解決你的持久化問(wèn)題。
一、RDB
先來(lái)解決開(kāi)局的問(wèn)題之一,RDB 是什么單詞的全稱。RDB(Redis Database Backup file)--- Redis 數(shù)據(jù)備份文件,也稱為 Redis 數(shù)據(jù)快照。
這個(gè)玩意就是用來(lái)將內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤中,當(dāng) Redis 實(shí)例故障重啟后,從磁盤讀取快照文件,從而恢復(fù)數(shù)據(jù)。內(nèi)心狂喜,看來(lái)學(xué)的第一個(gè)概念就可以解決 Redis 持久化問(wèn)題~
在學(xué) RDB 之前,我們先明白兩個(gè)核心概念 fork 和 cow,下面我們會(huì)解釋,這里先賣個(gè)關(guān)子。
RDB 是 Redis 中默認(rèn)的持久化機(jī)制,按照一定的時(shí)間將內(nèi)存中的數(shù)據(jù)以快照的方式保存到磁盤中,它會(huì)產(chǎn)生一個(gè)特殊類型的文件 .rdb 數(shù)據(jù)文件,同時(shí)可以通過(guò)配置文件中的 save 參數(shù)來(lái)定義快照的周期.
我們從配置文件中的兩個(gè)配置參數(shù)入手,首先是 save 配置。
這個(gè)指令是由 Redis 主進(jìn)程來(lái)執(zhí)行RDB,會(huì)阻塞所有命令
我們?cè)谂渲梦募姓业接嘘P(guān)于 sava 的配置
- dbfilename dump.rdb
該配置項(xiàng)的作用便是用來(lái)定義 rdb 文件名(需要注意該名稱不能定義為路徑,只能定義為文件名稱)
當(dāng)我們執(zhí)行完 save 命令后,便可在 redis 文件夾中看到一個(gè) dump.rdb 文件
- save <seconds> <changes>
該配置項(xiàng)的作用是用來(lái)定義多長(zhǎng)時(shí)間內(nèi)發(fā)生多少次變化便會(huì)執(zhí)行 bgsave,如果是 save "" 則表示禁用 RDB。
我們接下來(lái)打開(kāi) save 配置進(jìn)行測(cè)試
- dbfilename dump-test.rdb # 文件名為 dump-test.rdb
- save 3600 1 # 在 3600 秒內(nèi)發(fā)生一次更改,便會(huì)執(zhí)行 bgsave
我們通過(guò) redis-cli 進(jìn)入操作
然后我們退出后便可在當(dāng)前目錄下看到剛剛生成的 dump-test.rdb 文件
說(shuō)明我們配置是生效的,接著我們直接重啟 Redis ,看是否還存在我們剛剛保存的數(shù)據(jù)
看到我們的數(shù)據(jù),就說(shuō)明 redis 持久化成功了。然后我們把剛剛生成的 dump-test.rdb 文件刪除后重啟 redis
這可以說(shuō)明Redis 啟動(dòng)時(shí)是靠 .rdb 來(lái)恢復(fù)文件數(shù)據(jù)的。那我們上面一直說(shuō)到的 bgsave,那 bgsave 又是如何執(zhí)行的呢?
我們?cè)谇懊嬗姓f(shuō)過(guò)兩個(gè)概念 fork 和 cow,不知道是否還有印象,這兩個(gè)概念便是關(guān)鍵~!
bgsave 開(kāi)始的時(shí)候會(huì) fork 主進(jìn)程得到一個(gè)新的子進(jìn)程,而 子進(jìn)程 是 共享 主進(jìn)程的內(nèi)存數(shù)據(jù)的。子進(jìn)程會(huì)將數(shù)據(jù)寫到磁盤上的一個(gè)臨時(shí)的 .rdb 文件中,當(dāng)子進(jìn)程寫完臨時(shí)文件后,會(huì)將原來(lái)的 .rdb文件替換掉。這個(gè)就是 fork 的核心,那什么是 cow 呢?cow 全稱 copy-on-write 技術(shù),當(dāng)主進(jìn)程執(zhí)行讀操作的時(shí)候是訪問(wèn)共享內(nèi)存的,而主進(jìn)程執(zhí)行寫操作的時(shí)候,則會(huì)拷貝一份數(shù)據(jù),執(zhí)行寫操作。
具體流程如下:
這種持久化方式有什么優(yōu)點(diǎn)呢?
- 方便持久化,只有一個(gè) dump.rdb 文件
- 容災(zāi)性好,可以將文件保存到安全的磁盤中
- 性能最大化,fork 子進(jìn)程來(lái)完成寫操作,讓主進(jìn)程繼續(xù)處理命令,將 IO 最大化,保證 Redis 的高性能
缺點(diǎn)也是有的:
- 數(shù)據(jù)安全性低,RDB 是間隔一段時(shí)間來(lái)持久化 (save) ,如果持久化期間 Redis 發(fā)生故障,那么就會(huì)造成數(shù)據(jù)丟失,所以這種方式適用于數(shù)據(jù)要求不是很嚴(yán)謹(jǐn)?shù)那闆r下使用
- 保存時(shí)間長(zhǎng),如果數(shù)據(jù)量很大,保存快照的時(shí)間就會(huì)很長(zhǎng),會(huì)占用磁盤空間
優(yōu)劣均沾,斟酌使用
二、AOF
AOF 全稱 Append Only File (追加文件)。作用便是 Redis 處理的每一個(gè)寫命令都會(huì)記錄在 AOF 文件中,可以看做是命令日志文件。
該功能默認(rèn)是關(guān)閉的,我們可以在 redis.conf 文件中查看有關(guān)于 AOF 相關(guān)的配置項(xiàng)
- appendonly yes # 開(kāi)啟 AOF 日志記錄功能,默認(rèn)是關(guān)閉的
- appendfilename "appendonly.aof" # AOF 文件的名稱
以上兩個(gè)配置項(xiàng)便是用來(lái)開(kāi)啟 AOF 日志記錄,那么還有個(gè)額外的配置項(xiàng)也需要了解
- appendfsync everysec # AOF 命令記錄的頻率
該配置項(xiàng)有三個(gè)可選值
配置項(xiàng) | 刷盤時(shí)機(jī) | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|---|
Always | 同步刷盤 | 可靠性高,幾乎不會(huì)丟失數(shù)據(jù) | 性能影響較大 |
everysec | 每秒刷盤 | 性能適中 | 最多丟失1秒的數(shù)據(jù) |
no | 操作系統(tǒng)控制 | 性能最好 | 可靠性較差,可能丟失大量的數(shù)據(jù) |
有了解 Mysql 中 relay log 日志的同學(xué),就不會(huì)對(duì)這種模型很陌生。
原理:它是將寫命令追加到 AOF 文件的末尾,使用 AOF 持久化需要設(shè)置同步選項(xiàng),從而確保寫命令同步到磁盤文件上的時(shí)機(jī),這是因?yàn)閷?duì)文件進(jìn)行寫入并不會(huì)馬上將內(nèi)存同步到磁盤上,而是先存儲(chǔ)到緩存區(qū)中,然后由操作系統(tǒng)決定什么時(shí)候同步到磁盤。
我們開(kāi)啟 AOF 記錄功能查看下:
可以看出我們的每一個(gè)操作都已經(jīng)記錄到 AOF 文件中,我們這邊通過(guò)重啟 Redis 也一樣能獲取到剛剛存儲(chǔ)的數(shù)據(jù),說(shuō)明持久化是有生效的~
我們看到上面的 AOF 記錄文件是不是覺(jué)得很規(guī)整?但是在線上環(huán)境中越規(guī)整反而不好,因?yàn)檫@文件主要是給機(jī)器看的,而不是跟我們看的,因此我們最好能夠進(jìn)行壓縮。
為了解決AOF文件體積不斷增大的問(wèn)題,用戶可以向Redis發(fā)送 bgrewriteaof命令,這個(gè)命令會(huì)通過(guò) 通過(guò)移除AOF文件中的冗余命令 來(lái)重寫(rewrite)AOF文件,使AOF文件的體積變得盡可能地小。bgrewriteaof的工作原理和 bgsave 創(chuàng)建快照的工作原理非常相似:Redis會(huì)創(chuàng)建一個(gè)子進(jìn)程,然后由子進(jìn)程負(fù)責(zé)對(duì)AOF文件進(jìn)行重寫。因?yàn)锳OF文件重寫也需要用到子進(jìn)程,所以快照持久化因?yàn)閯?chuàng)建子進(jìn)程而導(dǎo)致的性能問(wèn)題和內(nèi)存占用問(wèn)題,在AOF持久化中也同樣存在。
既然存在手動(dòng)觸發(fā)壓縮,那也存在自動(dòng)觸發(fā)壓縮,這就得說(shuō)到配置文件中的兩個(gè)配置項(xiàng)
- auto-aof-rewrite-percentage 100
- auto-aof-rewrite-min-size 64mb
該配置項(xiàng)的意思為當(dāng)AOF文件的體積大于64MB,并且AOF文件的體積比上一次重寫之后的體積大了至少一倍(100%)的時(shí)候,Redis將執(zhí)行bgrewriteaof命令。
總結(jié)下,它的優(yōu)點(diǎn)如下:
- 數(shù)據(jù)安全。AOF 持久化可以配置 appendfsync 屬性中的 always,每進(jìn)行一次寫命令操作就會(huì)記錄到 AOF 文件中一次
- 一致性。通過(guò) append 模型寫文件,即使中途服務(wù)器宕機(jī),也可以通過(guò) redis-check-aof 工具來(lái)解決數(shù)據(jù)一致性問(wèn)題
缺點(diǎn)如下:
- AOF 文件比 RDB 文件大,而且恢復(fù)速度慢
- 數(shù)據(jù)集大的時(shí)候比 RDB 文件啟動(dòng)效率低
同樣是優(yōu)劣均沾,斟酌使用
三、兩者區(qū)別
分別介紹了兩者,我們回顧一下兩者有什么區(qū)別?
方面 | RDB | AOF |
---|---|---|
持久化方式 | 定時(shí)對(duì)整個(gè)內(nèi)存做快照 | 記錄每一次執(zhí)行的命令 |
數(shù)據(jù)完整性 | 不完整,兩次備份之間會(huì)丟失 | 相對(duì)完整。取決于刷盤策略 |
文件大小 | 會(huì)有壓縮,文件體積小 | 記錄命令,文件體積很大 |
宕機(jī)恢復(fù)速度 | 很快 | 慢 |
數(shù)據(jù)恢復(fù)優(yōu)先級(jí) | 低,因?yàn)閿?shù)據(jù)完整性不如AOF | 高,因?yàn)閿?shù)據(jù)完整性更高 |
系統(tǒng)資源占用 | 高,大量CPU和內(nèi)存消耗 | 低,主要是磁盤IO資源。且 AOF 重寫時(shí)會(huì)占用大量CPU和內(nèi)存資源 |
使用場(chǎng)景 | 可以容忍數(shù)分鐘的數(shù)據(jù)丟失,追求更快的啟動(dòng)速度 | 對(duì)數(shù)據(jù)安全性要求較高 |
看完上面后,想必對(duì)兩種持久化機(jī)制都有一定的了解了。兩者都有優(yōu)劣勢(shì),那我們?cè)撊绾芜x擇?這里給出幾點(diǎn)意見(jiàn)~
如果可以忍受一小段時(shí)間內(nèi)的數(shù)據(jù)丟失,可以使用 RDB 機(jī)制,定時(shí)生成 RDB 快照, 并且 RDB 恢復(fù)數(shù)據(jù)集的速度也要比 AOF 恢復(fù)的速度要快
但是如果單單使用 RDB 機(jī)制,可能導(dǎo)致丟失很多數(shù)據(jù),因此我們需要綜合使用 AOF 和 RDB 兩種持久化機(jī)制,用 AOF 來(lái)保證數(shù)據(jù)不丟失,作為數(shù)據(jù)恢復(fù)的第一選擇;用 RDB 來(lái)做不同程度的冷備份,在 AOF 文件都丟失或損壞不可用的情況下,可以使用 RDB 來(lái)進(jìn)行快速的數(shù)據(jù)恢復(fù)
我們可以利用 RDB 來(lái)快速恢復(fù)數(shù)據(jù),并用 AOF 來(lái)補(bǔ)全數(shù)據(jù)
我們到這里就講述了 Redis 持久化機(jī)制的配置,通過(guò)這篇文章的學(xué)習(xí),我相信到時(shí)候面試的時(shí)候遇到這個(gè)問(wèn)題也不至于那么手足無(wú)措~!
不要空談,不要貪懶,和小菜一起做個(gè)吹著牛X做架構(gòu)的程序猿吧~點(diǎn)個(gè)關(guān)注做個(gè)伴,讓小菜不再孤單。咱們下文見(jiàn)!