Redis常見問題和解決辦法梳理

 

1、Redis主從複製讀寫分離問題redis

1)數據複製的延遲
讀寫分離時,master會異步的將數據複製到slave,若是這是slave發生阻塞,則會延遲master數據的寫命令,形成數據不一致的狀況。
解決方法:能夠對slave的偏移量值進行監控,若是發現某臺slave的偏移量有問題,則將數據讀取操做切換到master,但自己這個監控開銷比較高,因此關於這個問題,大部分的狀況是能夠直接使用而不去考慮的。
2)讀到過時的數據
redis在刪除過時key的時候有兩種策略, 第一種是懶惰型策略,即只有當redis操做這個key的時候,發現這個key過時,就會把這個key刪除。 第二種是按期採樣一些key進行刪除。
針對上面說的兩種過時策略,會有個問題,即若是過時key的數量很是多,而採樣速度根本比不上過時key的生成速度時會形成不少過時數據沒有刪除,但在redis裏master和slave達成一種協議,slave是不能處理數據的(即不能刪除數據)而客戶端沒有及時讀到到過時數據同步給master將key刪除,就會致使slave讀到過時的數據(這個問題已經在redis3.2版本中解決)。
 
2、Redis主從配置不一致
這個問題通常不多見,但若是有,就會發生不少詭異的問題,例如:
1)max memory配置不一致:這個會致使數據的丟失。
緣由:例如master配置4G,slave配置2G,這個時候主從複製能夠成功,但若是在進行某一次全量複製的時候,slave拿到master的RDB加載數據時發現自身的2G內存不夠用,這時就會觸發slave的maxmemory策略,將數據進行淘汰。更可怕的是,在高可用的集羣環境下,若是將這臺slave升級成master的時候,就會發現數據已經丟失了。
2)數據結構優化參數不一致(例如hash-max-ziplist-entries):這個就會致使內存不一致。
緣由:例如在master上對這個參數進行了優化,而在slave沒有配置,就會形成主從節點內存不一致的詭異問題。
 
3、規避全量複製
首先,redis複製有全量複製和部分複製兩種,而全量複製的開銷是很大的。那麼來看看,如何儘可能去規避全量複製。
1)第一次全量複製
當某一臺slave第一次去掛到master上時,是不可避免要進行一次全量複製的,那麼如何去想辦法下降開銷呢?
方案1:小主節點,例如把redis分紅2G一個節點,這樣一來會加速RDB的生成和同步,同時還能夠下降fork子進程的開銷(master會fork一個子進程來生成同步須要的RDB文件,而fork是要拷貝內存快的,若是主節點內存太大,fork的開銷就大)。
方案2:既然第一次不能夠避免,那能夠選在集羣低峯的時間(凌晨)進行slave的掛載。
2)節點RunID不匹配
例如主節點重啓(RunID發生變化),對於slave來講,它會保存以前master節點的RunID,若是它發現了此時master的RunID發生變化,那它會認爲這是master過來的數據多是不安全的,就會採起一次全量複製。
解決辦法:對於這類問題,只有是作一些故障轉移的手段,例如master發生故障宕掉,選舉一臺slave晉升爲master(哨兵或集羣)。
3)複製積壓緩衝區不足
在全量複製與部分複製那篇文章提到過,master生成RDB同步到slave,slave加載RDB這段時間裏,master的全部寫命令都會保存到一個複製緩衝隊列裏(若是主從直接網絡抖動,進行部分複製也是走這個邏輯),待slave加載完RDB後,拿offset的值到這個隊列裏判斷,若是在這個隊列中,則把這個隊列從offset到末尾所有同步過來,這個隊列的默認值爲1M。而若是發現offset不在這個隊列,就會產生全量複製。
解決辦法:增大複製緩衝區的配置 rel_backlog_size 默認1M,咱們能夠設置大一些,從而來加大offset的命中率。這個值,能夠假設,通常網絡故障時間是分鐘級別,那能夠根據當前的QPS來算一下每分鐘能夠寫入多少字節,再乘以可能發生故障的分鐘就能夠獲得咱們這個理想的值。
 
4、規避複製風暴
什麼是複製風暴?舉例:master重啓,其master下的全部slave檢測到RunID發生變化,致使全部從節點向主節點作全量複製。儘管redis對這個問題作了優化,即只生成一份RDB文件,但須要屢次傳輸,仍然開銷很大。
1)單主節點複製風暴:主節點重啓,多從節點全量複製
解決辦法:更換複製拓撲,以下圖:
a)將原來master與slave中間加一個或多個slave,再在slave上加若干個slave,這樣能夠分擔全部slave對master複製的壓力。(這種架構仍是有問題:讀寫分離的時候,slave1也發生了故障,怎麼去處理?)
b)若是隻是實現高可用,而不作讀寫分離,那當master宕機,直接晉升一臺slave便可。
2)單機器複製風暴:機器宕機後的大量全量複製 ,以下圖:
當machine-A這個機器宕機重啓,會致使該機器全部master下的全部slave同時產生複製。(災難)
解決:
a)主節點分散多機器(將master分散到不一樣機器上部署)
b)還有咱們能夠採用高可用手段(slave晉升master)就不會有相似問題了。

=============Redis常見性能問題和解決辦法=================shell

1)Master寫內存快照
save命令調度rdbSave函數,會阻塞主線程的工做,當快照比較大時對性能影響是很是大的,會間斷性暫停服務,因此Master最好不要寫內存快照。
2)Master AOF持久化
若是不重寫AOF文件,這個持久化方式對性能的影響是最小的,可是AOF文件會不斷增大,AOF文件過大會影響Master重啓的恢復速度。
3)Master調用BGREWRITEAOF
Master調用BGREWRITEAOF重寫AOF文件,AOF在重寫的時候會佔大量的CPU和內存資源,致使服務load太高,出現短暫服務暫停現象。
下面是個人一個實際項目的狀況,大概狀況是這樣的:一個Master,4個Slave,沒有Sharding機制,僅是讀寫分離,Master負責 寫入操做和AOF日誌備份,AOF文件大概5G,Slave負責讀操做,當Master調用BGREWRITEAOF時,Master和Slave負載會 忽然陡增,Master的寫入請求基本上都不響應了,持續了大概5分鐘,Slave的讀請求過也半沒法及時響應,Master和Slave的服務器負載圖 以下:
Master Server load:
Slave server load:

上面的狀況原本不會也不該該發生的,是由於之前Master的這個機器是Slave,在上面有一個shell定時任務在天天的上午10點調用 BGREWRITEAOF重寫AOF文件,後來因爲Master機器down了,就把備份的這個Slave切成Master了,可是這個定時任務忘記刪除 了,就致使了上面悲劇狀況的發生,緣由仍是找了幾天才找到的。緩存

將no-appendfsync-on-rewrite的配置設爲yes能夠緩解這個問題,設置爲yes表示rewrite期間對新寫操做不fsync,暫時存在內存中,等rewrite完成後再寫入。最好是不開啓Master的AOF備份功能。安全

4)Redis主從複製的性能問題
第一次Slave向Master同步的實現是:Slave向Master發出同步請求,Master先dump出rdb文件,而後將rdb文件全量 傳輸給slave,而後Master把緩存的命令轉發給Slave,初次同步完成。第二次以及之後的同步實現是:Master將變量的快照直接實時依次發 送給各個Slave。無論什麼緣由致使Slave和Master斷開重連都會重複以上過程。Redis的主從複製是創建在內存快照的持久化基礎上,只要有 Slave就必定會有內存快照發生。雖然Redis宣稱主從複製無阻塞,但因爲Redis使用單線程服務,若是Master快照文件比較大,那麼第一次全 量傳輸會耗費比較長時間,且文件傳輸過程當中Master可能沒法提供服務,也就是說服務會中斷,對於關鍵服務,這個後果也是很可怕的。
 
以上1.2.3.4根本問題的緣由都離不開系統IO瓶頸問題,也就是硬盤讀寫速度不夠快,主進程 fsync()/write() 操做被阻塞。
 
5)單點故障問題
因爲目前Redis的主從複製還不夠成熟,因此存在明顯的單點故障問題,這個目前只能本身作方案解決,如:主動複製,Proxy實現Slave對 Master的替換等,這個也是目前比較優先的任務之一。
 
簡單總結: -  Master最好不要作任何持久化工做,包括內存快照和AOF日誌文件,特別是不要啓用內存快照作持久化。 -  若是數據比較關鍵,某個Slave開啓AOF備份數據,策略爲每秒同步一次。 -  爲了主從複製的速度和鏈接的穩定性,Slave和Master最好在同一個局域網內。 -  儘可能避免在壓力較大的主庫上增長從庫 -  爲了Master的穩定性,主從複製不要用圖狀結構,用單向鏈表結構更穩定,即主從關係 爲:Master<–Slave1<–Slave2<–Slave3…….,這樣的結構也方便解決單點故障問題,實現Slave對 Master的替換,也即,若是Master掛了,能夠立馬啓用Slave1作Master,其餘不變。
相關文章
相關標籤/搜索