Redis持久化——記憶體快照(RDB)
我們都知道Redis是記憶體資料庫,它將自己的資料儲存的記憶體中。這樣一旦伺服器程式退出(斷電、重啟等原因),那麼資料將會丟失。為了解決這個問題,Redis提供兩種持久化的方式來將資料持久化到硬碟上,即記憶體快照(RDB)與AOF日誌。
1 什麼是記憶體快照
所謂記憶體快照,顧名思義就是給記憶體拍個照,在某個時刻把記憶體中的資料記錄下來,以檔案的形式儲存到硬碟上,這樣即使當機,資料依然存在。在伺服器重啟後只需要把“照片”中的資料恢復即可。
RDB持久化就是把當前程式的資料在某個時刻生成快照(一個壓縮的二進位制檔案)儲存到硬碟的過程,觸發RDB持久化過程分為手動觸發和自動觸發。
1.1 RDB檔案的建立
RDB檔案的建立可以手動觸發,也可以自動觸發。
1.1 手動觸發
手動觸發分別對應save和bgsave命令:
1.1.1 save命令
save命令會阻塞當前Redis伺服器,直到RDB過程完成為止。在伺服器程式阻塞期間,伺服器不能處理任何命令請求。因此,當save命令正在執行時,客戶端傳送的所有命令都會被拒絕,知道save命令執行完畢。
Copy
redis>save //等待,直到RDB檔案建立完畢 ok
注意:
Redis的單執行緒模型就決定了,我們要儘量避免所有會阻塞主執行緒的操作,由於Save命令執行期間阻塞伺服器程式,對於記憶體比較大的例項會造成長時間阻塞,因此線上環境不建議使用。
1.1.2 bgsave命令
bgsave命令會派生出一個子程式(而不是執行緒),由子程式進行RDB檔案建立,而父程式繼續處理命令。
Copy
redis>bgsave Background saving started //直接返回,由子程式進行RDB檔案建立 redis> //繼續處理其它命令
注意:
- 在bgsave命令執行的時候,為了避免父程式與子程式同時執行兩個rdbSave的呼叫而產生競爭條件,客戶端傳送的save命令會被伺服器拒絕。
- 如果bgsave命令正在執行,bgrewriteaof(aof重寫)命令會被延遲到bgsave命令之後執行,如果bgrewriteaof命令正在執行,那麼客戶端傳送的bgsave命令會被伺服器拒絕。
- 雖然bgsave命令是由子程式進行RDB檔案的生成,但是fork()建立子程式的時候會阻塞父程式(詳情請往下看)。
1.2 自動觸發
因為bgsave命令可以在不阻塞伺服器程式的情況下儲存,所以redis可以透過設定伺服器配置的save選項,讓伺服器每隔一段時間自動執行一次bgsave命令。如:我們向伺服器設定如下配置(這也是redis預設的配置):
Copy
save 900 1 save 300 10 save 60 10000
那麼只要滿足如下條件中的一個bgsave命令就會被執行:
- 伺服器在900秒內對資料庫進行了至少1次修改
- 伺服器在300秒內對資料庫進行了至少10次修改
- 伺服器在60秒內對資料庫進行了至少10000次修改
1.2 RDB檔案的載入
在Redis啟動的時候,只要檢測到RDB檔案的存在,就會自動載入RDB檔案。需要注意的是
-
因為AOF檔案的更新頻率通常比RDB檔案的更新頻率高,所以口如果伺服器開啟了AOF持久化功能,那麼伺服器會優先使用AOF檔案來還原資料庫狀態。
-
只有在AOF持久化功能處於關閉狀態時,伺服器才會使用RDB檔案來還原資料庫狀態。
注意:伺服器在載入RDB檔案期間,會一直處於阻塞狀態,直到載入工作完成為止
2 記憶體快照的問題
瞭解了什麼是Redis的RDB持久化,我們來思考兩個問題。
2.1 快照的時候資料可以修改嗎
Redis RDB持久化是對某一時刻
的記憶體中的全量資料
進行拍照。這讓我們不得不思考,快照的時候資料可以修改嗎?
首先,如果我們使用save
命令做持久化,那麼由於Redis單執行緒模型的原因,在持久化的過程中會阻塞,是不能執行其它命令的。也許有人會說可以使用bgave
命令,但使用bgsave
就沒有問題了嗎?
我們在拍照的時候,通常攝影師是不讓我們動的,因為一動可能照片就模糊了。在Redis 進行記憶體快照的時候也會如此。如果我們持久化的過程中,有些資料被修改了。那麼就會破壞快照的正確性與完整性。
比如在t時刻,我們對記憶體進行快照,此時我們希望的是記錄下來t時刻記憶體中所有的資料,假設我們的RDB操作需要10s的時間,而t+2s我們執行了一個修改操作把Key1
的值由A修改成了B,而此時RDB操作卻還沒有把Key1
的值寫入磁碟。在t+5s的時候讀取到key1
的值寫入磁碟。那麼此次快照記錄的Key1
的值就是B,而不是t時刻的A。這樣就破壞了RDB檔案的正確性。
RDB檔案的生成是需要時間的,如果快照執行期間資料不能被修改,對於業務系統來說不能接受的。那麼Redis 是如何解決這個問題的呢?
Redis 藉助了作業系統提供的寫時複製技術(Copy-On-Write, COW),可以讓在執行快照的同時,正常處理寫操作。簡單來說,bgsave fork子程式的時候,並不會完全複製主程式的記憶體資料,而是隻複製必要的虛擬資料結構,並不為其分配真實的物理空間,它與父程式共享同一個實體記憶體空間。bgsave 子程式執行後,開始讀取主執行緒的記憶體資料,並把它們寫入 RDB 檔案。此時,如果主執行緒對這些資料也都是讀操作,那麼,主執行緒和 bgsave 子程式相互不影響。但是,如果主執行緒要修改一塊資料,此時會給子程式分配一塊實體記憶體空間,把要修改的資料複製一份,生成該資料的副本到子程式的實體記憶體空間。然後,bgsave 子程式會把這個副本資料寫入 RDB 檔案,而在這個過程中,主執行緒仍然可以直接修改原來的資料。
2.2 可以頻繁進行快照操作嗎
假設我們在t 時刻做了一次快照,然後又在 t+n 時刻做了一次快照,而在這期間,發生了資料修改。而此時當機了,那麼,只能按照 t 時刻的快照進行恢復。那麼這n秒的資料就徹底丟失無法恢復了。
所以,要想盡可能恢復資料,就只能縮短快照執行的時間間隔,間隔的時間越小,丟失資料也就越少。那麼可以頻繁的執行快照操作嗎?
我們知道bgsave 執行時並不阻塞主執行緒,但是這不代表可以頻繁執行快照操作。
一方面,持久化是一個寫入磁碟的過程,頻繁將全量資料寫入磁碟,會給磁碟帶來很大壓力,頻繁執行快照也容易導致前一個快照還沒有執行完,後一個又開始了,這樣多個快照競爭有限的磁碟頻寬,容易造成惡性迴圈。
再者,bgsave所fork出來的子程式執行操作雖然並不會阻塞父程式的操作,但是fork
出子程式的操作卻是由主程式完成的,會阻塞主程式,fork子程式需要複製程式必要的資料結構,其中有一項就是複製記憶體頁表(虛擬記憶體和實體記憶體的對映索引表),這個複製過程會消耗大量CPU資源,複製完成之前整個程式是會阻塞的,阻塞時間取決於整個例項的記憶體大小,例項越大,記憶體頁表越大,fork阻塞時間也就越久。
也許有人會想到是否可以做增量快照呢?也就是隻對上一次快照之後的資料做快照。
首先思路肯定是可以,但是增量快照要求記住哪些資料上一次快照之後產生的。這就需要額外的後設資料來記錄這些資訊,會引入額外的空間消耗。這對於記憶體資源寶貴的 Redis 來說,並不是一個很好的方案。
如果不能頻繁執行快照操作,那麼該如何解決兩次快照之間的資料丟失的問題呢?Redis 還提供了另外一種持久化方式——AOF(append to file)日誌。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4289/viewspace-2807281/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Redis基礎篇(四)持久化:記憶體快照(RDB)Redis持久化記憶體
- Redis系列:RDB記憶體快照提供持久化能力Redis記憶體持久化
- redis快照--RDB持久化Redis持久化
- Redis的兩種持久化方式-快照持久化(RDB)和AOF持久化Redis持久化
- 圖解Redis,談談Redis的持久化,RDB快照與AOF日誌圖解Redis持久化
- redis系列:RDB持久化與AOF持久化Redis持久化
- Redis持久化之RDB & AOFRedis持久化
- Redis持久化RDB和AOFRedis持久化
- Redis持久化(RDB 和 AOF)Redis持久化
- redis RDB持久化不生效Redis持久化
- Redis持久化-RDB與AOFRedis持久化
- (七)Redis 持久化 AOF、RDBRedis持久化
- Redis資料持久化—RDB持久化與AOF持久化Redis持久化
- Redis持久化儲存——>RDB & AOFRedis持久化
- redis-16.持久化之RDBRedis持久化
- Redis 持久化之RDB和AOFRedis持久化
- Redis持久化 (RDB和AOF) 梳理Redis持久化
- Redis(五)--- Redis的持久化RDB與AOFRedis持久化
- 【Redis篇】Redis持久化方式AOF和RDBRedis持久化
- 配置方案:Redis持久化RDB和AOFRedis持久化
- 5-Redis 的持久化之 RDBRedis持久化
- Redis持久化RDB和AOF的概念Redis持久化
- 深入剖析Redis RDB持久化機制Redis持久化
- 【Redis】 redis解析rdb檔案,記憶體排序等Redis記憶體排序
- Redis基礎(三)Redis持久化:RDB與AOFRedis持久化
- 【Redis】Redis 持久化之 RDB 與 AOF 詳解Redis持久化
- Redis——Redis用作資料庫(持久化/RDB/AOF)Redis資料庫持久化
- Redis學習筆記六:持久化實驗(AOF,RDB)Redis筆記持久化
- 【Redis 系列】redis 學習八,redis 持久化 RDB 和 AOFRedis持久化
- redis的持久化機制 (RDB&AOF)Redis持久化
- 對比 Redis 中 RDB 和 AOF 持久化Redis持久化
- Redis系列(三):Redis的持久化機制(RDB、AOF)Redis持久化
- Redis 學習筆記(四)RDB 和 AOF 持久化機制Redis筆記持久化
- 搞懂Redis RDB和AOF持久化及工作原理Redis持久化
- 淺談:Redis持久化機制(一)RDB篇Redis持久化
- 技術分享 | Redis 持久化之 RDB 與 AOFRedis持久化
- redis的 rdb 和 aof 持久化的區別Redis持久化
- redis個人原始碼分析筆記5---RDB持久化機制Redis原始碼筆記持久化