緩存的設(shè)計(jì)方式
問題情況:
當(dāng)有大量的請求到內(nèi)部系統(tǒng)時(shí),若每一個請求都需要我們操作數(shù)據(jù)庫,例如查詢操作,那么對于那種數(shù)據(jù)基本不怎么變動的數(shù)據(jù)來說,每一次都去數(shù)據(jù)庫里面查詢,是很消耗我們的性能
尤其是對于在海量數(shù)據(jù)中進(jìn)行數(shù)據(jù)操作的時(shí)候,如果都是從 DB 中進(jìn)行加載,那這是在挑戰(zhàn)用戶的耐性
簡單來看,例如我們要去小區(qū)里面了解一個人在不在家,當(dāng)沒有通訊工具的前提下,我們每一次都要經(jīng)過小區(qū)們的保安,然后再到具體的單元樓,最終到了這家門口,最終才知道在不在家

如果我們換了一個比較優(yōu)秀的保安,他知道當(dāng)前小區(qū)里面的特定的家里面是否有人,那這個時(shí)候,如果我們直接去問小區(qū)保安,自然就無需跑冤枉路了,自然就提高了效率

此處簡單的就可以將優(yōu)秀保安看做是一個緩存,我們每一次去訪問,就會先去訪問緩存 , 這樣就能極大的提高訪問效率和系統(tǒng)性能
可以看出,有一個優(yōu)秀的保安相當(dāng)重要
緩存的基本設(shè)計(jì)方式是什么樣的
設(shè)計(jì)緩存自然也是為了解決系統(tǒng)是的低效問題,讓系統(tǒng)可以高性能,高并發(fā)
例如我們直接訪問單機(jī)的數(shù)據(jù)庫如mysql 也就是上千級別的 qps,如果是訪問 緩存的時(shí)候,就能達(dá)到上萬,上十幾萬,這差距不是一點(diǎn)半點(diǎn),是一個質(zhì)的飛越
緩存的設(shè)計(jì)實(shí)際上就是 DB 和 緩存操作順序以及誰來操作的事情,大體分為如下 4 種模式
Cache Aside
Read Through
Write Through
Write Behind Caching
上述四種模式, Cache Aside 用的方式是最常使用的,咱們后續(xù)細(xì)說
后續(xù)三種模式的含義是
Read Through
是在查詢操作的時(shí)候更新緩存,若緩存失效了,則是由緩存服務(wù)器自己將數(shù)據(jù)加載到緩存中
Write Through
是在更新數(shù)據(jù)庫的時(shí)候,如果命中了緩存,則先更新緩存,再由緩存服務(wù)器自己去更新數(shù)據(jù),
如果是沒有命中緩存,那么就直接更新數(shù)據(jù)庫
Write Behind Caching 通過名字我們知道,是在寫到緩存操作之后才做些操作,實(shí)際上這種模式只更新緩存,不會更新數(shù)據(jù)庫,緩存服務(wù)器會以異步的方式將數(shù)據(jù)批量更新到數(shù)據(jù)庫中
很明顯,這種,模式速度自然會更快,可這種模式對于保證數(shù)據(jù)庫和緩存數(shù)據(jù)一致性問題,是個硬傷,且還會存在丟數(shù)據(jù)的情況,比如,咱們的緩存服務(wù)器掛掉了
Cache Aside 讀寫緩存模式是怎么玩的
Cache Aside 讀寫模式緩存又是如何去處理的呢,一起來看看
Cache Aside 模式讀取數(shù)據(jù)的邏輯是這個樣子的:
讀取數(shù)據(jù)時(shí)
先讀取緩存中的數(shù)據(jù),如果緩存中有數(shù)據(jù),則直接返回
若緩存中沒有數(shù)據(jù),則去讀數(shù)據(jù)庫中的數(shù)據(jù),并將數(shù)據(jù)同步到緩存中

寫入數(shù)據(jù)時(shí)
寫入數(shù)據(jù)庫,寫入成功時(shí),將緩存的數(shù)據(jù)刪除掉

仔細(xì)的同學(xué)可能會思考并提出這樣的問題,如果我一個查詢操作,現(xiàn)在緩存中無數(shù)據(jù),此時(shí)會去數(shù)據(jù)庫中查詢,在這個過程中,另外有一個寫入數(shù)據(jù)庫的操作,且操作完畢后,刪除了緩存,這個時(shí)候,第一個操作實(shí)際上從數(shù)據(jù)庫拿到的還是之前的老數(shù)據(jù),并且會將數(shù)據(jù)放到緩存中,那么此時(shí)的數(shù)據(jù)實(shí)際上是一個老數(shù)據(jù),也可以理解是在臟數(shù)據(jù)
這個點(diǎn)其實(shí)我們就無需擔(dān)心了,大佬們已經(jīng)論證過這種情況出現(xiàn)的概率極低
因?yàn)樵蹅兊膶懕聿僮魇且i表的,且我們知道數(shù)據(jù)庫寫入操作比讀取操作要慢,也就是說,當(dāng)同時(shí)有一個讀取和寫入 DB 的操作時(shí),自然是寫入的操作是要后返回結(jié)果的,此處不要杠啥讀寫數(shù)據(jù)量不一致的情況,咱們做對比,自然是在同等條件下比較咯

從圖中我們知道,同等條件下,先進(jìn)行查詢 DB 的操作,過程中,來了一個寫入 DB 操作,自然是 查詢操作先返回,寫入操作再返回結(jié)果
其實(shí)此處,有的做法是,寫入數(shù)據(jù)的時(shí)候,寫入成功,同時(shí)也會將數(shù)據(jù)同步到緩存中
那么這種方式的引入,實(shí)際上從數(shù)據(jù)庫到緩存就有了 2 種情況了,一個是查詢操作,一個是寫入操作,那么在實(shí)際操作中,我是可以加入分布式鎖來進(jìn)行處理,保證寫入數(shù)據(jù)庫的時(shí)候,同時(shí)也要寫入緩存,數(shù)據(jù)才可訪問,當(dāng)然查詢 DB 操作也是一樣
緩存帶來了哪些問題?
那么引入緩存除了可以帶來高性能,高并發(fā),自然也是有會帶來一些問題的,例如:
緩存擊穿
緩存穿透
緩存雪崩
如上 3 中情況,都是由于緩存這一層防線失守了,導(dǎo)致外部請求以各種各樣的形式,各種各樣的原因打到了數(shù)據(jù)庫上,導(dǎo)致出現(xiàn)的問題,詳細(xì)的 緩存擊穿,緩存穿透,緩存雪崩的出現(xiàn)情況,解決方式可以查看歷史文章 redis 緩存穿透,緩存擊穿,緩存雪崩
感謝閱讀,歡迎交流,點(diǎn)個贊,關(guān)注一波 再走吧