面試官:今天要不來聊聊Redis的持久化機制吧?
候選者:嗯,沒問題的
候選者:在上一次面試已經說過了Redis是基于記憶體的
候選者:假設我們不做任何操作,隻要Redis伺服器重新開機(或者中途故障挂掉了),那記憶體的資料就會沒掉
候選者:我們作為使用方,肯定是不想Redis裡頭的資料會丢掉
候選者:是以Redis提供了持久化機制給我們用,分别是RDB和AOF
候選者:RDB指的就是:根據我們自己配置的時間或者手動去執行BGSAVE或SAVE指令,Redis就會去生成RDB檔案
候選者:這個RDB檔案實際上就是一個經過壓縮的二進制檔案,Redis可以通過這個檔案在啟動的時候來還原我們的資料
候選者:而AOF則是把Redis伺服器接收到的所有寫指令都記錄到日志中
候選者:Redis重跑一遍這個記錄下的日志檔案,就相當于還原了資料
面試官:那我就想問了,你上次不是說Redis是單線程嗎
面試官:那比如你說的RDB,它會執行SAVE或BESAVE指令,生成檔案
面試官:那不是非常耗時的嗎,那如果隻有一個線程處理,那其他的請求不就得等了?
候選者:嗯,沒錯,Redis是單線程的。
候選者:以RDB持久化的過程為例,假設我們在配置上是定時去執行RDB存儲
候選者:Redis有自己的一套事件處理機制,主要處理檔案事件(指令請求和應答等等)和時間事件(RDB定時持久化、清理過期的Key等的)
候選者:是以,定時的RDB實際上就是一個時間事件
候選者:線程不停地輪詢就緒的事件,發現RDB的事件可執行時,則調用BGSAVE指令
候選者:而BGSAVE指令實際上會fork出一個子程序來進行完成持久化(生成RDB檔案)
候選者:在fork的過程中,父程序(主線程)肯定是阻塞的。
候選者:但fork完之後,是fork出來的子程序去完成持久化。處理請求的程序該幹嘛的就幹嘛
候選者:是以說啊,Redis是單線程,了解是沒錯的,但沒說人家不能fork程序來處理事情呀,對不對
候選者:還有就是,其實Redis在較新的版本中,有些地方都使用了多線程來進行處理
候選者:比如說,一些删除的操作(UNLINK、FLUSHALL ASYNC等等)還有Redis 6.x 之後對網絡資料的解析都用了多線程處理了。
候選者:隻不過,核心的處理指令請求和響應還是單線程。
面試官:那AOF呢?AOF不是也要寫檔案嗎?難道也是fork 了個子程序去做的?
候選者:emm,不是的。AOF是在指令執行完之後,把指令寫在buffer緩沖區的(直接追加寫)
候選者:那想要持久化,肯定得存盤嘛。Redis提供了幾種政策供我們選擇什麼時候把緩沖區的資料寫到磁盤
候選者:我記得有:每秒一次/每條指令都執行/從不存盤;一般我們會選每秒一次
候選者:Redis會啟一個線程去刷盤,也不是用主線程去幹的
面試官:那如果把執行過的指令都存起來
面試官:等啟動的時候是可以再把這些寫指令再執行一遍,達到恢複資料的效果
面試官:這樣會有什麼樣的問題嗎?
候選者:嗯,問題就是,如果這些寫入磁盤的「指令集合」不做任何處理,那該「指令集合」就會一直膨脹
候選者:其實就是該檔案會變得非常大
候選者:Redis當然也考慮了這一點,它會fork個子程序會對「原始」指令集合進行重寫
候選者:說白了就是會壓縮,壓縮完了之後隻要替換原始檔案就好了
面試官:那我又想問了,既然它是fork一個程序來對AOF進行重寫的
面試官:前面你也提到了再fork時,主程序是阻塞的,但fork後,主程序會繼續接收指令
面試官:你是說重寫完(壓縮)會進行檔案覆寫
面試官:那這樣不會丢資料嗎?畢竟主程序在fork之後是一直會接收指令的
候選者:哦,我明白你的意思了。
候選者:其實做法很簡單啊,在fork子程序之後,把新接收到指令再寫到另一個緩沖區不就好了嗎
面試官:可以
面試官:那AOF和RDB用哪一個呢?
候選者:主要是看業務場景吧,我們這邊是基于Redis自研了一套key-value存儲
面試官:自研的?你們的Redis架構是什麼?
候選者:别别别,當我沒說。就是開源的,開源的。我們回到RDB和AOF上吧。
候選者:在新增namespace(執行個體) 的時候也會讓你選擇對應的使用場景
候選者:就是會讓你通過不同的應用場景進行配置選擇
候選者:比如說,業務上是允許重新開機時部分資料丢失的,那RDB就夠用了(:
候選者:RDB在啟動的時候恢複資料會比AOF快很多
候選者:在Redis4.0以後也支援了AOF和RDB混合
候選者:在官網是不建議僅僅隻使用AOF的,如果對資料丢失容忍度是有要求的,建議是開啟AOF+RDB一起用
候選者:總的來說,不同的場景使用不同的持久化政策吧
面試官:了解
面試官:順便我想問下,假如Redis的記憶體滿了,但業務還在寫資料,會怎麼樣?
候選者:嗯,這個問題我也遇到過
候選者:一般來說,我們會淘汰那些「不活躍」的資料,然後把新的資料寫進去
候選者:更多情況下,還是做好對應的監控和容量的考量吧
候選者:等容量達到門檻值的時候,及時發現和擴容
面試官:你這懂得有點多啊
本文總結:
Redis持久化機制:RDB和AOF
RDB持久化:定時任務,BGSAVE指令 fork一個子程序生成RDB檔案(二進制)
AOF持久化:根據配置将寫指令存儲至日志檔案中,順序寫&&異步刷盤(子線程),重寫AOF檔案也是需要 fork 子程序。Redis4.0之後支援混合持久化,用什麼持久化機制看業務場景
【對線面試官-移動端】系列 一周兩篇持續更新中!
【對線面試官-電腦端】系列 一周兩篇持續更新中!