每日一句
低頭是一種能力,它不是自卑,也不是怯弱,它是清醒中的嬗變。有時,稍微低一下頭,或者我們的人生路會更精彩。
前提概要
Redis是一個的鍵-值(K-V)對的內(nèi)存數(shù)據(jù)庫服務,通常包含了任意個非空數(shù)據(jù)庫。而每個非空的鍵值數(shù)據(jù)庫中又可以存放任意個K-V,基本的結(jié)構(gòu)如下圖所示:
- Redis的強勁性能很大程度上是由于其將所有數(shù)據(jù)都存儲在了內(nèi)存中,為了使Redis在重啟之后仍能保證數(shù)據(jù)不丟失,需要將數(shù)據(jù)從內(nèi)存中以某種形式同步到硬盤中,這一過程就是持久化。
- 我們知道redis中緩存的數(shù)據(jù)都存放在內(nèi)存中,一旦服務故障,會導致內(nèi)存中數(shù)據(jù)丟失,所以需要一種數(shù)據(jù)持久化的方案,將redis內(nèi)存中的數(shù)據(jù),寫入磁盤,當redis重啟后,能從磁盤中恢復數(shù)據(jù)。
Redis服務器的結(jié)構(gòu)
- 這里有一個問題,因為Redis是一個內(nèi)存數(shù)據(jù)庫,如果它直接將數(shù)據(jù)存儲到內(nèi)存中,但是如果不考慮將存儲在內(nèi)存中的數(shù)據(jù)持久化到硬盤里面,一旦服務器進程退出,那么數(shù)據(jù)庫中的數(shù)據(jù)也會消失。
- 數(shù)據(jù)庫的持久化機制主要有兩種,一種是RDB機制,另外一種是AOF機制,AOF機制已經(jīng)在前面的文章中介紹過了,
- 如果有興趣可以去看看,而本文主要講述RDB機制。
RDB持久化方式
RDB持久化是指在指定的時間間隔內(nèi)將redis內(nèi)存中的數(shù)據(jù)集快照寫入磁盤,實現(xiàn)原理是redis服務在指定的時間間隔內(nèi)先fork一個子進程,由子進程將數(shù)據(jù)集寫入臨時文件,寫入成功后,再替換之前的文件,用二進制壓縮存儲,生成dump.rdb文件存放在磁盤中。
RDB機制
- Redis提供了RDB持久化能力,這個功能可以將Redis在內(nèi)存中的數(shù)據(jù)庫狀態(tài)保持在磁盤里面,避免數(shù)據(jù)意外丟失。
- RDB持久化機制可以手動執(zhí)行,也可以根據(jù)服務器配置選定定期執(zhí)行操作,該功能可以將某一個時間點的數(shù)據(jù)快照進行保存到一個RDB文件中。
RDB優(yōu)勢
- 一旦采用該方式,那么你的整個Redis數(shù)據(jù)庫將只包含一個文件,這對于文件備份而言是非常完美的。比如,你可能打算每個小時歸檔一次最近24小時的數(shù)據(jù),同時還要每天歸檔一次最近30天的數(shù)據(jù)。通過這樣的備份策略,一旦系統(tǒng)出現(xiàn)災難性故障,我們可以非常容易的進行恢復。
- 對于災難恢復而言,RDB是非常不錯的選擇。因為我們可以非常輕松的將一個單獨的文件壓縮后再轉(zhuǎn)移到其它存儲介質(zhì)上。
- 性能最大化。對于Redis的服務進程而言,在開始持久化時,它唯一需要做的只是fork出子進程,之后再由子進程完成這些持久化的工作,這樣就可以極大的避免服務進程執(zhí)行IO操作了。
- 相比于AOF機制,如果數(shù)據(jù)集很大,RDB的啟動效率會更高。
RDB劣勢
如果你想保證數(shù)據(jù)的高可用性,即最大限度的避免數(shù)據(jù)丟失,那么RDB將不是一個很好的選擇。因為系統(tǒng)一旦在定時持久化之前出現(xiàn)宕機現(xiàn)象,此前沒有來得及寫入磁盤的數(shù)據(jù)都將丟失。
由于RDB是通過fork子進程來協(xié)助完成數(shù)據(jù)持久化工作的,因此,如果當數(shù)據(jù)集較大時,可能會導致整個服務器停止服務幾百毫秒,甚至是1秒鐘。
RDB配置規(guī)則
在redis的6379.conf配置文件中:
備份配置參數(shù)
save seconds> changes>
save 指定時間間隔> 執(zhí)行指定次數(shù)更新操作>,滿足條件就將內(nèi)存中的數(shù)據(jù)同步到硬盤中。官方出廠配置默認是 900秒內(nèi)有1個更改,300秒內(nèi)有10個更改以及60秒內(nèi)有10000個更改,則將內(nèi)存中的數(shù)據(jù)快照寫入磁盤。
save 900 1 #在900秒(15分鐘)之后,如果至少有一個key發(fā)生變化,則dump內(nèi)存快照
save 300 10 #在300秒(15分鐘)之后,如果至少有10個key發(fā)生變化,則dump內(nèi)存快照
save 60 10000 #在60秒(1分鐘)之后,如果至少有10000個key發(fā)生變化,則dump內(nèi)存快照
文件配置參數(shù)
默認的rdb文件路徑是當前目錄,文件名是dump.rdb,可以在配置文件中修改路徑和文件名,分別是dir和dbfilename.
# 存放快照的目錄
dir ./ # rdb文件存儲路徑
dbfilename dump.rdb # rdb文件名
壓縮配置參數(shù)
在進行鏡像備份時,是否進行壓縮。
rdbcompression yes #Redis默認是開啟壓縮的。
# yes:壓縮,但是需要一些cpu的消耗。
# no:不壓縮,需要更多的磁盤空間。
如果沒有觸發(fā)自動快照,需要對Redis執(zhí)行手動快照操作,save和bgsave命令來手動快照,兩個命令是:
- SAVE:由主進程進行快照,會阻塞其他請求。
- BGSAVE:通過fork子進程進行快照,不會阻塞其他請求。
注意:由于Redis使用fork來復制一份當前進程,那么子進程就會占有和主進程一樣的內(nèi)存資源,比如說主進程8G內(nèi)存,那么在備份的時候,必須保證有16G的內(nèi)存,要不然會啟用虛擬內(nèi)存,性能非常的差。
快照的過程如下:
- Redis使用fork函數(shù)復制一份當前進程(父進程)的副本(子進程);
- 父進程繼續(xù)接收并處理客戶端發(fā)來的命令,而子進程開始將內(nèi)存中的數(shù)據(jù)寫入硬盤中的臨時文件;
- 當子進程寫入完所有數(shù)據(jù)后會用該臨時文件替換舊的RDB文件,至此一次快照操作完成。(注意:會存在寫一部命令壓縮緩存區(qū),記錄寫入rdb文件時候的操作)
在執(zhí)行fork的時候操作系統(tǒng)會使用寫時復制(copy-on-write)策略,即fork函數(shù)發(fā)生的一刻父子進程共享同一內(nèi)存數(shù)據(jù),當父進程要更改其中某片數(shù)據(jù)時(如執(zhí)行一個寫命令),操作系統(tǒng)會將該片數(shù)據(jù)復制一份以保證子進程的數(shù)據(jù)不受影響,所以新的RDB文件存儲的是執(zhí)行fork時那一刻的內(nèi)存快照數(shù)據(jù)。
通過上述過程可以發(fā)現(xiàn)Redis在進行快照的過程中不會修改RDB文件,只有快照結(jié)束后才會將舊的文件替換成新的,也就是說任何時候RDB文件都是完整的。這使得可以通過定時備份RDB文件來實現(xiàn)Redis數(shù)據(jù)庫備份。
快照的過程壓縮分析:
RDB文件是經(jīng)過壓縮(上文介紹了:可以配置rdbcompression參數(shù)以禁用壓縮節(jié)省CPU占用)的二進制格式,所以占用的空間會小于內(nèi)存中的數(shù)據(jù)大小,更加利于傳輸。
快照的讀取加載過程:
- Redis啟動后會讀取RDB快照文件,將數(shù)據(jù)從硬盤載入到內(nèi)存。根據(jù)數(shù)據(jù)量大小與結(jié)構(gòu)和服務器性能不同,這個時間也不同。通常將一個記錄一千萬個字符串類型鍵、大小為1GB的快照文件載入到內(nèi)存中需要花費20~30秒鐘。
- 通過RDB方式實現(xiàn)持久化,一旦Redis異常退出,就會丟失最后一次快照以后更改的所有數(shù)據(jù)。這就需要開發(fā)者根據(jù)具體的應用場合,通過組合設置自動快照條件的方式來將可能發(fā)生的數(shù)據(jù)損失控制在能夠接受的范圍。如果數(shù)據(jù)很重要以至于無法承受任何損失,則可以考慮使用AOF方式進行持久化。
RDB 的優(yōu)缺點
優(yōu)點:
- 適合大規(guī)模的數(shù)據(jù)恢復。
- 如果業(yè)務對數(shù)據(jù)完整性和一致性要求不高,RDB是很好的選擇。
缺點:
- 數(shù)據(jù)的完整性和一致性不高,因為RDB可能在最后一次備份時宕機了。
- 備份時占用內(nèi)存,因為Redis 在備份時會獨立創(chuàng)建一個子進程,將數(shù)據(jù)寫入到一個臨時文件(此時內(nèi)存中的數(shù)據(jù)是原來的兩倍),最后再將臨時文件替換之前的備份文件。
- 由于RDB是通過fork子進程來協(xié)助完成數(shù)據(jù)持久化工作的,因此,如果當數(shù)據(jù)集較大時,可能會導致整個服務器停止服務幾百毫秒,甚至是1秒鐘。(回寫和覆蓋的時候用的是主進程)。
RDB與AOF二者選擇的標準(雖然還沒有講AOF,提前普及)
- 如果系統(tǒng)是愿意犧牲一些性能,換取更高的緩存一致性(aof)
- 或者是愿意寫操作頻繁的時候,不啟用備份來換取更高的性能,待手動運行save的時候,再做備份(rdb)。
Redis允許同時開啟AOF和RDB,既保證了數(shù)據(jù)安全又使得進行備份等操作十分容易。此時重新啟動Redis后Redis會使用AOF文件來恢復數(shù)據(jù),因為AOF方式的持久化可能丟失的數(shù)據(jù)更少。
總結(jié)
- Redis 默認開啟RDB持久化方式,在指定的時間間隔內(nèi),執(zhí)行指定次數(shù)的寫操作,則將內(nèi)存中的數(shù)據(jù)寫入到磁盤中。
- RDB 持久化適合大規(guī)模的數(shù)據(jù)恢復但它的數(shù)據(jù)一致性和完整性較差。
- Redis 需要手動開啟AOF持久化方式,默認是每秒將寫操作日志追加到AOF文件中。
所以Redis的持久化和數(shù)據(jù)的恢復要選擇在夜深人靜的時候執(zhí)行是比較合理的。
到此這篇關于Redis RDB技術底層原理詳解的文章就介紹到這了,更多相關Redis RDB底層原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Redis 徹底禁用RDB持久化操作
- 淺談Redis中的RDB快照
- Redis 通過 RDB 方式進行數(shù)據(jù)備份與還原的方法
- Redis持久化RDB和AOF區(qū)別詳解
- Redis打開rdb文件常用方法詳解
- redis學習之RDB、AOF與復制時對過期鍵的處理教程
- Redis兩種持久化方案RDB和AOF詳解
- 了解redis中RDB結(jié)構(gòu)_動力節(jié)點Java學院整理