Redis的持久化

redis是一個內存數據庫,是把數據存儲在內存中的,而我們知道內存中的數據是不持久的,一旦服務器重啟或者進程重啟,內存的數據就丟失了.為了讓數據達到持久化的效果,就必須把數據寫到硬盤上.

redis相對于mysql這樣的關系型數據庫最明顯的優勢就是快.所以為了保證速度快,數據還得在內存中,但是為了持久,數據還要想辦法存儲在硬盤上.

Redis為了應對這樣的情況,決定把數據在內存中存儲一份,同時在硬盤上也存儲一份.這樣的兩份數據,理論上是完全相同的,實際上可能存在差異,取決于我們具體怎么進行持久化.

當要插入一個新的數據的時候,就需要把這個數據,同時寫入內存和硬盤.但說是同時寫,實際上怎么寫入硬盤是有不同的策略的,應用這些策略,就可以保證redis整體的效率還是足夠高的.

當查詢某個數據的時候,直接從內存讀取.硬盤中的數據只是在redis重啟的時候,用來回復內存中的數據的.

代價就是消耗了更多的空間,同一份數據存儲了兩份,但是硬盤空間畢竟是比較廉價的,這樣的開銷并不會帶來很多的成本.


redis實現持久化的策略

redis實現持久化的整體策略有兩種,RDB和AOF.

RDB:Redis DataBase.AOF:Append Only File.

RDB是定期備份,AOF是實時備份.

RDB持久化

RDB持久化是定期的把當前進程數據生成快照保存到硬盤的過程.

后續redis一旦重啟了,就可以根據硬盤的中快照把內存中的數據給回復回來.

RDB定期備份的兩種方式

1.手動觸發

程序員通過redis客戶端,執行特定的命令,來觸發快照的生成.

save命令,執行save命令的時候,redis服務器會在單線程模型下全力以赴的進行快照生成的操作,此時就會阻塞redis其他客戶端的命令,一般不建議使用save.

bgsave,bg是background的縮寫,此命令不會影響redis服務器處理其他客戶端的請求和命令.此命令是redis通過多進程的方式來完成并發編程從而實現bgsave.

2.自動觸發

我們可以在redis配置文件中,設置一下,讓redis每隔多長時間以及每產生多少次修改就觸發備份操作.

redis生成rdb文件,是存放在redis的工作目錄中的,redis的工作目錄也是在redis配置文件中進行設置的.

我們不僅可以修改redis的工作目錄,也可以修改生成的rdb文件的名字.

dump.rdb是RDB機制生成的鏡像文件,redis服務器默認是開啟了rdb的.此rdb文件時一個二進制的文件,把內存中的數據,以壓縮的形式,保存到這個二進制文件中.(壓縮會消耗一定的cpu資源,但是能節省存儲空間).

這個二進制文件,我們不能隨意修改.redis服務器重新啟動,會嘗試加載這個rdb文件,如果發現格式錯誤,就可能會加載數據失敗.

需要注意的是,rdb文件,即使我們不去主動修改它,但是也可能會出現一些意外情況,一旦通過一些操作(比如網絡傳輸)引起這個文件被破壞,此時redis服務器也是無法正常啟動的.

rdb的持久化操作可以執行多次,當執行生成rdb鏡像文件操作的時候,此時就會把要生成的快照數據,先保存到一個臨時文件中,當這個快照生成完畢之后,在刪除之前的rdb文件,把新生成的rdb臨時文件名字改為剛才的dump.rdb,所以自始至終,rdb文件是始終只有一個的.


RDB自動觸發的條件

我們可以在redis的配置文件中查看達到自動觸發rdb的條件.?

15分鐘之后如果至少修改了一次或者5分鐘之后至少修改了10次或者1分鐘之后至少修改了10000次就會自動觸發rdb機制.

注意:時間要滿足的同時修改次數也要滿足.

此處的數值都可以自行修改.但是修改上述的數據的時候,要有一個基本的原則:生成一個rdb快照,是一個比較高的成本,不能讓這個操作執行的太過頻繁.

也正是因為rdb生成的不能太過頻繁,這就導致,快照里的數據,和當前實際的數據情況可能是存在偏差的.


手動執行bgsave觸發一次生成快照

由于這里的數據比較少,執行bgsave瞬間就完成了,立即查看應該是有結果的.如果這里的數據比較多,執行bgsave就可能需要消耗一定的時間,立即查看不一定就是生成完畢了.

在rdb鏡像文件里可以隱約的看到我們的插入的key.

我們重啟redis服務器,再次進入redis客戶端查看數據.

通過上述操作,就可以看到,redis服務器在重啟的時候,加載了rdb文件的內容,恢復了之前內存中的數據狀態.


插入新的key,不手動執行bgsave

我們插入一個新的key之后,重新啟動redis服務器,再次查看內容.

可以看到我們新插入的key4依然存在,但是我們并沒有手動執行bgsave,同時也沒有達到自動觸發的條件,這是什么原因呢?

這是因為如果是通過正常流程重新啟動redis服務器,此時redis服務器會在退出的時候自動觸發生成rdb的操作.但是如果是異常重啟(kill -9或者服務器掉電),此時redis服務器來不及生成rdb,內存中尚未保存的數據就會隨著redis啟動而真的丟失了!!!

所以redis自動觸發rdb會在多個場景中存在:

1.在配置文件中配置save 時間 次數,表示在多長時間之后,執行次數達到多少,才觸發.

2.通過shutdown命令(不帶參數),關閉redis服務器,此處的關閉屬于是正常關閉,也會觸發生成rdb快照的操作.我們上述的service redis-server restart也屬于是正常關閉.

3.redis進行主從復制的時候,主節點也會自動生成rdb快照,然后把rdb快照文件內容傳輸給從節點.

如果正常情況的關閉,我們是不必擔心內存數據丟失的情況,在實際開發中我們更擔心異常情況的出現導致redis服務器異常關閉.比如使用kill命令(kill -9 redis進程id)的方式來直接殺死redis進程,此時就會導致新插入的數據的丟失.

注意在ubuntu系統下,由于我們是通過service的方式來啟動redis,所以會存在一個守護進程來時刻檢測redis的情況,當redis服務器掛掉之后,會迅速在拉起一個redis,所以雖然kill掉了redis進程,但是查看進程信息redis還存在,但是此時的進程id已經不一致了.


bgsave操作流程是創建子進程,由子進程完成持久化操作.

持久化會把數據寫入到一個新的臨時文件中,最后使用新的文件來代替舊的文件.

如果直接使用save命令,此時是不會創建子進程和進行文件替換的.save命令是直接在當前進程中,往同一個文件中寫入數據,不會創建新的文件.

inode相當于是文件的標識,inode不同,說明文件已經不是同一個文件了.


通過配置自動生成rdb快照

我們可以在配置文件中修改save來設置自動生成快照的條件.對于redis來說,修改配置文件之后,一定要重啟服務器,才能生效,如果想要立即生效,也可以通過命令的方式修改.

save " "是用來關閉自動生成快照的.


當我們把rdb的文件改壞了,會發生什么

手動的把rdb的文件改壞,然后一定是通過kill進程方式,重新啟動redis服務器.

如果是通過service redis-server restart重啟,就會在服務器退出的時候,重新生成rdb快照,就把剛才改壞掉的文件替換掉了,所以要使用kill的方式.

由于rdb文件時二進制的,直接把改壞掉的rdb文件交給redis服務器去使用,得到的結果是不可預期的.

如果改的地方正好是文件末尾,對前面的內容沒有影響,可能redis再次啟動還是可以恢復正常的數據的.

對于rdb文件損壞,可能redis服務器啟動得到的數據正確性可能有問題,也可能redis服務器直接就啟動失敗了.

redis也提供了rdb文件的檢查工具,可以先通過檢查工具,檢查一下rdb的文件格式是否是符合要求的.


AOF

當開啟aof的時候,rdb就不生效了,reids服務器啟動的時候就不再讀取rdb文件的內容了.

會把用戶的每個操作都記錄到文件中.當redis重新啟動的時候,就會讀取這個aof文件中的內容,用來恢復數據.

aof默認一般是關閉狀態,修改配置文件,來開啟aof功能.

修改為yes開啟.

aof文件所在的位置和rdb文件在同一目錄下.(/var/lib/redis)

aof是一個文本文件,每次進行的操作都會記錄到文本文件中,通過一些特殊符號作為分隔符,對命令的細節做出區分.

引入aof之后,既要寫內存又要寫硬盤,redis是不是就變慢了?

redis是一個單線程的服務器,速度很快(快就快在直接操作內存).引入aof之后,實際上對于redis來說,是沒有影響的.并沒有影響redis處理請求的速度.原因有兩點:

1.aof機制并非是直接讓工作線程將數據寫入硬盤,而是先寫入一個內存中的緩沖區,當緩沖區的數據積累到一定量之后,在統一寫入內存.引入緩沖區之后,就大大降低了寫硬盤的次數.寫硬盤的時候,寫入硬盤數據的多少,對于性能的影響不是很大,關鍵是寫硬盤的次數多了,影響就比較大了.

2.硬盤上讀寫數據,順序讀寫的速度是比較快的,隨機訪問速度是比較慢的.aof是每次把新的操作寫入到原有的文件的末尾,屬于是順序寫入.


如果把數據寫入到緩沖區里,本質還是在內存中,如果這個時候,進程突然崩潰或者主機掉電,緩沖區中的數據還沒來得及寫入到硬盤中,那么這一部分數據就丟失了.

所以,redis給出了一些選項,來取舍刷新頻率和性能.

刷新頻率越高,那么對性能的影響就越大,但是數據的可靠性就越高.

刷新頻率越低,性能影響的越小,但是數據的可靠性就越低.


aof重寫機制

當aof文件持續增長,體積就會越來越大,會影響到redis下次啟動時的啟動時間.

為了解決這個問題,就出現了重寫機制.

重寫機制是因為在zof文件中,有一些內容是冗余的,比如對一個key修改了多次,但是我們在下次啟動的時候,只是關注這個key的最終結果的,至于它是修改了幾次我們是不關注的,比如刪除一個key,或者set了多個key我們可以用mset命令.

重寫其實就是對aof文件進行整理操作,這個整理能夠提出其中的冗余操作,并且合并一些操作,達到給aof文件瘦身的效果.

AOF?重寫過程可以?動觸發和?動觸發:
???動觸發:調??bgrewriteaof?命令。
???動觸發:根據?auto-aof-rewrite-min-size?和?auto-aof-rewrite-percentage?參數確定?動觸發時
機。
auto-aof-rewrite-min-size:表?觸發重寫時?AOF?的最??件??,默認為?64MB。
auto-aof-rewrite-percentage:代表當前?AOF?占???相?較上次重寫時增加的?例.


aof重寫流程

父進程通過fork操作創建出子進程.

父進程仍然負責接收請求,子進程負責針對aof文件重寫.在重寫的時候,不關心aof文件中原來的內容,只是關心內存中最終的數據狀態.

子進程只需要把內存中當前的數據,獲取出來,以aof的格式,寫入到一個新的aof文件中.(內存中的數據狀態,就已經相當于是aof文件結果整理后的模樣了).

子進程寫新的aof文件的同時,父進程仍然在不停的接收客戶端的請求,父進程還是會把這些請求產生的aof數據先寫入到緩沖區,在刷新到原有的aof文件中.

在創建子進程的瞬間,子進程就繼承了當前父進程的內存狀態.因此,子進程里的內存數據是父進程fork之前的狀態,fork之后,新來的請求對內存造成的影響,是子進程感知不到的.

所以,此時父進程又準備了一個aof_rewrite_buf緩沖區,專門用來存放fork之后收到的數據.當子進程把aof數據寫完之后,會通過信號通知父進程,父進程在把aof_rewrite_buf中的內容也寫入到新的aof文件里.

此時就可以用新的aof文件代替舊的文件了.


如果在執行bgrewriteaof的時候,當前reids已經在進行aof重寫了,此時就不會再次執行aof重寫了,會直接返回.

如果,在執行bgrewriteaof的時候,當前redis正在生成rdb文件的快照,那么aof操作就會等待,等到rdb快照生成完畢之后,在進行執行aof操作.

rdb對于fork之后的數據,就直接置之不理了.aof則對于fork之后的數據,采取了aof_rewrite_buf緩沖區的方式來處理.這也很符合它們的設計理念.rdb只是用來定期備份(定期備份就難以和最新的數據保持一致),aof則是實時備份.

父進程fork完畢之后,就已經讓子進程寫新的aof文件了,并且一段時間過后,子進程很快的完成了工作,新的文件代替舊的文件.那么,父進程還有必要繼續寫這個即將被替換的舊的文件嗎?

是有必要的.考慮到極端情況,假設在重寫過程中,重寫到一半,服務器崩潰了,子進程內存的數據就丟失了,而新的aof文件內容還不完整,所以如果父進程不堅持寫舊的aof文件,在這種情況下,reids重啟就無法保證數據的完整性了.


混合持久化

aof本來是按照文本的方式來寫入文件的,但是文本的方式寫文件,后續加載的成本是比較高的.

此時redis就引入了混合持久化的方式,結合rdb和aof的特點.

按照aof的方式,每一個請求或者操作都會記錄到文件中.

在觸發aof重寫之后,就會把當前的內存狀態按照rdb的二進制格式寫入到新的aof文件,后續再進行的操作,仍然是按照aof文本的方式追加到aof文件后面.

yes表示開啟混合持久化.


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/160101.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/160101.shtml
英文地址,請注明出處:http://en.pswp.cn/news/160101.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

動態跳過測試用例

動態跳過測試用例 說明 我們可以通過指定環境變量來動態判斷是否執行指定的測試用例設置環境變量有很多種方法,例如命令行方式,格式:--env keyval1,key2val2 ,若需要指定多個環境變量則需要逗號來隔開,而不是空格 t…

Live800:企業提升客戶互動體驗,有哪些關鍵因素?

如今,隨著信息時代的不斷發展,企業已經不再是單向的商業機構,他們需要與客戶進行及時的溝通與反饋,從而更好地提升客戶互動體驗,達到營銷和用戶體驗的雙贏局面。那么,企業如何提升客戶互動體驗呢&#xff1…

設計模式——RBAC 模型詳解

1.什么是 RBAC 呢? RBAC 即基于角色的權限訪問控制(Role-Based Access Control)。這是一種通過角色關聯權限,角色同時又關聯用戶的授權方式。 簡單地說:一個用戶可以擁有若干角色,每一個角色又可以被分配…

Mysql 中如何導出數據?

文章目錄 前言MySQL 導出數據使用 SELECT ... INTO OUTFILE 語句導出數據SELECT ... INTO OUTFILE 語句有以下屬性:導出表作為原始數據導出SQL格式的數據將數據表及數據庫拷貝至其他主機 后言 前言 hello world歡迎來到前端的新世界 😜當前文章系列專欄:…

Linux程序之可變參數選項那些事!

一、linux應用程序如何接收參數? 1. argc、argv Linux應用程序執行時,我們往往通過命令行帶入參數給程序,比如 ls /dev/ -l 其中參數 /dev/ 、-l都是作為參數傳遞給命令 ls 應用程序又是如何接收這些參數的? 通常應用程序都…

Raspberry Pi 5 新一代單板計算機:樹莓派5代 (介紹、入門、解疑)

樹莓派5代正式發布后,硬件和性能的全面升級讓眾多開發者們都想入手感受一波,外觀上Raspberry Pi 5 與前代產品非常相似,不過,在保留信用卡大小的整體尺寸的同時,也更新了一些設計元素,以適應新芯片組的功能…

python實現調和反距離空間插值法AIDW

1 簡介 AIDW 主要是針對 IDW 的缺點進行了改進,考慮了樣本點與預測點的位置,即方向和距離,具體見下圖: 2 改進 IDW 公式: 從IDW算法可看出,插值點的估算值僅與插值樣本距插值點的遠近相關,并未…

貝葉斯AB測試

AB測試是用來評估變更效果的有效方法,但很多時候會運行大量AB測試,如果能夠在測試中復用之前測試的結果,將有效提升AB測試的效率和有效性。原文: Bayesian AB Testing[1] 隨機實驗,又稱AB測試,是行業中評估因果效應的既…

自定義類型:結構體

1.結構體類型的聲明 1.1結構體的概念 結構是?些值的集合,這些值稱為成員變量。結構的每個成員可以是不同類型的變量。 1.2 結構的聲明 struct tag {member-list; }variable-list; 例如描述?個學?: struct Stu {char name[20];//名字int age;//年…

【Mysql】[Err] 1293 - Incorrect table definition;

基本情況 SQL文件描述 /* Navicat MySQL Data TransferSource Server : cm4生產-200 Source Server Version : 50725 Source Host : 192.168.1.200:3306 Source Database : db_wmsTarget Server Type : MYSQL Target Server Version : 50725 File…

vxe編輯保存表格

業務需求: 1、需要點擊編輯時,全部表格顯示編輯框,點擊保存,全部保存。 2、因為位置問題,產品經理把24小時分成了兩行,開發就得分兩個表格。列標題是寫死的,文字偏移也是寫死的,其他…

服務器主機安全的重要性及防護策略

在數字化時代,服務器主機安全是任何組織都必須高度重視的問題。無論是大型企業還是小型企業,無論是政府機構還是個人用戶,都需要確保其服務器主機的安全,以防止數據泄露、網絡攻擊和系統癱瘓等嚴重后果。 一、服務器主機安全的重…

__int128類型movaps指令crash

結論 在使用__int128時,如果__int128類型的內存起始地址不是按16字節對齊的話,有些匯編指令會拋出SIGSEGV使程序crash。 malloc在64位系統中申請的內存地址,是按16字節對齊的,但一般使用時經常會申請一塊內存自己切割使用&#…

Qt的一個無邊界窗口公共類

頭文件&#xff1a; #pragma once #include <QWidget>class CFrameLessWidgetBase :public QWidget { public:CFrameLessWidgetBase(QWidget* p nullptr);~CFrameLessWidgetBase() {}protected:bool nativeEvent(const QByteArray& eventType, void* message, long…

static和extern

1.extern extern 是?來聲明外部符號的&#xff0c;如果?個全局的符號在A?件中定義的&#xff0c;在B?件中想使?&#xff0c;就可以使? extern 進?聲明&#xff0c;然后使?。 即在一個源文件中想要使用另一個源文件&#xff0c;即可通過這個extern來聲明使用。 2.st…

未來制造業的新引擎:工業機器人控制解決方案

制造業正經歷著一場革命性的變革 在這個變革的浪潮中&#xff0c;工業機器人成為推動制造業高效生產的關鍵力量。然而&#xff0c;要發揮機器人的最大潛力&#xff0c;一個強大而智能的控制系統是必不可少的。在這個領域&#xff0c;新一代的工業機器人控制解決方案正嶄露頭角&…

學習MySQL先有全局觀,細說其發展歷程及特點

學習MySQL先有全局觀&#xff0c;細說其發展歷程及特點 一、枝繁葉茂的MySQL家族1. 發展歷程2. 分支版本 二、特點分析1. 常用數據庫2. 選型角度及場景 三、三大組成部分四、總結 相信很多同學在接觸編程之初&#xff0c;就接觸過數據庫&#xff0c;而對于其中關系型數據庫中的…

這樣寫postman實現參數化,阿里p8都直呼牛逼

什么時候會用到參數化 比如&#xff1a;一個模塊要用多組不同數據進行測試 驗證業務的正確性 Login模塊&#xff1a;正確的用戶名&#xff0c;密碼 成功&#xff1b;錯誤的用戶名&#xff0c;正確的密碼 失敗 postman實現參數化 在實際的接口測試中&#xff0c;部分參數…

你的關聯申請已發起,請等待企業微信的管理員確認你的申請

微信支付對接時&#xff0c;需要申請AppID,具體在下面的位置&#xff1a; 關聯AppID&#xff0c;發起申請時&#xff0c;會提示這么一句話&#xff1a; 此時需要登錄企業微信網頁版&#xff0c;使用注冊人的企業微信掃碼登錄進去&#xff0c;然后按照下面的步驟操作即可。 點擊…

iEnglish全國ETP大賽:教育游戲助力英語習得

“seesaw,abacus,sword,feather,frog,lion,mouse……”11月18日,經過3局的激烈較量,“以過客之名隊”的胡玲、黃長翔、林家慷率先晉級“玩轉英語,用iEnglish”第三屆全國ETP大賽的16強,在過去的周末中,還有TIK徘徊者隊、不負昭華隊、溫柔殺戮者隊先后晉級。據悉,根據活動規則,在…