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