快取的使用,是一個逐漸演進的程序,
問一下你自己,最直接的使用快取的原因是什么?
無它,唯快而已!
追溯一下自己最開始使用快取的場景,一些資料庫里存盤的不變的配置資訊,服務啟動時,直接加載到本地公共模塊,方便其它功能模塊共享使用,這便是最基本,最簡單的本地快取應用,
一、服務與快取
所謂的服務,簡而言之,一層應用 + 一層資料,應用從資料層獲取資料然后加工輸出,
資料層,通常我們指的是持久化介質上的持久化存盤,它有多種形式的,可以是檔案,或者資料庫,
資料存盤在持久化介質上,而應用運行與記憶體中,記憶體和持久化介質是兩個有著量級速度差別的不同介質,由此,應用和資料之間便有了“矛盾”,
有了這“矛盾”的引子,便有了對快取的迫切需求,
我們說的快取,必然要是存放于記憶體中的,這樣它便能距離應用更近,更快的給出應用所需要的資料,以獲得更快的服務回應,

當然,并不是快取完全隔絕持久層資料,快取,伴隨而生的一個詞叫做命中率,
當我們查詢的資料存在于快取中的時候,我們稱之為“命中”,此時,所需資料可以直接由快取提供,
而對于未“命中”的資料,則需要穿過快取層,進一步去持久化資料層獲取,此種情景,我們稱之為快取穿透,
資料獲取之后,在回傳給應用之前,我們需要重新填充快取,以供下一次“命中”查詢,
當然,上述我們所述只是指“讀”查詢情景,
當應用發生資料操作變更,我們則需要將變更同時更新到持久層及緩沖層,此時,我們又會面臨另外一個問題,“先”與“后” 的問題,

“先”與“后”的問題,我們也稱之為快取一致性問題,
如果先更新快取,則可能面臨持久層更新失敗,產生快取臟資料的問題,
然則,假如先更新持久層,我們又不得不面對從持久層更新成功之后到快取更新之前這個間期,快取對外提供舊資料的窘境,
快取一致性問題,尤其在高并發環境,需要根據特定場景進行更精妙的控制,
比如,并發修改的一致性鎖;比如,異步重繪的延遲重繪等等,
二、快取與更新
上面我們提到了快取更新一致性的問題,從實際應用情景來講,可以細分為強一致性需求,弱一致性需求及最終一致性需求,
1、強一致性需求
比如,交易狀態資訊,已下單、支付中,已支付等應用,需要我們主動及時進行關聯更新并保證事務層面的一致性,
應景而生的許多包括分布式事務等理論也為我們解決實際問題提供了很好的踐行方案,
2、弱一致性需求
一些涉及不太重要的資訊更新,能夠容忍短時間(比如,幾分鐘)內持久層資料和快取資料不一致的場景,比如不外顯的描述資訊,統計性的計數快取資訊等,通常可以采取異步處理的方式,
一些一段短時間內(幾秒,幾分鐘)輸出固定資訊的場景,比如每隔30s更新熱點資訊,票價資訊等,可以通過設定快取超時自動剔除的方式進行處理,
3、最終一致性需求
保障資料狀態的最終一致性,
三、快取的粒度
所謂粒度,也即快取資訊塊層級,大小,選擇何種粒度的快取,取決于我們應用的整體架構,資料存盤規劃及具體的應用場景,
拿用戶資訊來舉例,是快取活躍資訊?還是相對靜態的資訊?是按單屬性層級來快取?還是按整個物件資訊?
不同的資料粒度,也決定著我們存盤快取的形式:整個物件的二進制序列化資料?更透明直觀的json字串?屬性與值的一一映射?
每種形式都有各自的使用優缺點,開發者可以從應用、存盤及維護成本各方面進行全面性評估選擇,另外,關注公眾號Java技術堆疊,在后臺回復:面試,可以獲取我整理的快取系列面試題和答案,非常齊全,
四、快取穿透的危害
第一小節,我們提到過關于快取穿透發生的原因:快取未命中,那為什么會未命中呢?
1、資料暫時不存在于快取中
所謂暫時,可以指資料初始尚未加載到快取,lazy load 按需按時時事加載應用;
也可以是快取資料被我們特定的快取過期策略自動或主動過期,通常使用的過期策略包括元素數量限制,記憶體占用限制及生存時間限制,

其實,無論是初始未加載還是快取過期,洗掉,這些都屬于我們假定的正常應用場景,再次我們不予過多評論,
2、資料從來不存在
當一個查詢不存在資料的請求到來,其必然會穿過快取,達到持久化存盤層,
持久話存盤的回應能力是有限的,當這種請求達到一定的量級,服務可能就要面臨著宕機的危險,
至此,我們對于快取的作用認知,也需要進一步延伸:降低下層負載,保護后端資源,

造成這種快取穿透的原因可以簡單的分為內外兩方面誘因:內部的應用邏輯問題及外部惡意攻擊、爬蟲干擾等,
內部問題容易解決,內觀可預知,良性優化即可;
反而是外部的不可預料,可能需要更謹慎的進行多面的防御性處理,
其實,不論內部還是外部,在快取層面需要處理的就只有一件事:有效攔截穿透,
到此,通常慣性的思維第一步,就是把造成快取穿透的資料放置到快取中,無論其是否存在在于持久化存盤中,
比如對于正常的已洗掉的用戶資料,做快取層面的軟洗掉處理,以狀態資訊做標注(我存在,其實我不存在! ??),就可以很好的解決此類問題造成的穿透壓力,
但是,我們有也個清楚的認知就,就是真正能夠造成危害的是那些非正常的入侵資料,比如,窮盡遍歷的差別資料,一一存入快取,唯一的結果就是快取資源的溢滿用盡,這是一種相當恐怖的場景,
針對此種“大資料”型攻擊,布隆過濾攔截或許可以成為一個不錯的選擇,

五、也談快取雪崩
上面一節中我們談到了快取的承載保護功能,一面快速回應,一面背負保護持久層資料,
在某些以讀為主的服務中,快取幾近承載近乎90%以上的請求,
但是,如果快取由于某些原因一時不能提供正常服務時,所有的請求就會穿透到持久存盤層,造成存盤層極端宕機情況發生,

那么,我們應該如何應對這種情況呢?
1、高可用
快取的高可用是應對快取雪崩的首要保障:主從,讀寫分離,動態擴容,一致性均衡,異地容災等,
實際應用如Redis的哨兵模式,集群部署等,

2、服務治理之限流、熔斷降級
服務治理的目的是什么?服務的穩定性,
限流即對例外流量的控制;熔斷、降級標的核心服務資源的保護,
筆者在輕量級熔斷降級框架 alibaba sentinel 應用介紹過當下流行的幾種流控框架的使用,
快取、持久化資料存盤都是資源,或者我們可以從對快取的流控及對持久化資料存盤的熔斷、降級保護來著手應對快取雪崩的情景發生,

3、快取元素的集中過期導致快取失效
對于設定了過期時間的快取元素,如果發生元素同時過期,則會有瞬間的外部請求直接到達持久存盤層,
在實際的快取應用中,需要采取一定的措施,實作快取元素過期時間的均勻分布,另外,關注公眾號Java技術堆疊,在后臺回復:面試,可以獲取我整理的快取系列面試題和答案,非常齊全,
作者:WindWant
出處:www.cnblogs.com/niejunlei/p/12914336.html
近期熱文推薦:
1.Java 15 正式發布, 14 個新特性,重繪你的認知!!
2.終于靠開源專案弄到 IntelliJ IDEA 激活碼了,真香!
3.我用 Java 8 寫了一段邏輯,同事直呼看不懂,你試試看,,
4.吊打 Tomcat ,Undertow 性能很炸!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/248854.html
標籤:Java
上一篇:JDK1.7-HashMap原理
