一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

深度剖析 Redis 持久化機制

 昵稱10087950 2022-09-01 發(fā)布于江蘇

日英文

If you\'re brave enough to say GOODBYE, life will reward you with a new HELLO. 

只要你勇敢地說出再見,生活一定會賜予你一個新的開始。

每日掏心話

人生,原本就是風塵中的滄海桑田,只是,回眸處,世態(tài)炎涼演繹成了苦辣酸甜。

責編:樂樂 | 來自:繪你一世傾城

鏈接:juejin.cn/post/6844904055098048519

編程技術圈(ID:study_tech)第 1697 期推文

往日回顧:2022科技公司薪酬排行榜,來了!

     正文     

大家好,我是小樂。

Redis將數(shù)據(jù)存儲在內(nèi)存中,宕機或重啟都會使內(nèi)存數(shù)據(jù)全部丟失, Redis的持久化機制用來保證數(shù)據(jù)不會因為故障而丟失。

Redis提供兩種持久化方式,一種為內(nèi)存快照方式,生成rdb文件,rdb是某一時間點內(nèi)存數(shù)據(jù)的全量備份,文件內(nèi)容是存儲結構非常緊湊的二進制序列化形式;另一種是AOF日志備份方式,日志保存的是基于數(shù)據(jù)的連續(xù)增量備份,日志文件內(nèi)容是服務端執(zhí)行的每一條指令的記錄文本。

兩種方式各有優(yōu)略,下面的章節(jié)會詳細介紹兩種持久化機制的實現(xiàn)原理和使用技巧。

圖片

1.內(nèi)存快照

圖片
Redis進行快照數(shù)據(jù)持久化時,為了不阻塞線上業(yè)務,要能夠響應客戶端請求??煺粘志没墓ぷ魇菍⒁粋€時間點內(nèi)存數(shù)據(jù)序列化后同步到磁盤rdb文件。備份數(shù)據(jù)如何在內(nèi)存中瞬間凝固,不再改變?文件IO操做怎樣才能不拖累服務端對客戶端的正常響應?這一切都要從Copy On Write說起。

1.1 快照原理——Copy On Write

Copy On Write簡寫為COW,又叫寫時復制,是操作系統(tǒng)為優(yōu)化使用子進程采取的一種策略。
類Unix系統(tǒng)創(chuàng)建進程的主要方式是調(diào)用glibc的函數(shù)fork,熟悉Linux的人都知道:Linux操作系統(tǒng)的進程都是通過init進程(pid=1)或者其子進程fork(vfork)出來的。
fork()會產(chǎn)生一個與父進程完全相同的子進程,有兩次返回:將子進程的pid返回給父進程,0返回給子進程。如果小于0,說明創(chuàng)建進程失??!下面是一個C語言的例子:
#include <unistd.h>#include <stdio.h>
int main() { pid_t pid; int count = 0; pid = fork(); if (pid < 0) printf('error in fork!'); else if (pid == 0) { printf('child process, process id is %d/n', getpid()); count++; } else { printf('parent process, process id is %d/n', getpid()); count++; } printf('count total: %d/n', count); return 0;}
輸出結果為:
parent process, process id is 23049count total: 1child process, process id is 23050count total: 1

當前進程調(diào)用fork(),會創(chuàng)建一個跟當前進程完全相同的子進程(除了pid),

所以子進程同樣是會執(zhí)行fork()之后的代碼。

父子進程的count變量都是1,

說明父子進程使用了各自獨有的棧區(qū)(count變量存放在棧區(qū))。

我們先來看一下CPU執(zhí)行程序的流程。


圖片

CPU在加載執(zhí)行程序時,首先按照虛擬地址來尋址,然后通過MMU(內(nèi)存管理單元)將虛擬地址轉換為物理地址。因為只有程序的一部分加入到內(nèi)存中(按頁加載),所以會出現(xiàn)所尋找的地址不在內(nèi)存中的情況(CPU產(chǎn)生缺頁異常),如果在內(nèi)存不足的情況下,就會通過頁面調(diào)度算法來將內(nèi)存中的頁面置換出來,然后將在外存中的頁面加入到內(nèi)存中,使程序繼續(xù)正常運行。

Linux操作系統(tǒng)的每一個進程,都會分配有虛擬地址物理地址,虛擬地址和物理地址通過MMU保持映射關系。一個進程是一個主體,它有靈魂有身體,靈魂就是其虛擬地址空間(有相應的數(shù)據(jù)結構表示),包括:正文段、數(shù)據(jù)段、堆、棧這四個部分;相應的,內(nèi)核會為這四個部分分配各自的物理塊(進程的身體)即:正文段塊、數(shù)據(jù)段塊、堆塊、棧塊。
我們再來看一下fork進程時寫時復制的過程:


圖片

圖片圖片圖片圖片圖片圖片

牛逼啊!接私活必備的 N 個開源項目!趕快收藏

fork產(chǎn)生子進程時,操作系統(tǒng)只為新生成的子進程創(chuàng)建虛擬空間結構,它們復制于父進程的虛擬空間結構,但是不為這些段分配物理內(nèi)存,它們共享父進程的物理空間,當父子進程中有更改相應段的行為發(fā)生時,再為子進程相應的段分配物理空間,這就是寫時復制。

1.2 快照執(zhí)行流程

Redis在持久化時會調(diào)用glibc的函數(shù)fork產(chǎn)生一個子進程,快照持久化完全交給子進程來處理,父進程繼續(xù)處理客戶端請求。


圖片

可以通過在Redis客戶端輸入bgsave命令來觸發(fā)快照保存操作,Redis調(diào)用bgsaveCommand函數(shù),該函數(shù)fork一個子進程,子進程剛剛產(chǎn)生時,它和父進程共享內(nèi)存里面的代碼段和數(shù)據(jù)段。這時將父子進程比喻成一個連體嬰兒非常恰當,這是Linux操作系統(tǒng)的機制,為了節(jié)約內(nèi)存資源,盡可能的將內(nèi)存資源共享起來。在進程分離的一瞬間,內(nèi)存的增長幾乎沒有明顯的變化。子進程因為沒有數(shù)據(jù)的變化,它能感知到的內(nèi)存數(shù)據(jù)在進程產(chǎn)生的一瞬間就凝固了,再也不會改變。父進程可以繼續(xù)處理客戶端請求,當子進程推出后,父進程調(diào)用相關函數(shù)處理子進程的善后工作。

圖片

2.AOF持久化

圖片
AOF日志存儲的Redis服務器的順序指令序列,只記錄對內(nèi)存進行修改的指令記錄。有了AOF文件,就可以通過一個空的Redis實例順序執(zhí)行所有的指令來恢復Redis當前實例的內(nèi)存數(shù)據(jù)結構的狀態(tài),這個過程叫做重放

2.1 AOF日志文件寫入

AOF日志以文件的形式存在,寫文件通過操作系統(tǒng)提供的write函數(shù)執(zhí)行,但是write之后的數(shù)據(jù)只是寫到了內(nèi)核的一個緩沖區(qū)中,然后內(nèi)核還需要異步的調(diào)用fsync函數(shù)異步的將數(shù)據(jù)刷回磁盤。fsync函數(shù)是一個阻塞并且緩慢的操作,如果機器突然宕機,AOF日志內(nèi)容可能還沒來的及完全刷到磁盤,這時候就會丟失數(shù)據(jù)。Redis通過appendfsync配置控制執(zhí)行fsync的頻次,具體有如下三種模式:
  • no: 永遠不調(diào)用fsync,讓操作系統(tǒng)決定何時同步磁盤,這樣做很不安全,但是Redis的性能最高。
  • always: 每執(zhí)行一次寫入操作就執(zhí)行一次fsync,雖然數(shù)據(jù)安全性高,會導致執(zhí)行非常緩慢。
  • everysec: 每隔1s執(zhí)行一次fsync,這個1s的周期是可以配置的,這是數(shù)據(jù)安全性和性能之間的折中方案,在保證高性能的同時,盡量使數(shù)據(jù)少丟失。推薦在生產(chǎn)環(huán)境中使用。

2.2 AOF執(zhí)行流程

Redis收到客戶端的指令以后,首先進行參數(shù)校驗、邏輯處理,如果沒有問題,會判斷是否開啟AOF,如果開啟,則會將每條命令執(zhí)行完畢后同步寫入aof_buf中,aof_buf是個全局的SDS類型的緩沖區(qū)。


圖片


每一條命令的執(zhí)行都會調(diào)用call函數(shù),注意:Redis服務端是先執(zhí)行指令再將命令寫入aof_buf。

2.3 日志瘦身——AOF重寫

Redis服務端在長期運行過程中,AOF日志會越來越長,如果實例宕機或者重啟,重放整個AOF日志會非常耗時,導致Redis長時間無法對外提供服務,所以需要對AOF日志進行瘦身,即:AOF重寫。
我們考慮一下AOF和RDB文件的加載過程:RDB只需要把相應的數(shù)據(jù)加載都內(nèi)存并生成相應的數(shù)據(jù)結構就可以了,有些結構如intset、ziplist,保存的時候直接按照字符串保存,加載速度非??臁5茿OF日志文件的加載需要創(chuàng)建一個偽客戶端,順序執(zhí)行一遍命令,根據(jù)Redis作者做的測試,RDB在10~20秒能加載1GB的文件,AOF的速度是RDB的一半(如果做了AOF重寫會加快)
通過Redis客戶端bgrewriteaof指令對AOF日志進行瘦身過程如下:


圖片


Redis服務端調(diào)用bgrewriteaofCommand命令創(chuàng)建管道,創(chuàng)建管道對作用是AOF重寫過程中批量接收服務端累積的命令;創(chuàng)建完管道以后,fork進程,子進程調(diào)用rewriteAppendOnlyFile執(zhí)行AOF重寫操作;父進程記錄一些統(tǒng)計指標后繼續(xù)進入主循環(huán)處理客戶端請求,待子進程結束以后,處理一些善后工作。瘦身工作就是子進程對所有數(shù)據(jù)庫中的鍵各自生成一條相應的執(zhí)行命令,最后將重寫開始后父進程繼續(xù)執(zhí)行的命令進行回放,生成一個新的AOF文件。另外,搜索公眾號Java架構師技術后臺回復“面試題”,獲取一份驚喜禮包。

例如執(zhí)行了下面的命令:
127.0.0.1:6379> lpush list guo zhao ran(integer) 3127.0.0.1:6379> lpop list'ran'127.0.0.1:6379> lpop list'zhao'127.0.0.1:6379> lpush list zhao(integer) 2
AOF文件會保存對list操作的4條命令,但是list現(xiàn)在內(nèi)存中的元素是這樣的:
127.0.0.1:6379> lrange list 0 -11) 'zhao'2) 'guo'
AOF重寫以后就日志文件內(nèi)容直接就變?yōu)榱?/span>lpush list zhao guo。日志瘦身既可以減小文件大小,又可以提高加載速度。

圖片

3.混合持久化

圖片

RDB和AOF實現(xiàn)持久化的方式各有優(yōu)缺點,我們來簡單總結一下:

RDB保存的是一個時間的快照,如果發(fā)生故障,丟失的是最后一次RDB執(zhí)行時間點到故障發(fā)生的時間間隔之內(nèi)產(chǎn)生的數(shù)據(jù)。如果Redis數(shù)據(jù)量很大,QPS很高,執(zhí)行一次RDB需要的時間會相應增加,發(fā)生故障時丟失的數(shù)據(jù)也會增多。

AOF保存的是一條條的命令,理論上可以做到發(fā)生故障時只丟失一條命令。但是由于操作系統(tǒng)中執(zhí)行寫文件操作代價很大,Redis提供了配置參數(shù),可以對完全性和性能取折中,設置不同的配置策略。但是重放AOF日志相對于使用RDB來說還是慢很多。

Redis4.0為了解決這個問題,帶來了一個新的持久化選項——混合持久化?;旌铣志没侵高M行AOF重寫時子進程將當前時間點的數(shù)據(jù)快照保存為RDB文件格式,而后將父進程累積命令保存為AOF格式,最終生成的格式如下圖所示:



圖片


將RDB文件內(nèi)容和增量AOF日志文件存在一起,這里的AOF日志不再是全量日志,通常這部分AOF日志很小。于是在Redis重啟的時候,可以先加載rdb內(nèi)容,然后再重放增量AOF日志,就可以完全替代之前的AOF全量文件重放,重啟效率會得到大幅度提升。

圖片

4. Redis持久化相關配置

圖片
下面總結一下Redis4.0版持久化相關的配置及其含義。

配置項可選值默認值作用
save
save <seconds> <changes>
save 900 1
save 300 10
save 60 10000
save '':禁用快照備份,默認關閉
save 900 1:在900秒內(nèi)有1個key被改動,自動保存到dump.rdb文件中
save 300 10:在300秒內(nèi)有10個key被改動,自動保存到dump.rdb文件中
save 60 10000:在60秒內(nèi)有10000個key被改動,自動保存到dump.rdb文件中
以上3中條件任意一種被滿足就會觸發(fā)保存
stop-writes-on-bgsave-error
yes/no
yes
開啟該參數(shù)后,如果開啟了RDB快照(即配置了save指令),并且最近一次快照執(zhí)行失敗,則Redis將停止接收寫相關的請求
rdbcompression
yes/no
yes
執(zhí)行rdb的時候是否將string類型的數(shù)據(jù)壓縮
rdbchecksum
yes/no
yes
是否開啟rdb文件內(nèi)容的校驗
dbfilename
文件名稱
dump.rdb
rdb文件名稱
dir
文件路徑
./
RDB和AOF文件存放路徑
appendonly
yes/no
no
是否開啟AOF功能
appendfilename
文件名稱
appendonly.aof
AOF文件名稱
appendfsync
always/everysec/no
everysec
fsync執(zhí)行頻次,上邊有說到
no-appendfsync-on-rewrite
yes/no
no
開啟該參數(shù)后,如果后臺正在執(zhí)行一次rdb快照或者aof重寫,則主進程不再進行fsync操作,即使將appendsync配置成always或者everysec
auto-aof-rewrite-percentage
百分比
100
和auto-aof-rewrite-min-size配和使用,下面會講解
auto-aof-rewrite-min-size
文件大小
64M
當AOF文件大于64M時,并且AOF文件當前大小比基準大小增長了100%時會觸發(fā)一次AOF重寫。
aof-load-truncated
yes/no
yes
AOF以追加日志的方式生成,當服務端發(fā)生故障時會有命令不完整的情況。開啟該參數(shù)后,在這種情況下,AOF會截斷尾部不完整的命令繼續(xù)加載,并且在日志中給出提示。
aof-use-rdb-preamble
yes/no
yes
是否開啟混合持久化
aof-rewrite-incremental-fsync
yes/no
yes
開啟該參數(shù)后,AOF重寫時每產(chǎn)生32MB數(shù)據(jù)執(zhí)行一次fsync

圖片

5.總結

圖片

Redis是內(nèi)存數(shù)據(jù)庫,機器故障或重啟之后,內(nèi)存數(shù)據(jù)全部丟失,所以需要持久化來保證數(shù)據(jù)安全。

Redis提供了快照RDB和AOF日志同步兩種方式進行數(shù)據(jù)持久化,快照RDB實現(xiàn)原理是Copy On Write,優(yōu)點是機器加載速度快,缺點是執(zhí)行緩慢,QPS高的情況下會丟失大量數(shù)據(jù);AOF則是將命令一條條的有序存放到日志文件中,優(yōu)點是盡可能少的丟失數(shù)據(jù),缺點是日志文件重放緩慢,日志文件會很大,可以通過重寫AOF日志來實現(xiàn),另外提供了這種的配置方案異步執(zhí)行fsync操作。

生產(chǎn)環(huán)境中推薦使用混合持久化,這種方式綜合了RDB和AOF兩種方式的優(yōu)點。文章最后總結了一下Redis持久化配置項。本文是筆者學習Redis持久化的總結,希望能對讀者有所幫助。


歡迎有需要的同學試試,如果本文對您有幫助,也請幫忙點個 贊 + 在看 啦!??

你還有什么想要補充的嗎?

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    色偷偷亚洲女人天堂观看| 亚洲熟妇av一区二区三区色堂| 丝袜视频日本成人午夜视频| 国产日韩熟女中文字幕| 一区二区日韩欧美精品| 人妻少妇久久中文字幕久久| 日本免费熟女一区二区三区| 美女露小粉嫩91精品久久久| 国产日韩熟女中文字幕| 亚洲欧美日韩精品永久| 亚洲第一视频少妇人妻系列| 日韩精品一区二区三区含羞含羞草| 欧美精品在线播放一区二区| 国产熟女一区二区不卡| 97精品人妻一区二区三区麻豆| 东京热一二三区在线免| 久久精品少妇内射毛片| 国产精品久久香蕉国产线| 国产亚洲精品俞拍视频福利区| 国产日韩欧美国产欧美日韩| 久久中文字幕中文字幕中文| 精品国产丝袜一区二区| 国产精品免费视频视频| 99久久精品免费看国产高清| 欧美欧美欧美欧美一区| 人妻熟女欲求不满一区二区| 国产成人精品资源在线观看| 偷自拍亚洲欧美一区二页| 尤物久久91欧美人禽亚洲| 在线一区二区免费的视频| 一区二区三区亚洲国产| 欧美中文日韩一区久久| 伊人久久青草地综合婷婷| 99国产高清不卡视频| 国产超薄黑色肉色丝袜| 国产性情片一区二区三区| 欧美日韩有码一二三区| 国产精品一区二区高潮| 国产在线成人免费高清观看av| 一区二区免费视频中文乱码国产| 亚洲精品中文字幕欧美|