高并發(fā)下的緩存風險點和使用
緩存是為了提高應用服務的響應時間。是一種空間換時間典型應用力九。
1.一個緩存只干一件事。
2.確保組裝redis的key與將要緩存的數(shù)據(jù)的查詢條件一致。
在網(wǎng)關使用reids的流程是先查緩存亭螟,緩存不存在残家,則RPC或者操作數(shù)據(jù)庫榆俺,取回數(shù)據(jù),再放入緩存坞淮。
緩存的key與查詢數(shù)據(jù)條件不一致茴晋,緩存不僅一點意義沒有,還會導致臟數(shù)據(jù)回窘,產(chǎn)生一些莫名奇妙的bug诺擅。
1.緩存種類
1.Jdk自帶
????線程不安全HashMap,LinkedHashMap,LRUMap
線程安全ConcurrentHashMap,CopyOnWriteList,CopyOnWriteSet
2.第三方包
Gauva 線程安全,自帶過期檢查啡直,自帶更新烁涌。
Ehcache 可落地苍碟,重啟數(shù)據(jù)可保留,hibernate中使用撮执。
3.第三方服務
Redis 目前使用中微峰。多種數(shù)據(jù)結構∈闱可落地蜓肆。
Memcache 數(shù)據(jù)結構單一,只有key string谋币。不可落地仗扬。
2.目前使用情況
1.序列化為JSON。
簡單易用蕾额,速度快早芭,純業(yè)務信息。
100W次
序列化 382 279
反序列化用時 282 292
2.將對象序列化為二進制字節(jié)數(shù)據(jù)诅蝶。
轉(zhuǎn)化萬物退个,包括類信息占用內(nèi)存多,耗時較多
100W次
序列化 2376 2544
反序列化用時 11352 11411
對明確第三方服務有緩存的情況下秤涩,網(wǎng)關可以不加緩存帜乞。
如果第三方有緩存,網(wǎng)關也加緩存筐眷,不僅增加工作量黎烈,還會增加代碼邏輯,增大出錯機率匀谣。比如照棋。。武翎。烈炭。
網(wǎng)關調(diào)用一次第三方有緩存的rpc,會經(jīng)過以下幾個步驟:
1.網(wǎng)關序列化宝恶。
2.網(wǎng)絡傳輸符隙。
3.第三方服務反序列化請求參數(shù)。
4.第三方讀緩存垫毙,分二種情況
jvm,純內(nèi)存操作霹疫,耗時可以忽略不計。
redis,會有一次網(wǎng)絡傳輸综芥。
5.第三方序列化請求結果丽蝎。
6.網(wǎng)絡傳輸。
7.網(wǎng)關反序列化請求結果膀藐。
整個流程耗時在2-5ms屠阻,接口性能非常優(yōu)秀红省。
3.高并發(fā)
1.?JVM
HashMap LinkedHashMap純讀可以使用。
LRUMap 最近最少淘汰国觉,可以自定義大小吧恃。
ConcurrentHashMap 多讀多寫多線程。
CopyOnWriteList,CopyOnWriteSet 讀多寫少多線程麻诀,寫時會加鎖復制原有數(shù)組蚜枢,性 能較差。
Guava 同ConcurrentHashMap 针饥,自帶刷新,過期時間需频,自動加載丁眼。網(wǎng)關現(xiàn)在在用。
EhCache 功能強大昭殉,支持落地苞七。
2.?Redis
Redis是單線程,異步非阻塞 IO挪丢,多路復用模式蹂风,純內(nèi)存操作的外部緩存。
所謂的單線程指的是網(wǎng)絡請求模塊使用了一個線程(所以不需考慮并發(fā)安全性)乾蓬,即一個線程處理所有網(wǎng)絡請求惠啄,其他模塊仍用了多個線程。
redis采用多路復用機制:即多個網(wǎng)絡socket復用一個io線程任内,實際是單個線程通過記錄跟蹤每一個Sock(I/O流)的狀態(tài)來同時管理多個I/O流.?
所以撵渡,我認為用redis作緩存與JVM緩存耗時上,主要是序列化與反序列化以及內(nèi)部網(wǎng)絡傳輸上的消耗死嗦。
緩存穿透:
可以防止對惡意攻擊趋距。
后端沒有的數(shù)據(jù),緩存中自然沒有越除。supplierId=-1,suId=-1
1.?布隆過濾器节腐,維護一個大map,空間換安全摘盆,從而避免了對底層存儲系統(tǒng)的查詢壓力翼雀。(沒用過)
2.?自定義規(guī)則,比如在網(wǎng)關對suId進行校驗骡澈,spuId+XXXXXXXX,長度不夠锅纺,自然 就是無效key。
2.如果某個key返回的數(shù)據(jù)為空肋殴,仍然緩存key囤锉,設置比較短的過期時間坦弟,比如10 秒,20秒官地。網(wǎng)關現(xiàn)在使用這種方式酿傍,但不是所有的緩存都有這個邏輯。
緩存擊穿
主要保護下游戲系統(tǒng)驱入,數(shù)據(jù)庫赤炒,第三方服務。
緩存過期一瞬間亏较,大量請求過來莺褒,都去請求后端服務。比如某個排行榜雪情。
有并發(fā)遵岩,但不高,比如幾十次巡通。就是多幾十次后端查詢尘执,多set幾十次值。
如果并發(fā)很高宴凉,后端服務就完蛋了誊锭。
1.代碼加鎖,單服應用可以弥锄,多服依然可能會產(chǎn)生<N-1(應用實例數(shù))次后端請求丧靡。
2.setnx加鎖,獲得鎖的請求去后端請求數(shù)據(jù)籽暇,然后放入redis窘行。切記這個鎖一定要 加過期時間。
緩存雪崩
主要保護下游戲系統(tǒng)图仓,數(shù)據(jù)庫罐盔,第三方服務。
一組業(yè)務關聯(lián)的緩存同一時間失效救崔。比如suid緩存與suppliderId緩存惶看。
預熱緩存,定時刷新緩存六孵。比如UserInfo纬黎,SupplierInfo,ProductInfo劫窒。
1.多級緩存本今,jvm緩存 + redis,jvm緩存+rpc(這是另一種實現(xiàn)和redis無關)。
2.過期時間+隨機增量冠息,比如5分鐘失效挪凑,5*60 + random(0,60),主要思想還是把請 求分散逛艰,有點像請求限流+限流預熱