【原創】你的Redis怎麼持久化的

引言

(本文改編自生活真實案例,如有類同,絕不是巧合!)
端午節,煙哥正在一邊愉快的學習....
突然,微信一陣抖動。原來是老劉呼喚煙哥!善良的煙哥本以爲人家是要約我出去玩!然而,打開微信一看,出現下圖聊天記錄

於是本文的主題就這麼展開了。由於我需要迅速讓老劉明白,這種問題的回答套路,所以我回答的時候,教她的是一種通用做法。
ps:附《那些年用過的redis集羣架構(含面試解析)》的連接地址。
當然,必須的,我一定要先問一下老劉答了哪種redis集羣架構!老劉的回答是用了redis cluster集羣架構。
於是,我一聽心裏就有底,開始balabala....

正文

持久化套路

OK,一般我們在生產上採用的持久化策略爲

  • (1)master關閉持久化
  • (2)slave開RDB即可,必要的時候AOF和RDB都開啓

該策略能夠適應絕大部分場景,絕大部分集羣架構。
爲什麼是絕大部分場景?
因爲這套策略存在部分的數據丟失可能性。redis的主從複製是異步的,master執行完客戶端請求的命令後會立即返回結果給客戶端,然後異步的方式把命令同步給slave。因此master可能還未來得及將命令傳輸給slave,就宕機了,此時slave變爲master,數據就丟了。
幸運的是,絕大部分業務場景,都能容忍數據的部分丟失。假設,真的遇到緩存雪崩的情況,代碼中也有熔斷器來進行資源保護,不至於所有的請求都轉發到數據庫上,導致我們的服務崩潰!
ps:這裏的緩存雪崩是指同一時間來了一堆請求,請求的key在redis中不存在,導致請求全部轉發到數據庫上。
爲什麼是絕大部分集羣架構?
因爲在集羣中存在redis讀寫分離的情況,就不適合這套方案了。
幸運的是,由於採用redis讀寫分離架構,就必須要考慮主從同步的延遲性問題,徒增系統複雜度。目前業內採用redis讀寫分離架構的項目,真的太少了。

爲什麼這麼做

(1)master關閉持久化

原因很簡單,因爲無論哪種持久化方式都會影響redis的性能,哪一種持久化都會造成CPU卡頓,影響對客戶端請求的處理。爲了保證讀寫最佳性能,將master的持久化關閉!
RDB持久化
RDB持久化是將當前進程中的數據生成快照保存到硬盤(因此也稱作快照持久化),保存的文件後綴是rdb;當Redis重新啓動時,可以讀取快照文件恢復數據。
那麼RDB持久化的過程,相當於在執行bgsave命令。該命令執行過程如下圖所示

如圖所示,主線程需要調用系統函數fork(),構建出一個子進程進行持久化!很不幸的是,在構建子進程的過程中,父進程就會阻塞,無法響應客戶端的請求!
而且,在測試中發現,fork函數在虛擬機上較慢,真機上較快。考慮到現在都是部署在docker容器中,很少部署在真機上,爲了性能,master不建議打開RDB持久化!
AOF持久化
RDB持久化是將進程數據寫入文件,而AOF持久化(即Append Only File持久化),則是將Redis執行的每次寫命令記錄到單獨的日誌文件中。
隨着時間的流逝,你會發現這個AOF文件越來越大,於是redis有一套rewrite機制,來縮小AOF文件的體積。然而,在rewrite的過程中也是需要父進程來fork出一個子進程進行rewrite操作。至於fork函數的影響,上面提到過了。
還有一個就是刷盤策略fsync,這個值推薦是配everysec,也就是Redis會默認每隔一秒進行一次fsync調用,將緩衝區中的數據寫到磁盤。
然而,如果磁盤性能不穩定,fsync的調用時間超過1秒鐘。此時主線程進行AOF的時候會對比上次fsync成功的時間;如果距上次不到2s,主線程直接返回;如果超過2s,則主線程阻塞直到fsync同步完成。
因此AOF也是會影響redis的性能的。
ps:linux函數中,wrtie函數將數據寫入文件的時候,是將數據寫入操作系統的緩衝區,還並未刷入磁盤。而fsync函數,可以強制讓操作系統將緩衝區數據刷入磁盤。

綜上所述,我們爲了保證讀寫性能最大化,將master的持久化關閉。

(2)slave開RDB即可,必要的時候AOF和RDB都開啓

首先,我先說明一下,我不推薦單開AOF的原因是,基於AOF的數據恢復太慢。
你要想,我們已經做了主從複製,數據已經實現備份,爲什麼slave還需要開持久化?
因爲某一天可能因爲某某工程,把機房的電線挖斷了,就會導致master和slave機器同時關機。
那麼這個時候,我們需要迅速恢復集羣,而RDB文件文件小、恢復快,因此災難恢復常用RDB文件。

其次,官網也不推薦單開AOF,地址如下:
https://redis.io/topics/persistence
截圖如下

所以,如果實在對數據安全有一定要求,將AOF和RDB持久化都開啓。

另外,做好災難備份。利用linux的scp命令,定期將rdb文件拷貝到雲服務器上。
ps:scp是secure copy的簡寫,用於在Linux下進行遠程拷貝文件的命令,和它類似的命令有cp,不過cp只是在本機進行拷貝不能跨服務器,而且scp傳輸是加密的。

總結

本文提出的是一種通用的持久化策略,主要目的是在面試的時候被問到,給出一個合理的回答,而不至於一臉懵逼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章