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