雙緩存架構(gòu)實(shí)踐
在一些高并發(fā)場(chǎng)景下,不僅追求RT也寄希望于抗住超高的流量.比如像首頁(yè)營(yíng)銷(xiāo)位姥饰、banner位饿幅、排行榜等,不僅用戶(hù)點(diǎn)擊量大,而且接口響應(yīng)必須快,不然給用戶(hù)有明顯的延遲感.但是這些模塊有一個(gè)共同的特點(diǎn),一般只有在運(yùn)營(yíng)需要做活動(dòng)的時(shí)候才會(huì)變更一下圖片育特、順序洽沟、用戶(hù)標(biāo)簽等之類(lèi)的基礎(chǔ)信息.單純的Db是很難扛住大流量的,redis作為高性能非關(guān)系型數(shù)據(jù)庫(kù)雖然有良好的表現(xiàn),但是網(wǎng)絡(luò)IO瓶頸和帶寬之類(lèi)的問(wèn)題無(wú)法解決.本文將設(shè)計(jì)一個(gè)雙緩存的架構(gòu)模型來(lái)解決首頁(yè)底部金剛位動(dòng)態(tài)展示的功能.
1. 技術(shù)選型
??springboot+rocketMq+redisCluster+caffeineCache
2. Caffeine
??Caffeine是新出現(xiàn)的一個(gè)高性能的Java緩存慎璧,在springcontext5.x之后不在支持Guava Cache逮栅,Caffeine采用了W-TinyLFU回收策略,集合了LRU和LFU的優(yōu)點(diǎn)钱贯,提供了一個(gè)最佳的命中率挫掏,在效率上可以秒殺Guava Cache.
3. 為什么不用redis
??首先redis存儲(chǔ)結(jié)構(gòu)選型上只能是String或者Hash,其他結(jié)構(gòu)都不適合隨機(jī)刪除.對(duì)于集群模式下的批量獲取,在redis3.x即redis集群架構(gòu)體系下,是沒(méi)有mget這個(gè)命令的,再有這批量的id分布在不同的節(jié)點(diǎn)上,在高并發(fā)下網(wǎng)絡(luò)IO會(huì)成為一個(gè)瓶頸.如果采用for循環(huán)get,性能會(huì)大打折扣.這里我們用本地緩存來(lái)解決這種可遇見(jiàn)未來(lái)的訪問(wèn),還能很好的解決網(wǎng)絡(luò)IO開(kāi)銷(xiāo)問(wèn)題.
4. 集群模式下的消息一致性問(wèn)題
?? Caffeine是本地緩存,底層是基于ConCurrentHashMap.所以一旦需要更新本地緩存,是無(wú)法是同步其他節(jié)點(diǎn)消息.那解決辦法有嗎?答案當(dāng)然是有的, 本文提供幾種解決思路.
?? 1).Caffeine提供提供了定時(shí)刷新機(jī)制,但是很遺憾不太適合我這種場(chǎng)景,因?yàn)槲覀兊膹V告位很少有變更,甚至幾周變一次,我們無(wú)法精確評(píng)估其失效時(shí)機(jī),失效太快會(huì)頻繁更新ConCurrentHashMap
?? 2).基于redis做pub-sub,廣播訂閱機(jī)制(痛點(diǎn)就是消息發(fā)送即丟失)
?? 3).基于mQ的廣播消費(fèi)的模式去同步所有節(jié)點(diǎn)的信息