當(dāng)前位置:首頁 > 公眾號精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]作者:vivo互聯(lián)網(wǎng)數(shù)據(jù)庫團(tuán)隊(duì)—YuanJianwei一、背景在現(xiàn)網(wǎng)環(huán)境,一些使用Redis集群的業(yè)務(wù)隨著業(yè)務(wù)量的上漲,往往需要進(jìn)行節(jié)點(diǎn)擴(kuò)容操作。之前有了解到運(yùn)維同學(xué)對一些節(jié)點(diǎn)數(shù)比較大的Redis集群進(jìn)行擴(kuò)容操作后,業(yè)務(wù)側(cè)反映集群性能下降,具體表現(xiàn)在訪問時(shí)延增長明顯。某些業(yè)務(wù)對R...

作者:vivo互聯(lián)網(wǎng)數(shù)據(jù)庫團(tuán)隊(duì)—Yuan Jianwei

一、背景


在現(xiàn)網(wǎng)環(huán)境,一些使用Redis集群的業(yè)務(wù)隨著業(yè)務(wù)量的上漲,往往需要進(jìn)行節(jié)點(diǎn)擴(kuò)容操作。


之前有了解到運(yùn)維同學(xué)對一些節(jié)點(diǎn)數(shù)比較大的Redis集群進(jìn)行擴(kuò)容操作后,業(yè)務(wù)側(cè)反映集群性能下降,具體表現(xiàn)在訪問時(shí)延增長明顯。


某些業(yè)務(wù)對Redis集群訪問時(shí)延比較敏感,例如現(xiàn)網(wǎng)環(huán)境對模型實(shí)時(shí)讀取,或者一些業(yè)務(wù)依賴讀取Redis集群的同步流程,會影響業(yè)務(wù)的實(shí)時(shí)流程時(shí)延。業(yè)務(wù)側(cè)可能無法接受。


為了找到這個(gè)問題的根因,我們對某一次的Redis集群遷移操作后的集群性能下降問題進(jìn)行排查。


1.1 問題描述


這一次具體的Redis集群問題的場景是:某一個(gè)Redis集群進(jìn)行過擴(kuò)容操作。業(yè)務(wù)側(cè)使用Hiredis-vip進(jìn)行Redis集群訪問,進(jìn)行MGET操作。


業(yè)務(wù)側(cè)感知到訪問Redis集群的時(shí)延變高。


1.2 現(xiàn)網(wǎng)環(huán)境說明


  • 目前現(xiàn)網(wǎng)環(huán)境部署的Redis版本多數(shù)是3.x或者4.x版本;

  • 業(yè)務(wù)訪問Redis集群的客戶端品類繁多,較多的使用Jedis。本次問題排查的業(yè)務(wù)使用客戶端Hiredis-vip進(jìn)行訪問;

  • Redis集群的節(jié)點(diǎn)數(shù)比較大,規(guī)模是100 ;

  • 集群之前存在擴(kuò)容操作。


1.3 觀察現(xiàn)象


因?yàn)闀r(shí)延變高,我們從幾個(gè)方面進(jìn)行排查:

  • 帶寬是否打滿;

  • CPU是否占用過高;

  • OPS是否很高;


通過簡單的監(jiān)控排查,帶寬負(fù)載不高。但是發(fā)現(xiàn)CPU表現(xiàn)異常:


Redis大集群擴(kuò)容性能優(yōu)化實(shí)踐


1.3.1 對比ops和CPU負(fù)載


觀察業(yè)務(wù)反饋使用的MGET和CPU負(fù)載,我們找到了對應(yīng)的監(jiān)控曲線。


從時(shí)間上分析,MGET和CPU負(fù)載高并沒有直接關(guān)聯(lián)。業(yè)務(wù)側(cè)反饋的是MGET的時(shí)延普遍增高。此處看到MGET的OPS和CPU負(fù)載是錯(cuò)峰的。


Redis大集群擴(kuò)容性能優(yōu)化實(shí)踐


此處可以暫時(shí)確定業(yè)務(wù)請求和CPU負(fù)載暫時(shí)沒有直接關(guān)系,但是從曲線上可以看出:在同一個(gè)時(shí)間軸上,業(yè)務(wù)請求和cpu負(fù)載存在錯(cuò)峰的情況,兩者間應(yīng)該有間接關(guān)系。


1.3.2 對比Cluster指令OPS和CPU負(fù)載


由于之前有運(yùn)維側(cè)同事有反饋集群進(jìn)行過擴(kuò)容操作,必然存在slot的遷移。


考慮到業(yè)務(wù)的客戶端一般都會使用緩存存放Redis集群的slot拓?fù)湫畔ⅲ虼藨岩蒀luster指令會和CPU負(fù)載存在一定聯(lián)系。


我們找到了當(dāng)中確實(shí)有一些聯(lián)系:


Redis大集群擴(kuò)容性能優(yōu)化實(shí)踐


此處可以明顯看到:某個(gè)實(shí)例在執(zhí)行Cluster指令的時(shí)候,CPU的使用會明顯上漲。


根據(jù)上述現(xiàn)象,大致可以進(jìn)行一個(gè)簡單的聚焦:

  • 業(yè)務(wù)側(cè)執(zhí)行MGET,因?yàn)橐恍┰驁?zhí)行了Cluster指令;

  • Cluster指令因?yàn)橐恍┰驅(qū)е翪PU占用較高影響其他操作;

  • 懷疑Cluster指令是性能瓶頸。


同時(shí),引申幾個(gè)需要關(guān)注的問題:

  • 為什么會有較多的Cluster指令被執(zhí)行?

  • 為什么Cluster指令執(zhí)行的時(shí)候CPU資源比較高?

  • 為什么節(jié)點(diǎn)規(guī)模大的集群遷移slot操作容易“中招”?


二、問題排查


2.1 Redis熱點(diǎn)排查


我們對一臺現(xiàn)場出現(xiàn)了CPU負(fù)載高的Redis實(shí)例使用perf top進(jìn)行簡單的分析:


Redis大集群擴(kuò)容性能優(yōu)化實(shí)踐


從上圖可以看出來,函數(shù)(ClusterReplyMultiBulkSlots)占用的CPU資源高達(dá) 51.84%,存在異常


2.1.1 ClusterReplyMultiBulkSlots實(shí)現(xiàn)原理


我們對clusterReplyMultiBulkSlots函數(shù)進(jìn)行分析:

void clusterReplyMultiBulkSlots(client *c) { /* Format: 1) 1) start slot * 2) end slot * 3) 1) master IP * 2) master port * 3) node ID * 4) 1) replica IP * 2) replica port * 3) node ID * ... continued until done */ int num_masters = 0; void *slot_replylen = addDeferredMultiBulkLength(c); dictEntry *de; dictIterator *di = dictGetSafeIterator(server.cluster->nodes); while((de = dictNext(di)) != NULL) { /*注意:此處是對當(dāng)前Redis節(jié)點(diǎn)記錄的集群所有主節(jié)點(diǎn)都進(jìn)行了遍歷*/ clusterNode *node = dictGetVal(de); int j = 0, start = -1; /* Skip slaves (that are iterated when producing the output of their * master) and masters not serving any slot. */ /*跳過備節(jié)點(diǎn)。備節(jié)點(diǎn)的信息會從主節(jié)點(diǎn)側(cè)獲取。*/ if (!nodeIsMaster(node) || node->numslots == 0) continue; for (j = 0; j < CLUSTER_SLOTS; j ) { /*注意:此處是對當(dāng)前節(jié)點(diǎn)中記錄的所有slot進(jìn)行了遍歷*/ int bit, i; /*確認(rèn)當(dāng)前節(jié)點(diǎn)是不是占有循環(huán)終端的slot*/ if ((bit = clusterNodeGetSlotBit(node,j)) != 0) { if (start == -1) start = j; } /*簡單分析,此處的邏輯大概就是找出連續(xù)的區(qū)間,是的話放到返回中;不是的話繼續(xù)往下遞歸slot。 如果是開始的話,開始一個(gè)連續(xù)區(qū)間,直到和當(dāng)前的不連續(xù)。*/ if (start != -1
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉