方案致力于實(shí)現(xiàn)的是相對靜態(tài)數(shù)據(jù)的緩存一致性問題蜜自,借鑒思想是用于CPU高速緩存和內(nèi)存之間同步的MESI協(xié)議以及內(nèi)存屏障的設(shè)計(jì)思想。在這里我們并不會Push服務(wù)去完成每塊數(shù)據(jù)的更新或者刪除泄私,數(shù)據(jù)中間件的職責(zé)是發(fā)出緩存失效標(biāo)記且確認(rèn)緩存失效標(biāo)記被準(zhǔn)確接收,緩存的更新工作應(yīng)由服務(wù)方實(shí)現(xiàn)备闲。
數(shù)據(jù)更新流程如下:
1晌端、各服務(wù)啟動,并發(fā)送監(jiān)控標(biāo)記和監(jiān)聽標(biāo)記至資源注冊中心
2恬砂、服務(wù)節(jié)點(diǎn)發(fā)送SQL執(zhí)行請求至MySQL中間件
3咧纠、中間件記錄日志,并下發(fā)請求至MySQL服務(wù)器
(注:此處有多種實(shí)現(xiàn)泻骤,a漆羔、請求發(fā)送至MySQL中間件,中間件進(jìn)行請求透傳狱掂;b演痒、請求發(fā)送至MySQL服務(wù)器,但是我們可以偽裝一個Slave節(jié)點(diǎn)符欠,進(jìn)行主從Dump復(fù)制嫡霞,像阿里的canal即此種思路;c希柿、第三種思路诊沪,在框架層接入MyBatis或者JPA攔截器养筒,進(jìn)行日志記錄發(fā)送至指定地址進(jìn)行日志分析即可,可選用logstash)
4端姚、中間件發(fā)送記錄日志至資源注冊中心
5晕粪、資源注冊中心分析日志,讀取固化的資源注冊節(jié)點(diǎn)并發(fā)送緩存失效標(biāo)記至各注冊節(jié)點(diǎn)渐裸,此處選用RocketMQ作為消息組件發(fā)送巫湘,保證每個Consumer都可以接收到失效事件
6、注冊節(jié)點(diǎn)進(jìn)入預(yù)更新姿態(tài)昏鹃,使自身緩存標(biāo)記失效
7尚氛、通知失敗節(jié)點(diǎn)重復(fù)嘗試至最大預(yù)設(shè)置次數(shù),若依然失敗標(biāo)記服務(wù)不可用洞渤,發(fā)出異常告警阅嘶,通過通知中心即時發(fā)送異常給運(yùn)維人員
8、注冊節(jié)點(diǎn)下次讀取時先預(yù)讀緩存標(biāo)記载迄,發(fā)現(xiàn)已失效讯柔,則更新緩存并重置緩存失效標(biāo)記
方案注:
1、借助隊(duì)列實(shí)現(xiàn)緩存更新的并發(fā)問題护昧,如Disruptor魂迄,按照時間戳排序更新
2、熱點(diǎn)數(shù)據(jù)和靜態(tài)數(shù)據(jù)的更新方案完全不同惋耙,熱點(diǎn)數(shù)據(jù)的實(shí)現(xiàn)是單體數(shù)據(jù)服務(wù)緩存+數(shù)據(jù)持久化+分布式緩存一致性解決方案捣炬,原因是更新頻繁,讀取頻繁的數(shù)據(jù)如果實(shí)現(xiàn)的全業(yè)務(wù)服務(wù)下的緩存一致性怠晴,那么緩存是沒有意義的遥金,假設(shè)有兩個數(shù)據(jù)服務(wù)實(shí)例,十五個業(yè)務(wù)實(shí)例蒜田,若采用此種策略,導(dǎo)致的結(jié)果是选泻,數(shù)據(jù)更新一次冲粤,更新代價乘十五,而數(shù)據(jù)實(shí)例間的服務(wù)一致性只需增加一倍更新代價页眯。這里考量的是遠(yuǎn)程調(diào)用代價和緩存更新代價的平衡梯捕。
3、Spring Cloud我們使用了Eureka Server在此處被復(fù)用窝撵,用來做資源注冊中心傀顾,原功能保持不變。這里直接在源碼上增加定制功能或者使用SPI機(jī)制進(jìn)行功能嵌入均可碌奉,不限定實(shí)現(xiàn)方式短曾,這里比較推薦SPI機(jī)制寒砖,因?yàn)槲覀€人信奉:做加法容易,做減法難的準(zhǔn)則<倒铡Aǘ肌!
注:本文中講述的MESI協(xié)議婉徘,內(nèi)存屏障漠嵌,Spring Cloud框架,TCC協(xié)議等概念性術(shù)語需自行了解盖呼,我不想把這篇博客變成科普文儒鹿,見諒。