引言
(本文改編自生活真實案例,如有類同,絕不是巧合!)
端午節,煙哥正在一邊愉快的學習....
突然,微信一陣抖動。原來是老劉呼喚煙哥!善良的煙哥本以為人家是要約我出去玩!然而,打開微信一看,出現下圖聊天記錄
於是本文的主題就這么展開了。由於我需要迅速讓老劉明白,這種問題的回答套路,所以我回答的時候,教她的是一種通用做法。
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傳輸是加密的。
總結
本文提出的是一種通用的持久化策略,主要目的是在面試的時候被問到,給出一個合理的回答,而不至於一臉懵逼。