二月份參加了螞蟻金服商家技術(shù)部(杭州)的Java服務(wù)端后臺(tái)開(kāi)發(fā)面試,結(jié)果掛在了交叉面。之后仔細(xì)反思了一下,應(yīng)該是緩存穿透這個(gè)問(wèn)題導(dǎo)致的吧,當(dāng)時(shí)太緊張回答成了工作中怎么使用一致性哈希+Redis解決遠(yuǎn)程分布式緩存負(fù)載均衡的,汗(⊙﹏⊙)b。
事后想找面試官再爭(zhēng)取一下,無(wú)奈座機(jī)打不通,找客服說(shuō)面試流程已經(jīng)關(guān)閉了,只好暫時(shí)作罷。。 但是整個(gè)面試下來(lái),收獲很大,意識(shí)到了自己的一些不足,最遺憾的是沒(méi)有和印象極其好極其好的一面和二面面試官一起工作的機(jī)會(huì)了,第一次面沒(méi)有經(jīng)驗(yàn),花名都忘了問(wèn)
了。。想想34歲還遠(yuǎn)著哪(呵呵),寫(xiě)代碼的生涯還長(zhǎng),一次失敗不算什么,樓主一定會(huì)回來(lái)的。
下面主要是寫(xiě)一下我實(shí)際工作中,解決的一個(gè)緩存數(shù)據(jù)量最大的場(chǎng)景的實(shí)現(xiàn)方案,以及怎么處理緩存穿透的。場(chǎng)景簡(jiǎn)單描述: 數(shù)據(jù)源是一張億萬(wàn)條數(shù)據(jù)的DB Table,我要使用它在我們查詢航班的API里匹配替換航班信息。實(shí)時(shí)讀DB做增量Cache是肯定不行的,用這
張DB的人很多,DBA肯定會(huì)找上門(mén)的,另外會(huì)加大我們查詢API的RT,最壞情況假如一個(gè)航班讀一次DB做匹配替換,一個(gè)熱門(mén)航線出現(xiàn)2000多個(gè)航段是家常便飯,再加上我們API的日均請(qǐng)求量已過(guò)半億,所以我也不干。。于是綜合討論了之后,使用了如下的技術(shù)方案:
1. 數(shù)據(jù)源的存儲(chǔ) 寫(xiě)一個(gè)定時(shí)任務(wù),將DB的數(shù)據(jù)全量dump到Redis做分布式緩存
2. 數(shù)據(jù)源的獲取 我們查詢航班的API采用LRU+實(shí)時(shí)讀取Redis補(bǔ)償緩存
簡(jiǎn)單架構(gòu)圖如下:
下面就到緩存穿透了,對(duì)我的這個(gè)場(chǎng)景來(lái)說(shuō)就是指,LRU緩存未命中,導(dǎo)致大量的請(qǐng)求達(dá)到了Redis上。
目前我使用的最簡(jiǎn)單的方式就是,對(duì)不存在的Key,把Value置為null放到LRU中,來(lái)保護(hù)Redis。補(bǔ)充一句,如果采用的map結(jié)構(gòu)不支持Value為null哪?(我個(gè)人是參考的Spring注冊(cè)單例Bean的方式,生成一個(gè)叫nullObject的Object來(lái)標(biāo)記null對(duì)象)
如果數(shù)據(jù)量再大或QPS更大,參考業(yè)界和查資料,有總結(jié)發(fā)現(xiàn)兩個(gè)更好的方案來(lái)解決:
1.在LRU之前加一個(gè)布隆過(guò)濾器
2.倒排索引,將冷門(mén)數(shù)據(jù)dump到本地文件中
時(shí)間不早要下班撤了,就寫(xiě)這么多,有時(shí)間再總結(jié)分享下我采用的LRU的實(shí)現(xiàn)方式、一致性哈希和布隆過(guò)濾器等等,最主要的是代碼,希望有大牛指點(diǎn)一下不足和更好的思路。
分類: 緩存技術(shù)
延伸閱讀
學(xué)習(xí)是年輕人改變自己的最好方式