更新時(shí)間:2023年05月15日11時(shí)29分 來源:傳智教育 瀏覽次數(shù):
緩存穿透是指查詢一個(gè)一定不存在的數(shù)據(jù),如果從存儲(chǔ)層查不到數(shù)據(jù)則不寫入緩存,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到 DB 去查詢,可能導(dǎo)致 DB 掛掉。這種情況大概率是遭到了攻擊。
通常都會(huì)用布隆過濾器來解決它,
布隆過濾器主要是用于檢索一個(gè)元素是否在一個(gè)集合中。我們當(dāng)時(shí)使用的是redisson實(shí)現(xiàn)的布隆過濾器。
它的底層主要是先去初始化一個(gè)比較大數(shù)組,里面存放的二進(jìn)制0或1。在一開始都是0,當(dāng)一個(gè)key來了之后經(jīng)過3次hash計(jì)算,模于數(shù)組長度找到數(shù)據(jù)的下標(biāo)然后把數(shù)組中原來的0改為1,這樣的話,三個(gè)數(shù)組的位置就能標(biāo)明一個(gè)key的存在。查找的過程也是一樣的。
當(dāng)然是有缺點(diǎn)的,布隆過濾器有可能會(huì)產(chǎn)生一定的誤判,我們一般可以設(shè)置這個(gè)誤判率,大概不會(huì)超過5%,其實(shí)這個(gè)誤判是必然存在的,要不就得增加數(shù)組的長度,其實(shí)已經(jīng)算是很劃分了,5%以內(nèi)的誤判率一般的項(xiàng)目也能接受,不至于高并發(fā)下壓倒數(shù)據(jù)庫。
緩存擊穿的意思是對(duì)于設(shè)置了過期時(shí)間的key,緩存在某個(gè)時(shí)間點(diǎn)過期的時(shí)候,恰好這時(shí)間點(diǎn)對(duì)這個(gè)Key有大量的并發(fā)請(qǐng)求過來,這些請(qǐng)求發(fā)現(xiàn)緩存過期一般都會(huì)從后端 DB 加載數(shù)據(jù)并回設(shè)到緩存,這個(gè)時(shí)候大并發(fā)的請(qǐng)求可能會(huì)瞬間把 DB 壓垮。
解決方案有兩種方式:
第一可以使用互斥鎖:當(dāng)緩存失效時(shí),不立即去load db,先使用如 Redis 的 setnx 去設(shè)置一個(gè)互斥鎖,當(dāng)操作成功返回時(shí)再進(jìn)行 load db的操作并回設(shè)緩存,否則重試get緩存的方法。
第二種方案可以設(shè)置當(dāng)前key邏輯過期,大概是思路如下:
①:在設(shè)置key的時(shí)候,設(shè)置一個(gè)過期時(shí)間字段一塊存入緩存中,不給當(dāng)前key設(shè)置過期時(shí)間
②:當(dāng)查詢的時(shí)候,從redis取出數(shù)據(jù)后判斷時(shí)間是否過期
③:如果過期則開通另外一個(gè)線程進(jìn)行數(shù)據(jù)同步,當(dāng)前線程正常返回?cái)?shù)據(jù),這個(gè)數(shù)據(jù)不是最新
當(dāng)然兩種方案各有利弊:
如果選擇數(shù)據(jù)的強(qiáng)一致性,建議使用分布式鎖的方案,性能上可能沒那么高,鎖需要等,也有可能產(chǎn)生死鎖的問題如果選擇key的邏輯刪除,則優(yōu)先考慮的高可用性,性能比較高,但是數(shù)據(jù)同步這塊做不到強(qiáng)一致。
北京校區(qū)