溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何實現(xiàn)Redis集群擴縮容

發(fā)布時間:2021-10-19 16:30:25 來源:億速云 閱讀:174 作者:iii 欄目:開發(fā)技術

這篇文章主要講解了“如何實現(xiàn)Redis集群擴縮容”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何實現(xiàn)Redis集群擴縮容”吧!

 一、背景

攜程Redis集群規(guī)模和數(shù)據(jù)規(guī)模在過去幾年里快速增長,我們通過容器化解決了Redis集群快速部署的問題,并根據(jù)實際業(yè)務進行的一系列嘗試,比如二次調度、自動化漂移等,在內(nèi)存超分的情況下保證了宿主機的可靠性。

擴縮容方面,我們主要通過垂直擴縮容的方式解決Redis集群容量的問題,但隨著集群規(guī)模擴大,這種方式逐漸遇到了瓶頸。一方面,單個Redis實例過大,會帶來較大的運維風險和困難;另一方面,宿主機容量有上限,不能無止境的擴容。考慮到運維便利性和資源利用率的平衡,我們希望單個Redis實例的上限為15GB。

但實際操作中卻很難做到:某些業(yè)務發(fā)展很快,經(jīng)常性需要給Redis進行擴容,導致單個實例大小遠超15GB;一些業(yè)務萎縮,實際使用量遠低于初始申請的量,造成資源的浪費。

如何有效控制Redis實例大小呢?接下來本文將帶著這個問題,逐步講解攜程Redis治理和擴縮容方面的演進歷程。

二、Redis水平擴分拆

在攜程開始使用Redis很長一段時間里,一直只有垂直擴縮容,原因有兩點:

第一,一開始業(yè)務規(guī)模比較小,垂直擴縮容可以滿足需求。垂直擴縮容對于Redis來說只是Maxmemory的配置更改,對業(yè)務透明。

第二,水平拆分/擴縮容的實現(xiàn)難度和成本較高。

之前文章《攜程Redis治理演進之路》中已經(jīng)提到,攜程訪問所有的Redis集群使用的是自主研發(fā)的CRedis,而部署在應用端的CRedis通過一致性hash來訪問實際承載數(shù)據(jù)的Redis實例。但一致性hash是無法支持直接水平擴縮容的。因為無論增加一個節(jié)點或者刪除一個節(jié)點,都會導致整個hash環(huán)的調整。

如何實現(xiàn)Redis集群擴縮容

圖1

如圖所示,假設原始有4個分片(圖1)。當添加一個節(jié)點后,它會導致某一部分的key本來是寫到nodeC上而現(xiàn)在會被寫到nodeE上,也就是無法命中之前的節(jié)點。從客戶端的角度來看,key就像是丟失了。而變動的節(jié)點越多,key丟失的也越多,假設某個集群從10分片直接添加到20分片,它直接會導致50%的key丟失。刪除一個節(jié)點同理,就不再贅述。

因此盡管一致性hash是個比較簡單優(yōu)秀的集群方案,但無法直接水平擴容一直困擾著運維和架構團隊。為此,CRedis團隊在2019年提出了水平拆分的方案。

CRedis水平分拆的思路比較樸素,因為在一致性hash同一個水平位置增加節(jié)點會導致數(shù)據(jù)丟失,那么不改變原來層次節(jié)點的hash規(guī)則,以某個節(jié)點為hash的起點,再來進行一次一致性hash,演變成樹的結構(圖2)。

如何實現(xiàn)Redis集群擴縮容

圖2

如上圖所示,將樹形結構從一層拓展成二層,如果繼續(xù)拆分新的葉子Group,則可以將樹形結構拓展到三層,拆分方案可以支持到十層。葉子 Group是物理分片,直接對應的 Redis 實例,分支 Group 是虛擬分片,當Hash 命中到分支 Group 后,并沒有找不到對應的Redis實例,需要再繼續(xù)向下尋找,直到找到葉子 Group 為止。

如何實現(xiàn)Redis集群擴縮容

圖3

CRedis水平分拆上線后,DBA將現(xiàn)存的絕大部分超過15G的實例都拆分成更小的實例,在一段時間內(nèi)緩解了大內(nèi)存實例的運維治理壓力。但隨著Redis規(guī)模的快速增長,不斷有大的實例集群出現(xiàn),此外CRedis水平分拆的缺點也逐漸暴露出來:

  •  持續(xù)的周期很長,對多個 Group 進行拆分的話,每個Group的數(shù)據(jù)需要同時復制幾份同樣的實例。比如60G的某個實例(圖3),如果想拆到5G一個,那么下級的Group必須有12個,而拆分要先將該實例的數(shù)據(jù)先同步為12個60G的實例,再根據(jù)key的命中規(guī)則清理該12個60G的實例中不會命中的key,最終演變成12個5G的實例。一般60G的group實例拆分需要3個小時-6個小時,如果一個集群的分片非常多,加上觀察對業(yè)務影響的時間,可能要持續(xù)上幾天或一兩周,并且只能是有人值守的串行操作。

  •  拆分過程中需要2次遷移,如上面所說的,拆分中中間態(tài)實例對于內(nèi)存的要求是非常大的,拆分完成后對內(nèi)存的需求會急劇下降,因此每次拆分都涉及到2次遷移,盡管遷移不會影響業(yè)務,但對于執(zhí)行操作拆分的運維人員來說,心智負擔比較大,而且一不小心也會導致線上事故。

  •  拆分后無法還原回去,也就是說假設業(yè)務分拆后收縮,對Redis的需求變小了,但它實際拆分后的分片還在那邊,所申請的空間還并沒有釋放掉,客觀上浪費了資源,降低了Redis總體的利用率。

  •  只支持擴容,不支持縮容,這點上面也提到了,除了一些集群過大需要分拆外,還有一些申請遠超需求的實例需要縮容,而水平分拆對于這點無能為力。

  •  拆分一次,就多一次的性能損耗,因為需要多計算一次hash,雖然耗時不大,但是對于性能敏感的業(yè)務還是有影響。

由此可見,水平分拆的方案雖然解決了實例過大的問題,但不能縮容的弊端也逐漸凸現(xiàn)了出來。尤其是在今年因疫情影響需要降本增效的背景下,一方面資源比充足,一方面宿主機上跑的都是無法縮容的實例。那么是否有更好的解決方案呢?答案是有的。

三、Redis水平擴縮容

1、設計思路

如何實現(xiàn)Redis集群擴縮容

圖4

既然縮分片比較困難,我們首先想到的是業(yè)務雙寫集群的方法,也就是業(yè)務同時雙寫2個新老集群,新老集群的分片數(shù)是不一樣的,并且大小配置也不一樣。比如之前申請4個分片現(xiàn)在發(fā)現(xiàn)資源過剩,讓業(yè)務創(chuàng)新申請一個新的2個分片的集群,由業(yè)務來控制灰度寫哪個集群(圖4)。最終會遷移到新集群上,而新集群大小是滿足當前業(yè)務需求的,從而達到了縮容的目的。

雙寫集群的方案雖然解決我們部分的問題,但對于業(yè)務的侵入比較深,此外由于雙寫集群引入了業(yè)務配合觀察的時間,整體流程也比較長。所以,我們需要尋找更好的解決方案。

既然業(yè)務雙寫集群可以達到要求,基礎設施如果代替業(yè)務做完這部分豈不是更好?借鑒業(yè)務雙寫集群的思路和云原生的不可變基礎設施的理念,我們首先想到的是通過新集群替換老集群而不是原地修改集群;另外,為了在公有云上節(jié)省Redis成本,我們積累了kvrocks的實踐經(jīng)驗,兩者相結合,設計了一種高效的水平擴縮容的方案。

本方案的核心是引入了一個基于kvrocks改造的中間態(tài)binlogserver,它既是一個老集群的Slave節(jié)點,又充當了新集群的客戶端。一方面,它會從Redis Master復制全量和增量數(shù)據(jù);另一方面,它又充當客戶端的角色,將復制來的數(shù)據(jù)按照新集群的一致性HASH規(guī)則寫往新的集群。大致的步驟如下,具體的步驟流程可以參考下面的圖所示(圖5)。

  •  根據(jù)當前V1集群的分片啟動對應個數(shù)binlogserver,并獲取V2集群的一致性HASH規(guī)則和group。

  •  每個binlogserver成為V1集群單個分片中Master的Slave,執(zhí)行salveof后保存V1中Master傳過來的RDB文件并解析,對于每個RDB文件,解析還原成Redis命令,并按CRedis的一致性hash規(guī)則寫入到V2中,對于后續(xù)V1集群傳播過來的命令,同樣同步到V2中。

  •  當這個過程都完成并且binlog追的差不多的時候,為了數(shù)據(jù)一致性,可以停止V1的寫(客戶端報錯)后由CRedis推送V2的配置或直接推送V2的配置(客戶端不報錯但數(shù)據(jù)可能會丟或不一致),APP端將會順序切換到 V2上來;此過程對用戶完全透明,應用端無需做任何操作。

如何實現(xiàn)Redis集群擴縮容

圖5

通過Redis的水平擴縮容方案,我們解決了之前的幾個痛點問題:

  •  持續(xù)時間大大縮短,基本上跟V1集群最大實例的大小正相關,因為是并發(fā)執(zhí)行,跟集群分片數(shù)無關。根據(jù)實際的運維數(shù)據(jù)來看,集群單個實例為20G,集群擴縮容在10分鐘之內(nèi)完成,而低于10G的,5分鐘即可完成,大大縮短了擴縮容的周期,并且業(yè)務在毫無感知的情況下即可完成擴縮容。由于可以做到秒級切換集群,即使擴縮容后對業(yè)務有影響也可以快速回退,因為回退也只是更改了集群的路由指向。

  •  擴縮容過程只需要1次切換集群指向,0次遷移,沒有中間態(tài),也無需通過大內(nèi)存宿主機來實現(xiàn)分拆。

  •  對于擴容的集群,很方便再來一次縮容還原回去,縮容同理。對于那些已經(jīng)水平拆分過的集群,也可以通過這種方式還原回去。

  •  既可以擴容也可以縮容,甚至還可以不擴容也不縮容按集群來遷移,比如《攜程Cilium+BGP云原生網(wǎng)絡實踐》一文中提到的云原生網(wǎng)絡安全控制試點項目。由于原來Redis集群下面的實例可能同時部署在openstack網(wǎng)絡和cilium網(wǎng)絡,但云原生安全只能控制cilium網(wǎng)絡下的實例,這種情況下就需要遷移Redis實例。如果按之前的運維方式,要按分片來一組組遷移,整個工程可能持續(xù)較長時間,并且耗費較多人力,而水平擴縮容可以將一個集群一次性快速遷移到cilium網(wǎng)絡,省時省力。

  •  擴縮容后無性能損耗。

2、運維數(shù)據(jù)

水平擴縮容方案上線4個月來,已經(jīng)成功完成了200多次的擴容和縮容。今年某個業(yè)務突然請求量暴增十幾倍,相關集群經(jīng)歷了多次擴容,每次擴容大多在10分鐘內(nèi)完成,有效地支撐了業(yè)務發(fā)展。

另一方面,針對申請分片非常多而大但實際使用量非常小的集群,我們也借助水平擴縮容的能力快速地縮小了分片數(shù)和申請量。通過這些縮容,有效地提升了整體的資源利用率。

3、一些坑

(1)單個key過大導致key被驅逐

在實際水平擴縮容過程中,我們發(fā)現(xiàn)有些集群,單個實例中可能會有巨大的key(大于3G),由于V2集群的大小是根據(jù)V1大小實時算出來的平均值,一旦V1中某個實例過大,可能會導致寫到V2中的某個實例大小大于預期的平均值,從而引起某些key被驅逐。因此,針對這種情況:

  •  加強大key的檢測邏輯,對于超過512M的key會有告警郵件告知所有者。

  •  V2中所有實例的maxmemory在分拆之前不設置限制,統(tǒng)一都調到60G,防止V2中key分配不均導致key驅逐。

  •  水平擴縮容后,在V1和V2切換過程中,檢測V2中的實例是否發(fā)生過驅逐,如果有則默認分拆失敗,不進行切換。

(2)mget擴容后會導致性能下降   

對于極個別的場景,我們還發(fā)現(xiàn),mget請求耗時會有明顯上升,主要原因還是在于,擴容之前mget需要訪問的實例數(shù)少,而分拆后訪問的實例數(shù)變多。一般這種情況,我們建議業(yè)務控制單次mget的key的數(shù)量,或者將string類型改造為hash類型,通過hmget來訪問數(shù)據(jù),保證每次只會訪問到一個實例,這樣擴容后其吞吐量是隨著分片數(shù)量線性增加,而延遲不會有增加。

四、總結和未來規(guī)劃

1、Xpipe支持

目前水平擴縮容和漂移以及二次調度等一系列治理工具和策略組成了一個比較完善的閉環(huán),有效地支撐了生產(chǎn)幾千臺宿主機,幾萬帶超分能力Redis實例的運維治理。

但目前受制于xpipe的架構,對于接入了xpipe的集群,必須先擴縮容后再將DR端的xpipe人工補齊,自動化程度還不足,而補齊xpipe的時間比較長,比如之前是就近讀本機房的Redis集群的APP,在擴縮容后可能一段時間里只能跨機房讀取,必然導致延遲上升。而這種延遲上升又會影響我們對于水平擴縮容邏輯是否正確,是否需要回退的判斷。因此后續(xù)我們會針對xpipe集群,也做到和普通集群一樣,也就是V2集群在擴縮容寫流量之前就是帶DR架構的集群。

2、持久化KV存儲的支持

除了Redis本身受業(yè)務歡迎使用廣泛外,我們還發(fā)現(xiàn)有些業(yè)務需要相比Redis 更可靠的KV存儲方式,比如數(shù)據(jù)保存在磁盤上而不是保存在內(nèi)存里,再比如業(yè)務需要支持一些增減庫存邏輯,對某個key的獨占訪問,實現(xiàn)語義近似INCRBY操作,但實際上是對于一些字符串進行merge操作。此外數(shù)據(jù)可靠性要求更高,master宕機不能丟失數(shù)據(jù)等。。

感謝各位的閱讀,以上就是“如何實現(xiàn)Redis集群擴縮容”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對如何實現(xiàn)Redis集群擴縮容這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI