這篇“redis集群實(shí)例分析”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Redis集群實(shí)例分析”文章吧。
創(chuàng)新互聯(lián)是一家集成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、網(wǎng)站頁面設(shè)計(jì)、網(wǎng)站優(yōu)化SEO優(yōu)化為一體的專業(yè)網(wǎng)絡(luò)公司,已為成都等多地近百家企業(yè)提供網(wǎng)站建設(shè)服務(wù)。追求良好的瀏覽體驗(yàn),以探求精品塑造與理念升華,設(shè)計(jì)最適合用戶的網(wǎng)站頁面。 合作只是第一步,服務(wù)才是根本,我們始終堅(jiān)持講誠信,負(fù)責(zé)任的原則,為您進(jìn)行細(xì)心、貼心、認(rèn)真的服務(wù),與眾多客戶在蓬勃發(fā)展的市場(chǎng)環(huán)境中,互促共生。
一、Why K8s
1、資源隔離
當(dāng)前的Redis Cluster部署在物理機(jī)集群上,為了提高資源利用率節(jié)約成本,多業(yè)務(wù)線的Redis集群都是混布的。由于沒有做CPU的資源隔離,經(jīng)常出現(xiàn)某Redis節(jié)點(diǎn)CPU使用率過高導(dǎo)致其他Redis集群的節(jié)點(diǎn)爭搶不到CPU資源引起時(shí)延抖動(dòng)。因?yàn)椴煌募夯觳迹@類問題很難快速定位,影響運(yùn)維效率。K8s容器化部署可以指定 CPU request 和 CPU limit ,在提高資源利用率的同時(shí)避免了資源爭搶。
2、自動(dòng)化部署
當(dāng)前Redis Cluster在物理機(jī)上的部署過程十分繁瑣,需要通過查看元信息數(shù)據(jù)庫查找有空余資源的機(jī)器,手動(dòng)修改很多配置文件再逐個(gè)部署節(jié)點(diǎn),最后使用redis_trib工具創(chuàng)建集群,新集群的初始化工作經(jīng)常需要一兩個(gè)小時(shí)。
K8s通過StatefulSet部署Redis集群,使用configmap管理配置文件,新集群部署時(shí)間只需要幾分鐘,大大提高了運(yùn)維效率。
二、How K8s
客戶端通過LVS的VIP統(tǒng)一接入,通過Redis Proxy轉(zhuǎn)發(fā)服務(wù)請(qǐng)求到Redis Cluster集群。這里我們引入了Redis Proxy來轉(zhuǎn)發(fā)請(qǐng)求。
1、Redis Cluster部署方式
Redis部署為StatefulSet,作為有狀態(tài)的服務(wù),選擇StatefulSet最為合理,可以將節(jié)點(diǎn)的RDB/AOF持久化到分布式存儲(chǔ)中。當(dāng)節(jié)點(diǎn)重啟漂移到其他機(jī)器上時(shí),可通過掛載的PVC(PersistentVolumeClaim)拿到原來的RDB/AOF來同步數(shù)據(jù)。
我們選擇的持久化存儲(chǔ)PV(PersistentVolume)是Ceph Block Service。Ceph的讀寫性能低于本地磁盤,會(huì)帶來100~200ms的讀寫時(shí)延。但由于Redis的RDB/AOF的寫出都是異步的,分布式存儲(chǔ)帶來的讀寫延遲對(duì)服務(wù)并沒有影響。
2、Proxy選型
開源的Redis Proxy有很多,常見的開源Redis Proxy如下:
我們希望能夠繼續(xù)使用Redis Cluster來管理Redis集群,所以Codis和Twemproxy不再考慮。redis-cluster-proxy是Redis官方在6.0版本推出的支持Redis Cluster協(xié)議的Proxy,但是目前還沒有穩(wěn)定版,暫時(shí)也無法大規(guī)模應(yīng)用。
備選就只有Cerberus和Predixy兩種。我們?cè)贙8s環(huán)境上對(duì)Cerberus和Predixy進(jìn)行了性能測(cè)試,結(jié)果如下:
測(cè)試環(huán)境
測(cè)試工具: redis-benchmark
Proxy CPU: 2 core
Client CPU: 2 core
Redis Cluster: 3 master nodes, 1 CPU per node
測(cè)試結(jié)果
在相同workload和配置下,Predixy的最高QPS要優(yōu)于Cerberus,時(shí)延也比較接近。綜合來看,Predixy比Cerberus的性能要高33%~60%,并且數(shù)據(jù)的key/value越大,Predixy優(yōu)勢(shì)越明顯,所以最后我們選擇了Predixy。
為了適應(yīng)業(yè)務(wù)和K8s環(huán)境,在上線前我們對(duì)Predixy做了大量的改動(dòng),增加了很多新的功能,比如動(dòng)態(tài)切換后端Redis Cluster、黑白名單、異常操作審計(jì)等。
3、Proxy部署方式
Proxy作為deployment部署,無狀態(tài)輕量化,通過LB對(duì)外提供服務(wù),很容易做到動(dòng)態(tài)擴(kuò)縮容。同時(shí),我們?yōu)镻roxy開發(fā)了動(dòng)態(tài)切換后端Redis Cluster的功能,可實(shí)現(xiàn)在線添加和切換Redis Cluster。
4、Proxy自動(dòng)擴(kuò)縮容方式
我們使用K8s原生的HPA(Horizontal Pod Autoscaler)來實(shí)現(xiàn)Proxy的動(dòng)態(tài)擴(kuò)縮容。當(dāng)Proxy所有pod的平均CPU使用率超過一定閾值時(shí),會(huì)自動(dòng)觸發(fā)擴(kuò)容,HPA會(huì)將Proxy的replica數(shù)加1,之后LVS就會(huì)探測(cè)到新的Proxy pod并將一部分流量切過去。如果擴(kuò)容后CPU使用率仍然超過規(guī)定的閾值,會(huì)繼續(xù)觸發(fā)擴(kuò)容邏輯。但是在擴(kuò)容成功5分鐘內(nèi),不論CPU使用率降到多低,都不會(huì)觸發(fā)縮容邏輯,這樣就避免了頻繁的擴(kuò)縮容給集群穩(wěn)定性帶來的影響。
HPA可配置集群的最少(MINPODS)和最多(MAXPODS)pod數(shù)量,集群負(fù)載再低也不會(huì)縮容到MINPODS以下數(shù)量的pods。建議客戶可以根據(jù)自己的實(shí)際業(yè)務(wù)情況來決定MINPODS和MAXPODS的值。
三、Why Proxy
1、Redis pod重啟可導(dǎo)致IP變化
使用Redis Cluster的Redis客戶端,都需要配置集群的部分IP和Port,用于客戶端重啟時(shí)查找Redis Cluster的入口。對(duì)于物理機(jī)集群部署的Redis節(jié)點(diǎn),即便遇到實(shí)例重啟或者機(jī)器重啟,IP和Port都可以保持不變,客戶端依然能夠找到Redis Cluster的拓?fù)?。但是部署在K8s上的Redis Cluster,pod重啟是不保證IP不變的(即便是重啟在原來的K8s node上),這樣客戶端重啟時(shí),就可能會(huì)找不到Redis Cluster的入口。
通過在客戶端和Redis Cluster之間加上Proxy,就對(duì)客戶端屏蔽了Redis Cluster的信息,Proxy可以動(dòng)態(tài)感知Redis Cluster的拓?fù)渥兓?,客戶端只需要將LVS的IP:Port作為入口,請(qǐng)求轉(zhuǎn)發(fā)到Proxy上,即可以像使用單機(jī)版Redis一樣使用Redis Cluster集群,而不需要Redis智能客戶端。
2、Redis處理連接負(fù)載高
在6.0版本之前,Redis都是單線程處理大部分任務(wù)的。當(dāng)Redis節(jié)點(diǎn)的連接較高時(shí),Redis需要消耗大量的CPU資源處理這些連接,導(dǎo)致時(shí)延升高。有了Proxy之后,大量連接都在Proxy上,而Proxy跟Redis實(shí)例之間只保持很少的連接,這樣降低了Redis的負(fù)擔(dān),避免了因?yàn)檫B接增加而導(dǎo)致的Redis時(shí)延升高。
3、集群遷移切換需要應(yīng)用重啟
在使用過程中,隨著業(yè)務(wù)的增長,Redis集群的數(shù)據(jù)量會(huì)持續(xù)增加,當(dāng)每個(gè)節(jié)點(diǎn)的數(shù)據(jù)量過高時(shí),BGSAVE的時(shí)間會(huì)大大延長,降低集群的可用度。同時(shí)QPS的增加也會(huì)導(dǎo)致每個(gè)節(jié)點(diǎn)的CPU使用率增高。這都需要增加擴(kuò)容集群來解決。目前Redis Cluster的橫向擴(kuò)展能力不是很好,原生的slots搬移方案效率很低。新增節(jié)點(diǎn)后,有些客戶端比如Lettuce,會(huì)因?yàn)榘踩珯C(jī)制無法識(shí)別新節(jié)點(diǎn)。另外遷移時(shí)間也完全無法預(yù)估,遷移過程中遇到問題也無法回退。
當(dāng)前物理機(jī)集群的擴(kuò)容方案是:
按需創(chuàng)建新集群;
使用同步工具將數(shù)據(jù)從老集群同步到新集群;
確認(rèn)數(shù)據(jù)無誤后,跟業(yè)務(wù)溝通,重啟服務(wù)切換到新集群。
整個(gè)過程繁瑣而且風(fēng)險(xiǎn)較大,還需要業(yè)務(wù)重啟服務(wù)。
有了Proxy層,可以將后端的創(chuàng)建、同步和切換集群對(duì)客戶端屏蔽掉。新老集群同步完成之后,向Proxy發(fā)送命令就可以將連接換到新集群,可以實(shí)現(xiàn)對(duì)客戶端完全無感知的集群擴(kuò)縮容。
4、數(shù)據(jù)安全風(fēng)險(xiǎn)
Redis是通過AUTH來實(shí)現(xiàn)鑒權(quán)操作,客戶端直連Redis,密碼還是需要在客戶端保存。而使用Proxy,客戶端只需要通過Proxy的密碼來訪問Proxy,不需要知道Redis的密碼。Proxy還限制了FLUSHDB、CONFIG SET等操作,避免了客戶誤操作清空數(shù)據(jù)或修改Redis配置,大大提高了系統(tǒng)的安全性。
同時(shí),Redis并沒有提供審計(jì)功能。我們?cè)赑roxy上增加了高危操作的日志保存功能,可以在不影響整體性能的前提下提供審計(jì)能力。
四、Proxy帶來的問題
1、多一跳帶來的時(shí)延
Proxy在客戶端和Redis實(shí)例之間,客戶端訪問Redis數(shù)據(jù)需要先訪問Proxy再訪問Redis節(jié)點(diǎn),多了一跳,會(huì)導(dǎo)致時(shí)延增加。經(jīng)測(cè)試,多一跳會(huì)增加0.2~0.3ms的時(shí)延,不過通常這對(duì)業(yè)務(wù)來說是可以接受的。
2、Pod漂移造成IP變化
Proxy在K8s上是通過deployment部署的,一樣會(huì)有節(jié)點(diǎn)重啟導(dǎo)致IP變化的問題。我們K8s的LB方案可以感知到Proxy的IP變化,動(dòng)態(tài)的將LVS的流量切到重啟后的Proxy上。
3、LVS帶來的時(shí)延
LVS也會(huì)帶來時(shí)延,如下表中的測(cè)試,不同的數(shù)據(jù)長度get/set操作,LVS引入的時(shí)延小于0.1ms。
五、K8s帶來的好處
1、部署方便
通過運(yùn)維平臺(tái)調(diào)用K8s API部署集群,大大提高了運(yùn)維效率。
2、解決端口管理問題
目前小米在物理機(jī)上部署Redis實(shí)例是通過端口來區(qū)分的,并且下線的端口不能復(fù)用,也就是說整個(gè)公司每個(gè)Redis實(shí)例都有唯一的端口號(hào)。目前65535個(gè)端口已經(jīng)用到了40000多,按現(xiàn)在的業(yè)務(wù)發(fā)展速度,將在兩年內(nèi)耗盡端口資源。而通過K8s部署,每一個(gè)Redis實(shí)例對(duì)應(yīng)的K8s pod都有獨(dú)立的IP,不存在端口耗盡問題和復(fù)雜的管理問題。
3、降低客戶使用門檻
對(duì)應(yīng)用來說,只需要使用單機(jī)版的非智能客戶端連接VIP,降低了使用門檻,避免了繁瑣復(fù)雜的參數(shù)設(shè)置。同時(shí)由于VIP和端口是固定不變的,應(yīng)用程序不再需要自己管理Redis Cluster的拓?fù)洹?/p>
4、提高客戶端性能
使用非智能客戶端還可以降低客戶端的負(fù)載,因?yàn)橹悄芸蛻舳诵枰诳蛻舳藢?duì)key進(jìn)行hash以確定將請(qǐng)求發(fā)送到哪個(gè)Redis節(jié)點(diǎn),在QPS比較高的情況下會(huì)消耗客戶端機(jī)器的CPU資源。當(dāng)然,為了降低客戶端應(yīng)用遷移的難度,我們讓Proxy也支持了智能客戶端協(xié)議。
5、動(dòng)態(tài)升級(jí)和擴(kuò)縮容
Proxy支持動(dòng)態(tài)添加切換Redis Cluster的功能,這樣Redis Cluster的集群升級(jí)和擴(kuò)容切換過程可以做到對(duì)業(yè)務(wù)端完全無感知。例如,業(yè)務(wù)方使用30個(gè)節(jié)點(diǎn)的Redis Cluster集群,由于業(yè)務(wù)量的增加,數(shù)據(jù)量和QPS都增長的很快,需要將集群規(guī)模擴(kuò)容兩倍。如果在原有的物理機(jī)上擴(kuò)容,需要以下過程:
協(xié)調(diào)資源,部署60個(gè)節(jié)點(diǎn)的新集群;
手動(dòng)配置遷移工具,將當(dāng)前集群的數(shù)據(jù)遷移到新集群;
驗(yàn)證數(shù)據(jù)無誤后,通知業(yè)務(wù)方修改Redis Cluster連接池拓?fù)?,重啟服?wù)。
雖然Redis Cluster支持在線擴(kuò)容,但是擴(kuò)容過程中slots搬移會(huì)對(duì)線上業(yè)務(wù)造成影響,同時(shí)遷移時(shí)間不可控,所以現(xiàn)階段很少采用這種方式,只有在資源嚴(yán)重不足時(shí)才會(huì)偶爾使用。
在新的K8s架構(gòu)下,遷移過程如下:
通過API接口一鍵創(chuàng)建60個(gè)節(jié)點(diǎn)的新集群;
同樣通過API接口一鍵創(chuàng)建集群同步工具,將數(shù)據(jù)遷移到新集群;
驗(yàn)證數(shù)據(jù)無誤后,向Proxy發(fā)送命令添加新集群信息并完成切換。
整個(gè)過程對(duì)業(yè)務(wù)端完全無感知。
集群升級(jí)也很方便:如果業(yè)務(wù)方能接受一定的延遲毛刺,可以在低峰時(shí)通過StatefulSet滾動(dòng)升級(jí)的方式來實(shí)現(xiàn);如果業(yè)務(wù)對(duì)延遲有要求,可以通過創(chuàng)建新集群遷移數(shù)據(jù)的方式來實(shí)現(xiàn)。
6、提高服務(wù)穩(wěn)定性和資源利用率
通過K8s自帶的資源隔離能力,實(shí)現(xiàn)和其他不同類型應(yīng)用混部,在提高資源利用率的同時(shí),也能保證服務(wù)穩(wěn)定性。
六、遇到的問題
1、Pod重啟導(dǎo)致數(shù)據(jù)丟失
K8s的pod碰到問題重啟時(shí),由于重啟速度過快,會(huì)在Redis Cluster集群發(fā)現(xiàn)并切主前將pod重啟。如果pod上的Redis是slave,不會(huì)造成什么影響。但如果Redis是master,并且沒有AOF,重啟后原先內(nèi)存的數(shù)據(jù)都被清空,Redis會(huì)reload之前存儲(chǔ)的RDB文件,但是RDB文件并不是實(shí)時(shí)的數(shù)據(jù)。之后slave也會(huì)跟著把自己的數(shù)據(jù)同步成之前的RDB文件中的數(shù)據(jù)鏡像,會(huì)造成部分?jǐn)?shù)據(jù)丟失。
StatefulSet是有狀態(tài)服務(wù),部署的pod名是固定格式(StatefulSet名+編號(hào))。我們?cè)诔跏蓟疪edis Cluster時(shí),將相鄰編號(hào)的pod設(shè)置為主從關(guān)系。在重啟pod時(shí),通過pod名確定它的slave,在重啟pod前向從節(jié)點(diǎn)發(fā)送cluster failover命令,強(qiáng)制將活著的從節(jié)點(diǎn)切主。這樣在重啟后,該節(jié)點(diǎn)會(huì)自動(dòng)以從節(jié)點(diǎn)方式加入集群。
LVS映射時(shí)延
Proxy的pod是通過LVS實(shí)現(xiàn) 對(duì)于正常的Proxy pod下線,例如集群縮容、滾動(dòng)更新Proxy版本以及其它K8s可控的pod下線,在pod下線前會(huì)發(fā)消息給LVS并等待171秒,這段時(shí)間足夠LVS將這個(gè)pod的流量逐漸切到其他pod上,對(duì)業(yè)務(wù)無感知。 2、K8s StatefulSet無法滿足Redis Cluster部署要求 K8s原生的StatefulSet不能完全滿足Redis Cluster部署的要求: 1)Redis Cluster不允許同為主備關(guān)系的節(jié)點(diǎn)部署在同一臺(tái)機(jī)器上。這個(gè)很好理解,如果該機(jī)器宕機(jī),會(huì)導(dǎo)致這個(gè)數(shù)據(jù)分片不可用。 2)Redis Cluster不允許集群超過一半的主節(jié)點(diǎn)失效,因?yàn)槿绻^一半主節(jié)點(diǎn)失效,就無法有足夠的節(jié)點(diǎn)投票來滿足gossip協(xié)議的要求。因?yàn)镽edis Cluster的主備是可能隨時(shí)切換的,我們無法避免同一個(gè)機(jī)器上的所有節(jié)點(diǎn)都是主節(jié)點(diǎn)這種情況,所以在部署時(shí)不能允許集群中超過1/4的節(jié)點(diǎn)部署在同一臺(tái)機(jī)器上。 為了滿足上面的要求,原生StatefulSet可以通過 anti-affinity 功能來保證相同集群在同一臺(tái)機(jī)器上只部署一個(gè)節(jié)點(diǎn),但是這樣機(jī)器利用率很低。 因此我們開發(fā)了基于StatefulSet的CRD:RedisStatefulSet,會(huì)采用多種策略部署Redis節(jié)點(diǎn)。同時(shí),還在RedisStatefulSet中加入了一些Redis管理功能。這些我們將會(huì)在其他文章中來繼續(xù)詳細(xì)探討。 七、總結(jié) 目前集團(tuán)內(nèi)部已經(jīng)有多個(gè)業(yè)務(wù)的數(shù)十個(gè)Redis集群部署到了K8s上并運(yùn)行了半年多。得益于K8s的快速部署和故障遷移能力,這些集群的運(yùn)維工作量比物理機(jī)上的Redis集群低很多,穩(wěn)定性也得到了充分的驗(yàn)證。 在運(yùn)維過程中我們也遇到了不少問題,文章中提到的很多功能都是根據(jù)實(shí)際需求提煉出來的。目前還是有很多問題需要在后續(xù)逐步解決,以進(jìn)一步提高資源利用率和服務(wù)質(zhì)量。 1、混布 Vs. 獨(dú)立部署 物理機(jī)的Redis實(shí)例是獨(dú)立部署的,單臺(tái)物理機(jī)上部署的都是Redis實(shí)例,這樣有利于管理,但是資源利用率并不高。Redis實(shí)例使用了CPU、內(nèi)存和網(wǎng)絡(luò)IO,但存儲(chǔ)空間基本都是浪費(fèi)的。在K8s上部署Redis實(shí)例,其所在的機(jī)器上可能也會(huì)部署其他任意類型的服務(wù),這樣雖然可以提高機(jī)器的利用率,但是對(duì)于Redis這樣的可用性和時(shí)延要求都很高的服務(wù)來說,如果因?yàn)闄C(jī)器內(nèi)存不足而被驅(qū)逐,是不能接受的。這就需要運(yùn)維人員監(jiān)控所有部署了Redis實(shí)例的機(jī)器內(nèi)存,一旦內(nèi)存不足,就切主和遷移節(jié)點(diǎn),但這樣又增加運(yùn)維的工作量。 同時(shí),如果混部的其他服務(wù)是網(wǎng)絡(luò)吞吐很高的應(yīng)用,也可能對(duì)Redis服務(wù)造成影響。雖然K8s的anti-affinity功能可以將Redis實(shí)例有選擇地部署到?jīng)]有這類應(yīng)用的機(jī)器上,但是在機(jī)器資源緊張時(shí),還是無法避免這種情況。 2、Redis Cluster管理 Redis Cluster是一個(gè)P2P無中心節(jié)點(diǎn)的集群架構(gòu),依靠gossip協(xié)議傳播協(xié)同自動(dòng)化修復(fù)集群的狀態(tài),節(jié)點(diǎn)上下線和網(wǎng)絡(luò)問題都可能導(dǎo)致Redis Cluster的部分節(jié)點(diǎn)狀態(tài)出現(xiàn)問題,例如會(huì)在集群拓?fù)渲谐霈F(xiàn)failed或者h(yuǎn)andshake狀態(tài)的節(jié)點(diǎn),甚至腦裂。對(duì)這種異常狀態(tài),我們可以在Redis CRD上增加更多的功能來逐步解決,進(jìn)一步提高運(yùn)維效率。 3、審計(jì)與安全 Redis本身只提供了Auth密碼認(rèn)證保護(hù)功能,沒有權(quán)限管理,安全性較差。通過Proxy,我們可以通過密碼區(qū)分客戶端類型,管理員和普通用戶使用不同的密碼登錄,可執(zhí)行的操作權(quán)限也不同,這樣就可以實(shí)現(xiàn)權(quán)限管理和操作審計(jì)等功能。 4、支持多Redis Cluster 單個(gè)Redis Cluster由于gossip協(xié)議的限制,橫向擴(kuò)展能力有限,集群規(guī)模在300個(gè)節(jié)點(diǎn)時(shí),節(jié)點(diǎn)選主這類拓?fù)渥兏男示兔黠@降低。同時(shí),由于單個(gè)Redis實(shí)例的容量不宜過高,單個(gè)Redis Cluster也很難支持TB以上的數(shù)據(jù)規(guī)模。通過Proxy,我們可以對(duì)key做邏輯分片,這樣單個(gè)Proxy就可以接入多個(gè)Redis Cluster,從客戶端的視角來看,就相當(dāng)于接入了一個(gè)能夠支持更大數(shù)據(jù)規(guī)模的Redis集群。 以上就是關(guān)于“Redis集群實(shí)例分析”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)頁名稱:Redis集群實(shí)例分析
分享路徑:http://weahome.cn/article/gjejpg.html