分布式緩存是網(wǎng)站服務(wù)端經(jīng)常用到的一種技術(shù),在讀多寫少的業(yè)務(wù)場景中,通過使用緩存可以有效地支撐高并發(fā)的訪問量,對(duì)后端的數(shù)據(jù)庫等數(shù)據(jù)源做到很好地保護(hù)?,F(xiàn)在市面上有很多分布式緩存,比如Redis、Memcached以及阿里的Tair等,不管我們使用的哪種緩存產(chǎn)品,基本上都會(huì)遇到緩存擊穿、緩存失效以及熱點(diǎn)key的問題。如何有效地防止這些問題,也是我們在享受緩存帶來的紅利地同時(shí),必須要解決地難題。
通常我們在使用緩存時(shí)候都是先檢查緩存中是否存在,如果存在直接返回緩存內(nèi)容,如果不存在就直接查詢數(shù)據(jù)庫然后再緩存查詢結(jié)果返回
緩存擊穿:
描述
查詢一個(gè)數(shù)據(jù)庫中不存在的數(shù)據(jù),比如商品詳情,查詢一個(gè)不存在的ID,每次都會(huì)訪問DB,如果有人惡意破壞,很可能直接對(duì)DB造成過大地壓力。
解決方案:
當(dāng)通過某一個(gè)key去查詢數(shù)據(jù)的時(shí)候,如果對(duì)應(yīng)在數(shù)據(jù)庫中的數(shù)據(jù)都不存在,我們將此key對(duì)應(yīng)的value設(shè)置為一個(gè)默認(rèn)的值,比如“NULL”,并設(shè)置一個(gè)緩存的失效時(shí)間,這時(shí)在緩存失效之前,所有通過此key的訪問都被緩存擋住了。后面如果此key對(duì)應(yīng)的數(shù)據(jù)在DB中存在時(shí),緩存失效之后,通過此key再去訪問數(shù)據(jù),就能拿到新的value了。
緩存失效:
描述
在高并發(fā)的環(huán)境下,如果此時(shí)key對(duì)應(yīng)的緩存失效,此時(shí)有多個(gè)進(jìn)程就會(huì)去同時(shí)去查詢DB,然后再去同時(shí)設(shè)置緩存。這個(gè)時(shí)候如果這個(gè)key是系統(tǒng)中的熱點(diǎn)key或者同時(shí)失效的數(shù)量比較多時(shí),DB訪問量會(huì)瞬間增大,造成過大的壓力。
解決方案:
將系統(tǒng)中key的緩存失效時(shí)間均勻地錯(cuò)開,防止統(tǒng)一時(shí)間點(diǎn)有大量的key對(duì)應(yīng)的緩存失效;
重新設(shè)計(jì)緩存的使用方式,當(dāng)我們通過key去查詢數(shù)據(jù)時(shí),首先查詢緩存,如果此時(shí)緩存中查詢不到,就通過分布式鎖進(jìn)行加鎖,取得鎖的進(jìn)程查DB并設(shè)置緩存,然后解鎖;其他進(jìn)程如果發(fā)現(xiàn)有鎖就等待,然后等解鎖后返回緩存數(shù)據(jù)或者再次查詢DB。
熱點(diǎn)key:
描述
緩存中的某些Key(可能對(duì)應(yīng)用與某個(gè)促銷商品)對(duì)應(yīng)的value存儲(chǔ)在集群中一臺(tái)機(jī)器,使得所有流量涌向同一機(jī)器,成為系統(tǒng)的瓶頸,該問題的挑戰(zhàn)在于它無法通過增加機(jī)器容量來解決。
解決方案:
客戶端熱點(diǎn)key緩存:將熱點(diǎn)key對(duì)應(yīng)value并緩存在客戶端本地,并且設(shè)置一個(gè)失效時(shí)間。對(duì)于每次讀請求,將首先檢查key是否存在于本地緩存中,如果存在則直接返回,如果不存在再去訪問分布式緩存的機(jī)器。
將熱點(diǎn)key分散為多個(gè)子key,然后存儲(chǔ)到緩存集群的不同機(jī)器上,這些子key對(duì)應(yīng)的value都和熱點(diǎn)key是一樣的。當(dāng)通過熱點(diǎn)key去查詢數(shù)據(jù)時(shí),通過某種hash算法隨機(jī)選擇一個(gè)子key,然后再去訪問緩存機(jī)器,將熱點(diǎn)分散到了多個(gè)子key上。