1. 程式人生 > >【原創】你的Redis怎麼持久化的

【原創】你的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傳輸是加密的。

總結

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