更新時(shí)間:2024-08-12 11:55:06作者:佚名
眾所周知,分布式緩存是提升系統(tǒng)性能的銀彈,在大型分布式系統(tǒng)中使用頻率很高,對(duì)提升系統(tǒng)性能起著不可或缺的作用。近些年,分布式和集中式系統(tǒng)在整個(gè)IT行業(yè)大行其道,CRM基于高內(nèi)聚、低耦合的原則,逐漸演化為多中心分布式部署架構(gòu)。由此產(chǎn)生的中心間交互,在日益復(fù)雜的業(yè)務(wù)催化下,對(duì)PAAS平臺(tái)組件提出了更高的要求。不出意外,分布式緩存在業(yè)務(wù)生產(chǎn)中也面臨著諸多挑戰(zhàn)。
02 理想與現(xiàn)實(shí)的沖突
業(yè)務(wù)系統(tǒng)引入分布式緩存的初衷是為了提升系統(tǒng)性能,為用戶帶來(lái)快速、簡(jiǎn)潔、靈活的操作體驗(yàn)。為了盡快享受到分布式緩存帶來(lái)的好處,加速系統(tǒng)建設(shè)中分布式緩存的引入,采用惰性加載(讀取時(shí)觸發(fā))模式——當(dāng)緩存中沒有數(shù)據(jù)時(shí),先從DB讀取,再加載到分布式緩存中。這種模式在很多系統(tǒng)建設(shè)初期很常見。
隨著時(shí)間的推移和業(yè)務(wù)需求的變化,人們會(huì)發(fā)現(xiàn)單純使用分布式緩存已經(jīng)不能滿足復(fù)雜業(yè)務(wù)的需求,因此會(huì)加入應(yīng)用服務(wù)器作為二級(jí)緩存,減少應(yīng)用與遠(yuǎn)程分布式緩存的交互次數(shù),經(jīng)過(guò)調(diào)整后,系統(tǒng)的緩存使用架構(gòu)變成了兩級(jí)模型。
在這個(gè)架構(gòu)模式下,我們發(fā)現(xiàn)在很多業(yè)務(wù)場(chǎng)景,比如商品查詢、品銷關(guān)系查詢等,系統(tǒng)性能得到了很大的提升。然而這也帶來(lái)了一些緩存使用上的問(wèn)題:
1)緩存數(shù)據(jù)不透明:無(wú)論是遠(yuǎn)程分布式緩存還是本地二級(jí)緩存都是巨大的黑盒子,目前還沒有可靠的可視化工具可以清晰的查看緩存的內(nèi)容。尤其是緩存key/value在應(yīng)用層處理之后,運(yùn)維人員沒有辦法通過(guò)簡(jiǎn)單的標(biāo)識(shí)來(lái)查看緩存key對(duì)應(yīng)的value。
2)多中心緩存刷新問(wèn)題:在多中心架構(gòu)下,多個(gè)中心可能需要同一套配置數(shù)據(jù),那么在刷新的時(shí)候,如何保證每個(gè)中心的緩存都能被刷新?如何保證錯(cuò)過(guò)的刷新能被及時(shí)發(fā)現(xiàn)并靈活處理?
3)緩存數(shù)據(jù)一致性問(wèn)題:如何保證遠(yuǎn)程分布式緩存、本地二級(jí)緩存、DB的數(shù)據(jù)一致性?如何及時(shí)發(fā)現(xiàn)不一致情況并進(jìn)行預(yù)警。
在分布式緩存給業(yè)務(wù)系統(tǒng)帶來(lái)的理想性能提升面前,使用過(guò)程中還存在一些技術(shù)與業(yè)務(wù)融合的痛點(diǎn),運(yùn)維過(guò)程中也面臨一些比較實(shí)際的問(wèn)題,解決理想與現(xiàn)實(shí)的沖突也是一大挑戰(zhàn),我們?cè)撛趺崔k?
03 直面挑戰(zhàn),給出答案
日常生活中,我們經(jīng)常會(huì)遇到房屋設(shè)施因時(shí)間、個(gè)人需求、人口規(guī)模等變化而變得陳舊過(guò)時(shí)的情況,需要時(shí)不時(shí)地進(jìn)行整理或翻新。有趣的是,實(shí)際的 CRM 緩存優(yōu)化過(guò)程與翻新舊房的過(guò)程類似。
圍繞“一個(gè)愿景、兩個(gè)目標(biāo)、四項(xiàng)提升、七項(xiàng)舉措”,各CRM中心緩存模塊的重構(gòu)優(yōu)化分為兩大部分:一是主體改造部分,二是微調(diào)打磨部分。
04 主體改造-緩存刷新重構(gòu)改造前期-現(xiàn)有功能拆解
改造前期,梳理原有功能邏輯的過(guò)程需要對(duì)現(xiàn)有業(yè)務(wù)支撐強(qiáng)度有一定的了解。拆解原有頁(yè)面所有組件,包括按鈕、表單等,記錄每個(gè)按鈕的功能。拆解是一個(gè)機(jī)械的過(guò)程,不需要任何額外的判斷。所有需要優(yōu)化的部分都會(huì)在后面的步驟中決定出來(lái)。這樣方便后期區(qū)分哪些業(yè)務(wù)功能需要保留,哪些邏輯需要重組。
設(shè)計(jì)階段:確定整體風(fēng)格,進(jìn)行總體設(shè)計(jì)
經(jīng)過(guò)拆解梳理現(xiàn)有功能,我們已經(jīng)知道系統(tǒng)中現(xiàn)有的功能,發(fā)現(xiàn)原來(lái)舊版的頁(yè)面功能比較混亂,有些邏輯冗余,有些功能存在缺陷,經(jīng)過(guò)梳理,我們按照業(yè)務(wù)維度進(jìn)行整理歸納,確定了整體優(yōu)化方案,制定了統(tǒng)一刷新的整體事項(xiàng)及方案:
重新設(shè)計(jì)的統(tǒng)一刷新架構(gòu)如圖所示
優(yōu)化重構(gòu)第一步:拆除工作-消除不必要的冗余邏輯
經(jīng)過(guò)功能分解和專項(xiàng)設(shè)計(jì)階段,發(fā)現(xiàn)緩存刷新口徑有十余個(gè),分散在各個(gè)中心,如此多的口徑和頁(yè)面,難免讓運(yùn)維人員感到無(wú)所適從,這就需要對(duì)各個(gè)中心分散的緩存管理功能進(jìn)行取精去糟粕,剔除分散的頁(yè)面和冗余的業(yè)務(wù)邏輯,將各個(gè)中心保留的頁(yè)面功能整合到門戶統(tǒng)一的管理頁(yè)面中。
第二步:隱藏構(gòu)建項(xiàng)目-統(tǒng)一緩存刷新機(jī)制及統(tǒng)一zk命令發(fā)布監(jiān)控模式
在分布式架構(gòu)中,對(duì)于要求性能更高、可用性更好的數(shù)據(jù),緩存往往會(huì)設(shè)計(jì)成多級(jí)結(jié)構(gòu)。如果有數(shù)據(jù)更新,需要考慮如何保證各個(gè)主機(jī)節(jié)點(diǎn)進(jìn)程中緩存數(shù)據(jù)的一致性。為了保證緩存刷新的一致性,我們采用一種新的刷新模式,通過(guò)刷新頁(yè)面的方式發(fā)起緩存刷新請(qǐng)求。應(yīng)用收到緩存刷新請(qǐng)求后,生成緩存刷新命令修修補(bǔ)補(bǔ),并將命令寫入ZK節(jié)點(diǎn)。各個(gè)中心后端應(yīng)用都有zookpper提供的API用于實(shí)時(shí)監(jiān)控。當(dāng)監(jiān)控到ZK節(jié)點(diǎn)數(shù)據(jù)發(fā)生變化時(shí),各個(gè)應(yīng)用獲取節(jié)點(diǎn)命令,解析命令,并調(diào)用命令緩存刷新API,刷新本地應(yīng)用節(jié)點(diǎn)進(jìn)程內(nèi)的緩存數(shù)據(jù)。
步驟3:基礎(chǔ)構(gòu)建項(xiàng)目-根據(jù)用戶角色提供刷新接口
緩存操作涉及的角色有版本發(fā)布、故障運(yùn)維人員、規(guī)范數(shù)據(jù)操作等,不同角色的操作習(xí)慣有所不同,為了使緩存管理功能更加強(qiáng)大,我們針對(duì)不同角色提供了個(gè)性化的刷新接口和邏輯。
1、對(duì)于運(yùn)維或者數(shù)據(jù)操作人員,我們提供查看緩存數(shù)據(jù)的接口,可以通過(guò)key值進(jìn)行刷新。
2、對(duì)于版本發(fā)布者,我們只需要提供表和字段對(duì)應(yīng)的KV關(guān)系刷新接口即可。
步驟4:通用裝修-緩存可視化、緩存檢查、緩存操作日志
要解決緩存可視化問(wèn)題網(wǎng)校頭條,必須將緩存內(nèi)容以結(jié)構(gòu)化的方式展現(xiàn)出來(lái)。在業(yè)務(wù)系統(tǒng)中,我們緩存的數(shù)據(jù)可能是單一的KV映射值,也可能是復(fù)雜的業(yè)務(wù)對(duì)象數(shù)據(jù)。因此,為了給運(yùn)維人員提供可視化的展現(xiàn),我們需要在內(nèi)部對(duì)key和value進(jìn)行封裝,然后提供給運(yùn)維人員。以某產(chǎn)品的配置數(shù)據(jù)緩存結(jié)構(gòu)為例,其結(jié)構(gòu)是由不同的分表緩存對(duì)象構(gòu)成的。
完成結(jié)構(gòu)化的梳理后,增加頁(yè)面緩存數(shù)據(jù)的結(jié)構(gòu)化展示,使得結(jié)果更加清晰直觀。
在完成緩存刷新動(dòng)作之后,無(wú)法檢查操作是否成功,以及緩存的數(shù)據(jù)狀態(tài)。為了解決這個(gè)問(wèn)題,還需要一個(gè)可視化的檢查功能。操作完成后可以在頁(yè)面發(fā)起請(qǐng)求,后端根據(jù)key值循環(huán)調(diào)用各個(gè)應(yīng)用節(jié)點(diǎn)獲取key對(duì)應(yīng)的緩存值進(jìn)行審計(jì),對(duì)比本地緩存是否與數(shù)據(jù)庫(kù)一致,標(biāo)記數(shù)據(jù)不一致的應(yīng)用節(jié)點(diǎn),同時(shí)組裝本地緩存對(duì)象的數(shù)據(jù)值。
將檢測(cè)結(jié)果可視化,并對(duì)比差異數(shù)據(jù),效果如下圖所示:
檢查
數(shù)據(jù)差異對(duì)比
05 微調(diào)完善-改善緩存引擎的使用
舊房裝修完成后,基本已經(jīng)達(dá)到入住標(biāo)準(zhǔn),但業(yè)主在裝修前保留的家具等物品需要妥善整理擺放,才能入住。俗話說(shuō)“三分雕琢,七分打磨”,在完成主要功能的優(yōu)化重構(gòu)后,常用的核心功能也需要細(xì)化打磨,提高緩存使用效率:
原子能力細(xì)化與封裝
對(duì)于部分緩存的API進(jìn)行了原子性的封裝,并針對(duì)每個(gè)API給出了詳細(xì)的描述,以保證其優(yōu)秀性、規(guī)范性,也為后續(xù)研發(fā)人員提供了方便。
緩存補(bǔ)償與緩存攔截機(jī)制
為了防止系統(tǒng)產(chǎn)生臟數(shù)據(jù),需要對(duì)異常數(shù)據(jù)進(jìn)行防范和清洗。對(duì)于緩存數(shù)據(jù)缺失值修修補(bǔ)補(bǔ),需要有補(bǔ)償機(jī)制;對(duì)于異常值,增加緩存校驗(yàn)攔截機(jī)制。
獨(dú)創(chuàng)功能-灰度制作緩存無(wú)縫切換
CRM灰度環(huán)境的應(yīng)用,可以讓部分用戶進(jìn)行版本升級(jí)內(nèi)測(cè),很大程度上規(guī)避了因?yàn)榘姹締?wèn)題導(dǎo)致生產(chǎn)失敗的風(fēng)險(xiǎn)。在架構(gòu)設(shè)計(jì)時(shí),對(duì)灰度和生產(chǎn)環(huán)境的緩存做了隔離。但是這樣的做法也帶來(lái)一些問(wèn)題,當(dāng)灰度驗(yàn)證的業(yè)務(wù)數(shù)據(jù)沒有及時(shí)完成,灰度切換到生產(chǎn)環(huán)境后,生產(chǎn)中無(wú)法讀取原有的灰度業(yè)務(wù)數(shù)據(jù)。因此我們改造了應(yīng)用的讀取策略,將一套實(shí)例數(shù)據(jù)(用戶、訂單、費(fèi)用等)緩存與生產(chǎn)和灰度共享,這樣灰度環(huán)境中的訂單在生產(chǎn)環(huán)境中也能查詢和續(xù)費(fèi)。系統(tǒng)切換后,用戶無(wú)需重新下單驗(yàn)收,實(shí)現(xiàn)了灰度和生產(chǎn)環(huán)境的無(wú)縫切換。
06 客戶評(píng)價(jià)
不同時(shí)期的業(yè)務(wù)對(duì)系統(tǒng)性能的要求不同,在性能要求不滿足時(shí)對(duì)系統(tǒng)設(shè)計(jì)的要求也不同。解釋起來(lái)有點(diǎn)困難,但總之,系統(tǒng)在不斷支持和演進(jìn)的過(guò)程中,會(huì)遇到前期設(shè)計(jì)不足、不完善導(dǎo)致的問(wèn)題。解決此類問(wèn)題,可以謹(jǐn)慎,只治不好的地方;也可以大刀闊斧,一路砍掉。對(duì)于這種不治之癥就會(huì)一直縈繞在病床上的問(wèn)題,修修補(bǔ)補(bǔ)可以暫時(shí)緩解,但果斷重構(gòu)才是負(fù)責(zé)任的表現(xiàn)。