網易視頻云是網易傾力打造的1款基于云計算的散布式多媒體處理集群和專業音視頻技術,提供穩定流暢、低時延、高并發的視頻直播、錄制、存儲、轉碼及點播等音視頻的PAAS服務,在線教育、遠程醫療、文娛秀場、在線金融等各行業及企業用戶只需經過簡單的開發便可打造在線音視頻平臺。現在,網易視頻云的技術專家給大家分享1則技術文:網易視頻云:支持redis節點高可用的twemproxy。
原生twemporxy
twemproxy支持1個proxy實例同時期理多個散布式集群(server pools),每一個集群使用不同的網絡端口實現數據流的隔離,下圖中port1利用于cluster1代理,port2利用于cluster2代理:
今天要介紹的是twemproxy對redis節點高可用的支持,拿上圖的其中1個散布式集群進行示例,邏輯結構以下:
客戶端client流入的要求,在proxy上進行路由分片,然后轉發到后真個redis節點上存儲或讀取。事實上,大家已注意到后真個redis節點只有1個點,在出現異常情況下,是很容易掉線的。按twemproxy的設計,它可以自動辨認失效節點并將其剔除,同時落在原來節點上的要求會分攤到其余的節點上。這是散布式緩存系統的1種通用做法,但需要忍耐這個失效節點上的數據丟失,這類情況是不是可以接受?
在業內,redis雖然被定位為緩存系統,但事實上,不管哪一種業務場景(我們接觸過的)都不愿意接受節點掉線帶來的數據丟失,由于那樣對他們系統的影響實在太大了,更有甚者在壓力大的時候引發后端數據庫被擊穿的風險。所以,我們打算改造twemproxy,前后總共有幾個版本,下面分享給各位的是我們目前線上在跑的版本。
定制化改造
在上圖的基礎上,我們增加了與manager交互的模塊、增加了與sentinel(redis-sentinel)交互的模塊,修改了redis連接收理模塊,圖中3個紅色虛線框所示:
manager交互模塊
增加連接manager的客戶端交互模塊,用于發送心跳消息,從心跳應對包里獲得group名稱列表和sentinel列表(IP/PORT信息),即全部散布式集群的配置信息,其中心跳消息帶有版本信息,發送間隔可配置。
sentinel交互模塊
增加與sentinel客戶端交互模塊(IP/PORT信息來自于manager),發送group名稱給sentinel獲得redis主節點的IP/PORT信息,1個group對應1個主節點。取到所有主節點后,定閱主從切換頻道,獲得切換消息用于觸發proxy和主節點間的連接切換。這里需要解析sentinel的響應消息,會比較繁瑣1些。當proxy開始與sentinel節點的交互進程,需要啟動定時器,用以控制交互結果,當定時器超時交互未結束(或proxy未正常工作),proxy將主動切換到下1個sentinel節點,并啟動新的交互進程。斟酌到proxy與sentinel之間網絡連接的重要性(連接假死,proxy收不到主從切換消息,不能正常切換),增加了定時心跳機制,確保這條TCP鏈路的可用性。
redis連接收理模塊
本來redis節點的IP/PORT信息來自于靜態配置文件,是固定的,而改造以后這些信息是從sentinel節點獲得。為了確保獲得到的IP/PORT信息的準確性,需要向IP/PORT對應的節點驗證是不是是主節點的邏輯,只有返回確認是主節點,才認為是合法的。全部進程,按官方指點實現,不存在漏洞。
詳細消息流
為了清晰的描寫proxy的內部處理邏輯,制作了以下消息流圖:
綠色為業務通道,用于透傳業務層數據;
紫色為命令通道(紅線的細化),用于初始化和節點主從切換:
箭頭1:manager heartbeat req;
箭頭2:manager heartbeat rsp;
箭頭3:sentinel get-master-addr-by-name req;
箭頭4:sentinel get-master-addr-by-name rsp;
箭頭5:redis auth & role req;
箭頭6:redis auth & role rsp;
箭頭7:sentinel psubscribe +switch-master req;
箭頭8:sentinel psubscribe +switch-master rsp;
箭頭9:sentinel pmessage;
命令通道命令順序按數字1⑻進行,7/8是proxy與sentinel的心跳消息,9是主從切換消息;
高可用影響面分析
在sentinel節點切換的進程中,存在proxy正在對外提供業務服務的狀態,這時候候正在處理的數據將繼續處理,不會遭到影響,而新接入的客戶端連接將會被謝絕,已有的客戶端連接上的新的業務要求數據也會被謝絕。sentinel節點切換,對系統的影響是毫秒級別,前面的設計對業務系統來說會顯得比較友好、不那末粗魯;
而redis節點的主從切換對系統的影響,主要集中在proxy發現主節點異常到sentinel集群做出主從切換這個進程,這段時間內落在該節點上的業務都將失敗,而該時間段的長度主要依賴在sentinel節點上的down-after-milliseconds配置字段;
經驗總結
作為代理中間件,支持pipeline的能力有限,容易產生消息積存,致使客戶端大量超時,所以慎用pipeline功能;
高負荷下容易吃內存,struct msg和struct mbuf對象會被大量緩存在進程內(內存池化);
zero copy,對多個連續要求(TCP粘包)進行拆分,拷貝是沒法避免的,但是有優化空間。