您好,登錄后才能下訂單哦!
為什么要做持久化存儲(chǔ)?
持久化存儲(chǔ)是將 Redis 存儲(chǔ)在內(nèi)存中的數(shù)據(jù)存儲(chǔ)在硬盤(pán)中,實(shí)現(xiàn)數(shù)據(jù)的永久保存。我們都知道 Redis 是一個(gè)基于內(nèi)存的 nosql 數(shù)據(jù)庫(kù),內(nèi)存存儲(chǔ)很容易造成數(shù)據(jù)的丟失,因?yàn)楫?dāng)服務(wù)器關(guān)機(jī)等一些異常情況都會(huì)導(dǎo)致存儲(chǔ)在內(nèi)存中的數(shù)據(jù)丟失。
持久化存儲(chǔ)分類(lèi)
在 Redis 中,持久化存儲(chǔ)分為兩種。一種是 aof 日志追加的方式,另外一種是 rdb 數(shù)據(jù)快照的方式。
RDB持久化存儲(chǔ)
什么是RDB持久化存儲(chǔ)
RDB持久化存儲(chǔ)即是將redis存在內(nèi)存中的數(shù)據(jù)以快照的形式保存在本地磁盤(pán)中。
.RDB持久化存儲(chǔ)分為自動(dòng)備份和手動(dòng)備份
1.手動(dòng)備份通過(guò) save 命令和 bgsave 命令。save是同步阻塞,而 bgsave 是非阻塞(阻塞實(shí)際發(fā)生在 fork 的子進(jìn)程中)。因此,在我們實(shí)際過(guò)程中大多是使用bgsave命令實(shí)現(xiàn)備份.
redis> SAVE
OK
redis> BGSAVE
Background saving started
2.自動(dòng)備份
a.修改配置項(xiàng) save m n即表示在 m 秒內(nèi)執(zhí)行了 n 次命令則進(jìn)行備份.
b.當(dāng)Redis 從服務(wù)器項(xiàng)主服務(wù)器發(fā)送復(fù)制請(qǐng)求時(shí),主服務(wù)器則會(huì)使用 bgsave命令生成 rbd 文件,然后傳輸給從服務(wù)器.
c.當(dāng)執(zhí)行 debug reload 命令時(shí)也會(huì)使用 save 命令生成rdb文件.
d.當(dāng)使用 shutdown 命令關(guān)掉服務(wù)時(shí),如果沒(méi)有啟用 aof方式實(shí)現(xiàn)持久化則會(huì)采用bgsave的方式做持久化.同時(shí)shutdown后面可以加備份參數(shù)[nosave|save].
bgsave持久化存儲(chǔ)實(shí)現(xiàn)原理
1.執(zhí)行bgsave命令,Redis父進(jìn)程判斷當(dāng)前是否存在正在執(zhí)行的子進(jìn)程,如果存在則直接返回.
2.父進(jìn)程fork一個(gè)子進(jìn)程(fork的過(guò)程中會(huì)造成阻塞的情況),這個(gè)過(guò)程可以使用info stats命令查看latest_fork_usec選項(xiàng),查看最近一次fork操作小號(hào)的時(shí)間,單位是微妙.
3.父進(jìn)程fork完之后,則會(huì)返回Background saving started信息提示,此時(shí)fork阻塞解除.
4.fork出的子進(jìn)程開(kāi)始根據(jù)父進(jìn)程內(nèi)存數(shù)據(jù)生成臨時(shí)的快照文件,然后替換原文件.使用lastsave命令可以查看最后一次生成rdb的時(shí)間,對(duì)應(yīng)info的rdb_last_savetime選項(xiàng).
5.當(dāng)備份完畢之后向父進(jìn)程發(fā)送完成信息,具體可以見(jiàn)info Persistence下的rbd*選項(xiàng).
RDB持久化的優(yōu)勢(shì)與劣勢(shì)
優(yōu)勢(shì):
1.文件實(shí)現(xiàn)的數(shù)據(jù)快照,全量備份,便于數(shù)據(jù)的傳輸.比如我們需要把A服務(wù)器上的備份文件傳輸?shù)紹服務(wù)器上面,直接將rdb文件拷貝即可.
2.文件采用壓縮的二進(jìn)制文件,當(dāng)重啟服務(wù)時(shí)加載數(shù)據(jù)文件,比aof方式更快.
劣勢(shì):
1.rbd采用加密的二進(jìn)制格式存儲(chǔ)文件,由于Redis各個(gè)版本之間的兼容性問(wèn)題也導(dǎo)致rdb由版本兼容問(wèn)題導(dǎo)致無(wú)法再其他的Redis版本中使用.
2.時(shí)效性差,容易造成數(shù)據(jù)的不完整性.因?yàn)閞db并不是實(shí)時(shí)備份,當(dāng)某個(gè)時(shí)間段Redis服務(wù)出現(xiàn)異常,內(nèi)存數(shù)據(jù)丟失,這段時(shí)間的數(shù)據(jù)是無(wú)法恢復(fù)的,因此易導(dǎo)致數(shù)據(jù)的丟失.
RDB文件常見(jiàn)的處理方式
1.當(dāng)遇到磁盤(pán)寫(xiě)滿(mǎn)情況,可以使用如下命令來(lái)切換存儲(chǔ)磁盤(pán)
// dirName則是新的存儲(chǔ)目錄名(該方式同樣適用于aof格式)
config set dir dirName
2.文件壓縮處理,雖然對(duì)CPU具有消耗,但是減少體積的暫用,同時(shí)做文件傳輸(主從復(fù)制)也減少消耗.
// 修改壓縮開(kāi)啟或關(guān)閉
config set rdbcompression yes|no
3.rbd備份文件損壞檢測(cè).可以使用redis-check-rdb工具檢測(cè)rdb文件,該工具默認(rèn)在/usr/local/bin/目錄下面.
[root@syncd redis-data]# /usr/local/bin/redis-check-rdb ./6379-rdb.rdb
[offset 0] Checking RDB file ./6379-rdb.rdb
[offset 26] AUX FIELD redis-ver = '5.0.3'
[offset 40] AUX FIELD redis-bits = '64'
[offset 52] AUX FIELD ctime = '1552061947'
[offset 67] AUX FIELD used-mem = '852984'
[offset 83] AUX FIELD aof-preamble = '0'
[offset 85] Selecting DB ID 0
[offset 105] Checksum OK
[offset 105] \o/ RDB looks OK! \o/
[info] 1 keys read
[info] 0 expires
[info] 0 already expired
AOF持久化存儲(chǔ)
AOF持久化存儲(chǔ)是什么
AOF持久化存儲(chǔ)便是以日志的形式將redis存儲(chǔ)在aof_buf緩沖區(qū)中的數(shù)據(jù)寫(xiě)入到磁盤(pán)中。簡(jiǎn)而言之,就是記錄redis的操作日志,將redis執(zhí)行過(guò)的命令記錄下載,當(dāng)我們需要數(shù)據(jù)恢復(fù)時(shí),redis去重新執(zhí)行一次日志文件中的命令.
如何配置持久化存儲(chǔ)
// 將no改為yes,控制aof開(kāi)啟與否
appendonly no
// 控制aof文件名稱(chēng),存儲(chǔ)的目錄便是dir配置項(xiàng)
appendfilename "appendonly.aof"
// 三種備份策略(三者只需要開(kāi)啟以一個(gè)即可)
# appendfsync always // 命令寫(xiě)入立即寫(xiě)入磁盤(pán)
appendfsync everysec // 每秒實(shí)現(xiàn)文件的同步,寫(xiě)入磁盤(pán)
# appendfsync no // 隨機(jī)進(jìn)行文件的同步,同步操作則交給操作系統(tǒng)來(lái)負(fù)責(zé),通常時(shí)間是最長(zhǎng)30s
AOF持久化存儲(chǔ)實(shí)現(xiàn)原理
aof日志追加方式實(shí)現(xiàn)持久化存儲(chǔ),需要經(jīng)歷如下四個(gè)過(guò)程.命令寫(xiě)入->文件同步->文件重寫(xiě)->文件重載
1.redis命令寫(xiě)入,此時(shí)會(huì)將redis命令寫(xiě)入aof_buf換從區(qū).
2.緩沖區(qū)中數(shù)據(jù)根據(jù)備份策略實(shí)現(xiàn)寫(xiě)入日志文件.
3.當(dāng)aof的文件越來(lái)越龐大,會(huì)根據(jù)我們的配置策略來(lái)實(shí)現(xiàn)aof的重寫(xiě),實(shí)現(xiàn)文件的壓縮,減少體積.
4.當(dāng)redis重新啟動(dòng)時(shí),在去重寫(xiě)加載aof文件,達(dá)到數(shù)據(jù)恢復(fù)的目的.
命令寫(xiě)入
命令寫(xiě)入主要是將文件執(zhí)行過(guò)的命令寫(xiě)入到日志文件中.并且日志文件尊徐文本協(xié)議格式,下面示例代碼便是aof日志文件中存儲(chǔ)的內(nèi)容格式.
*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n
aof采用的是文本協(xié)議格式。主要是原因根據(jù)資料提示,可以能使由于如下原因.
1.文本協(xié)議的兼容性好.前面我們提及到了rdb文件是進(jìn)行二進(jìn)制加密,可能不同版本之間會(huì)出現(xiàn)不兼容的情況,采用文本協(xié)議可以加避免該問(wèn)題。同時(shí)文本協(xié)議也可以減少跨平臺(tái)使用所帶來(lái)的諸多問(wèn)題.
2.可讀性強(qiáng).由于aof是將命令寫(xiě)入文件中,我們可以直接查看命令內(nèi)容,同時(shí)也可以修改日志文件內(nèi)容.
3.開(kāi)啟aof后,所有的文件文件都包含追加操作,直接采用文本協(xié)議,減少二次開(kāi)銷(xiāo)(這一點(diǎn),個(gè)人不是很理解.因?yàn)槲覀兊腶of是保存的是命令,當(dāng)我們?cè)俅稳ゼ虞d的時(shí)候,會(huì)去執(zhí)行一次里面的命令,當(dāng)文件大的時(shí)候應(yīng)該是比較耗時(shí)的吧。如果沒(méi)有做好文件重寫(xiě)策略,大量重復(fù)無(wú)效的命令執(zhí)行,對(duì)于二進(jìn)制加密的rdb格式,不需要再去轉(zhuǎn)換,這一點(diǎn)確實(shí)可以減少二次開(kāi)銷(xiāo)).
文件寫(xiě)入
文件寫(xiě)入是將aof_buf緩沖區(qū)的命令寫(xiě)入到文件中.文件寫(xiě)入的策略有如下三種方式
配置項(xiàng) | 配置說(shuō)明 |
---|---|
always | 命令寫(xiě)入到aof_buf緩沖區(qū)中之后立即調(diào)用系統(tǒng)的<font color='red'>fsync操作</font>同步到aof文件中,fsync完成后線(xiàn)程返回. |
everysec | 命令寫(xiě)入到aof_buf緩沖區(qū)后<font color='red'>每隔一秒</font>調(diào)用系統(tǒng)的<font color='red'>write操作</font>,write完成后線(xiàn)程返回. |
no | 命令寫(xiě)入aof_bug緩沖區(qū)后調(diào)用系統(tǒng)write操作,不對(duì)aof文件做fsync同步,同步硬盤(pán)操作由<font color='red'>系統(tǒng)操作</font>完成,時(shí)間一般最長(zhǎng)為30s. |
系統(tǒng)調(diào)用write和fsync說(shuō)明:
·write操作會(huì)觸發(fā)延遲寫(xiě)( delayed write) 機(jī)制。 Linux在內(nèi)核提供頁(yè)緩沖區(qū)用來(lái)提高硬盤(pán)IO性能。 write操作在寫(xiě)入系統(tǒng)緩沖區(qū)后直接返回。 同步硬盤(pán)操作依賴(lài)于系統(tǒng)調(diào)度機(jī)制, 例如: 緩沖區(qū)頁(yè)空間寫(xiě)滿(mǎn)或達(dá)到特定時(shí)間周期。 同步文件之前, 如果此時(shí)系統(tǒng)故障宕機(jī), 緩沖區(qū)內(nèi)數(shù)據(jù)將丟失.
·fsync針對(duì)單個(gè)文件操作( 比如AOF文件) , 做強(qiáng)制硬盤(pán)同步, fsync將阻塞直到寫(xiě)入硬盤(pán)完成后返回, 保證了數(shù)據(jù)持久化.
文件寫(xiě)入策略分析
配置為always時(shí), 每次寫(xiě)入都要同步AOF文件, 在一般的SATA硬盤(pán)上, Redis只能支持大約幾百TPS寫(xiě)入, 顯然跟Redis高性能特性背道而馳,
不建議配置.
配置為no。由于操作系統(tǒng)每次同步AOF文件的周期不可控, 而且會(huì)加大每次同步硬盤(pán)的數(shù)據(jù)量, 雖然提升了性能, 但數(shù)據(jù)安全性無(wú)法保證.
配置為everysec。是建議的同步策略, 也是默認(rèn)配置, 做到兼顧性能和數(shù)據(jù)安全性。 理論上只有在系統(tǒng)突然宕機(jī)的情況下丟失1秒的數(shù)據(jù).
文件重載
1.為什么要文件做文件重載操作?
由于aof采用的是日志追加,我們r(jià)edis命令不斷的寫(xiě)入,aof文件的體積也也會(huì)不斷的增加.因此redis引入了aof重寫(xiě)機(jī)制達(dá)到減小aof文件體積.<font color="blue">aof文件重寫(xiě)是把redis進(jìn)程內(nèi)的數(shù)據(jù)轉(zhuǎn)換為寫(xiě)命令同步到新的aof文件的過(guò)程(這一點(diǎn)其實(shí)不是特別明白,文件重寫(xiě)不是針對(duì)aof文件文件做操作的嗎?為什么這里是將redis進(jìn)程內(nèi)的數(shù)據(jù)轉(zhuǎn)換為命令寫(xiě)入文件,這里的進(jìn)程內(nèi)的數(shù)據(jù)不是太明白,還有待深入研究.個(gè)人理解的就是將舊的aof文件內(nèi)容根據(jù)重寫(xiě)策略,進(jìn)行優(yōu)化生成新的aof文件。).</font>
2.文件重載有什么好處?
文件重載主要優(yōu)化的地方有如下三點(diǎn)。使用文件重載既可以減少文件的體積,同時(shí)去掉了一些無(wú)效的操作,可以加快文件重載效率.
a.將一些在進(jìn)程內(nèi)無(wú)效的數(shù)據(jù)不在寫(xiě)入新的文件.如過(guò)期的鍵.
b.去掉一些無(wú)效的命令.如del key1.
c.簡(jiǎn)化操作.如lpush list a,lpush list b.直接可以簡(jiǎn)化為lpush list a b.
3.文件重載由那些方式?
文件重載有自動(dòng)觸發(fā)機(jī)制和手動(dòng)觸發(fā)機(jī)制.
手動(dòng)觸發(fā)機(jī)制:直接使用bgrewriteaof命令即可.該命令在fork子進(jìn)程的時(shí)候會(huì)發(fā)生阻塞.
自動(dòng)觸發(fā)機(jī)制:
auto-aof-rewrite-min-size:aof重寫(xiě)時(shí)文件最小的體積,默認(rèn)的是64M.
auto-aof-rewrite-percentage:代表當(dāng)前AOF文件空間( aof_current_size) 和上一次重寫(xiě)后AOF文件空間( aof_base_size) 的比值.
自動(dòng)觸發(fā)時(shí)機(jī)=aof_current_size>auto-aof-rewrite-minsize&&( aof_current_size-aof_base_size) /aof_base_size>=auto-aof-rewritepercentage
其中aof_current_size和aof_base_size可以在info Persistence統(tǒng)計(jì)信息中查看.
4.文件重載實(shí)現(xiàn)的原理是怎樣的?
1.執(zhí)行重寫(xiě)命令,判斷是否存在子進(jìn)程。
如果已經(jīng)有子進(jìn)程在進(jìn)行aof重寫(xiě),則會(huì)提示如下信息.
ERR Background append only file rewriting already in progress
如果已經(jīng)存在子進(jìn)程在進(jìn)行bgsave操作,重寫(xiě)命令會(huì)延遲到bgsave命令完成之后進(jìn)行,會(huì)返回如下信息.
Background append only file rewriting scheduled
2.父進(jìn)程會(huì)fork一個(gè)子進(jìn)程,在fork子進(jìn)程的過(guò)程中會(huì)造成阻塞.
3.fork子進(jìn)程結(jié)束阻塞解除,進(jìn)行其他新的命令操作.新的命令依舊根據(jù)文件寫(xiě)入策略同步數(shù)據(jù),保證aof機(jī)制正確進(jìn)行(圖中3.1).
4.子進(jìn)程在進(jìn)行寫(xiě)的過(guò)程中,由于fork操作運(yùn)用的是寫(xiě)時(shí)復(fù)制技術(shù),子進(jìn)程只能共享fork操作時(shí)內(nèi)存保留的數(shù)據(jù),新的數(shù)據(jù)是無(wú)法操作的.父進(jìn)程在這過(guò)程中仍然在響應(yīng)其他的命令,于是Redis會(huì)使用aof重寫(xiě)緩存區(qū)來(lái)保存這部分新的數(shù)據(jù)(圖中3.2).
5.子進(jìn)程進(jìn)行根據(jù)重寫(xiě)規(guī)則將數(shù)據(jù)寫(xiě)入到新的aof文件中,并且每次寫(xiě)入有大小限制,通過(guò)aof-rewrite-incremental-fsync配置項(xiàng)來(lái)控制,默認(rèn)是32M,這樣可以見(jiàn)減少單次刷盤(pán)(I/O寫(xiě))造成硬盤(pán)阻塞.
6.子進(jìn)程在完成重寫(xiě)之后,會(huì)向父進(jìn)程發(fā)送信息,父進(jìn)程更新統(tǒng)計(jì)信息.可參看info persistence下的aof_*相關(guān)統(tǒng)計(jì)。
7.父進(jìn)程會(huì)把新寫(xiě)入存在aof重寫(xiě)緩沖區(qū)的數(shù)據(jù)寫(xiě)入到aof文件中(圖5.2).
8.將新的aof文件替換掉舊的aof文件.
<font color='blue'>在第3和4中,其實(shí)不是特別理解.不理解的是為什么父進(jìn)程在響應(yīng)新的命令會(huì)寫(xiě)入舊的aof文件,還要aof重寫(xiě)緩存區(qū).個(gè)人理解的是,父進(jìn)程在進(jìn)行新命令寫(xiě)入處理的策略是,按照正常的備份策略寫(xiě)入舊的aof的同時(shí)也把新的命令寫(xiě)入重寫(xiě)緩沖區(qū),在第5.2中將這部分新的數(shù)據(jù)寫(xiě)入到新的aof文件中,這樣保證數(shù)據(jù)的完整性.</font>
文件重載
文件重載就是將文件重新加入到redis服務(wù)中.比如redis服務(wù)重啟用于數(shù)據(jù)恢復(fù).redis的重載機(jī)制非常完善,具體流程如下.
AOF文件常見(jiàn)的問(wèn)題處理
1.文件損壞
我們?cè)诩虞d損壞的文件是可能提示如下信息.
Bad file format reading the append only file: make a backup of your AOF file,then use ./redis-check-aof --fix <filename>
此時(shí)我們可以使用redis-check-aof --fix命令進(jìn)行修復(fù)(記得對(duì)文件做個(gè)備份).修復(fù)后使用diff-u進(jìn)行數(shù)據(jù)對(duì)比,找出部分丟失的數(shù)據(jù).
2.文件加載不完整
這可能是數(shù)據(jù)在備份的時(shí)候,redis服務(wù)異常,導(dǎo)致備份不完整.可以使用redis的aof-load-truncated兼容該異常
AOF的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
多種文件寫(xiě)入(fsync)策略.
數(shù)據(jù)實(shí)時(shí)保存,數(shù)據(jù)完整性強(qiáng).即使丟失某些數(shù)據(jù),制定好策略最多也是一秒內(nèi)的數(shù)據(jù)丟失.
可讀性強(qiáng),由于使用的是文本協(xié)議格式來(lái)存儲(chǔ)的數(shù)據(jù),可有直接查看操作的命令,同時(shí)也可以手動(dòng)改寫(xiě)命令.
缺點(diǎn):
文件體積過(guò)大,加載速度比rbd慢.由于aof記錄的是redis操作的日志,一些無(wú)效的,可簡(jiǎn)化的操作也會(huì)被記錄下來(lái),造成aof文件過(guò)大.但該方式可以通過(guò)文件重寫(xiě)策略進(jìn)行優(yōu)化.
選擇AOF還是RDB進(jìn)行數(shù)據(jù)的持久化
1.針對(duì)不同的情況來(lái)選擇,建議使用兩種方式相結(jié)合.
2.針對(duì)數(shù)據(jù)安全性、完整性要求高的采用aof方式.
3.針對(duì)不太重要的數(shù)據(jù)可以使用rdb方式.
4.對(duì)于數(shù)據(jù)進(jìn)行全量備份,便于數(shù)據(jù)備份的可以采用rdb方式.
原文轉(zhuǎn)自微信公眾號(hào):浪子編程走四方
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。