【缓存】数据库缓存
1.定義
關(guān)系型數(shù)據(jù)庫(kù)的數(shù)據(jù)都存儲(chǔ)在磁盤(pán)中,在高并發(fā)情況下,業(yè)務(wù)應(yīng)用的查詢會(huì)對(duì)關(guān)系型數(shù)據(jù)庫(kù)產(chǎn)生的巨大 I/O 開(kāi)銷,為了最大程度的降低對(duì)數(shù)據(jù)庫(kù)服務(wù)器的訪問(wèn)壓力,提出了數(shù)據(jù)庫(kù)緩存的概念。
2.優(yōu)點(diǎn)
2.1.性能優(yōu)越
數(shù)據(jù)庫(kù)緩存的數(shù)據(jù)基本上都是存儲(chǔ)在內(nèi)存中,相比磁盤(pán) I/O ,讀寫(xiě)的速度快,極大緩解了數(shù)據(jù)庫(kù)服務(wù)器的壓力。
2.2.響應(yīng)速度
數(shù)據(jù)庫(kù)緩存技術(shù)應(yīng)用場(chǎng)景絕大部分針對(duì)的是查的場(chǎng)景。因?yàn)樵诔R?jiàn)的應(yīng)用中,數(shù)據(jù)庫(kù)層的壓力有80%的是查詢,20%的才是數(shù)據(jù)的變更操作。所以絕大部分的應(yīng)用場(chǎng)景的還是查緩存。數(shù)據(jù)庫(kù)緩存的使用,提高應(yīng)用的響應(yīng)速度,提升了用戶體驗(yàn)。
3.緩存策略
當(dāng)一個(gè)數(shù)據(jù)發(fā)生變更的時(shí)候,應(yīng)考慮怎么樣確保緩存數(shù)據(jù)和數(shù)據(jù)庫(kù)中數(shù)據(jù)保存一致性,以確保從緩存讀取的數(shù)據(jù)是最新的。
3.1.寫(xiě)回策略
Write Back 策略,特別適合寫(xiě)多的場(chǎng)景。
在更新數(shù)據(jù)的時(shí)候,只更新緩存,同時(shí)將緩存數(shù)據(jù)設(shè)置為臟的,然后立馬返回,并不會(huì)更新數(shù)據(jù)庫(kù)。對(duì)于數(shù)據(jù)庫(kù)的更新,會(huì)通過(guò)批量異步更新的方式進(jìn)行。
3.2.讀穿策略
Read Through 策略,先查詢緩存中數(shù)據(jù)是否存在,如果存在則直接返回,如果不存在,則由緩存服務(wù)負(fù)責(zé)從數(shù)據(jù)庫(kù)查詢數(shù)據(jù),并將結(jié)果寫(xiě)入到服務(wù),最后緩存組件將數(shù)據(jù)返回給應(yīng)用。
3.3.寫(xiě)穿策略
Write Through 策略,先查詢緩存中數(shù)據(jù)是否存在,如果緩存中數(shù)據(jù)已經(jīng)存在,則更新緩存中的數(shù)據(jù),并且由緩存服務(wù)同步更新到數(shù)據(jù)庫(kù)中,然后緩存服務(wù)告知應(yīng)用程序更新完成;如果緩存中數(shù)據(jù)不存在,直接更新數(shù)據(jù)庫(kù),然后返回。
3.4.旁路緩存策略
Cache Aside策略,是最常用的策略。適合讀多寫(xiě)少的場(chǎng)景,不適合寫(xiě)多的場(chǎng)景。
寫(xiě)策略的步驟:先更新數(shù)據(jù)庫(kù)中的數(shù)據(jù),再刪除緩存中的數(shù)據(jù)。
讀策略的步驟:如果讀取的數(shù)據(jù)命中了緩存,則直接返回?cái)?shù)據(jù);如果讀取的數(shù)據(jù)沒(méi)有命中緩存,則從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),然后將數(shù)據(jù)寫(xiě)入到緩存,并且返回給用戶。
4.常見(jiàn)問(wèn)題
4.1.緩存穿透
指訪問(wèn)一個(gè)緩存和數(shù)據(jù)庫(kù)中都不存在的 key,由于這個(gè) key 在緩存中不存在,則會(huì)到數(shù)據(jù)庫(kù)中查詢,數(shù)據(jù)庫(kù)中也不存在該 key,無(wú)法將數(shù)據(jù)添加到緩存中。
解決辦法有:
- 將空 key 添加到緩存中;
- 過(guò)濾空 key;
- 對(duì)請(qǐng)求進(jìn)行身份鑒權(quán)、數(shù)據(jù)合法性校驗(yàn)等。
4.2.緩存擊穿
指大量請(qǐng)求訪問(wèn)緩存中的一個(gè) key 時(shí),該 key 過(guò)期導(dǎo)致這些請(qǐng)求都去直接訪問(wèn)數(shù)據(jù)庫(kù),短時(shí)間大量的請(qǐng)求可能會(huì)將數(shù)據(jù)庫(kù)擊垮。
解決辦法有:
- 添加互斥鎖或分布式鎖,總之讓一個(gè)線程去訪問(wèn)數(shù)據(jù)庫(kù),將數(shù)據(jù)添加到緩存中后,其他線程直接從緩存中獲取;
- 熱點(diǎn)數(shù)據(jù) key 不過(guò)期,定時(shí)更新緩存,但如果更新出問(wèn)題會(huì)導(dǎo)致緩存中的數(shù)據(jù)一直為舊數(shù)據(jù)。
4.3.緩存雪崩
指在系統(tǒng)運(yùn)行過(guò)程中,緩存服務(wù)宕機(jī)或大量的 key 值同時(shí)過(guò)期,導(dǎo)致所有請(qǐng)求都直接訪問(wèn)數(shù)據(jù)庫(kù)導(dǎo)致數(shù)據(jù)庫(kù)壓力增大。
解決方法有:
- 將 key 的過(guò)期時(shí)間打散,避免大量 key 同時(shí)過(guò)期;
- 對(duì)緩存服務(wù)做高可用處理;
- 加互斥鎖,同一 key 值只允許一個(gè)線程去訪問(wèn)數(shù)據(jù)庫(kù),其余線程等待寫(xiě)入后直接從緩存中獲取。
5.緩存預(yù)熱
緩存預(yù)熱是指系統(tǒng)上線后,提前將相關(guān)的緩存數(shù)據(jù)加載到數(shù)據(jù)庫(kù)緩存中。避免在用戶請(qǐng)求的時(shí)候先查詢數(shù)據(jù)庫(kù),然后再將數(shù)據(jù)緩存的問(wèn)題,用戶直接查詢事先被預(yù)熱的緩存數(shù)據(jù)。如果不進(jìn)行預(yù)熱,那么緩存初始狀態(tài)數(shù)據(jù)為空,對(duì)于高并發(fā)的流量都會(huì)訪問(wèn)到數(shù)據(jù)庫(kù)中,對(duì)數(shù)據(jù)庫(kù)造成流量的壓力。
解決方法為:
工程啟動(dòng)的時(shí)候進(jìn)行加載緩存動(dòng)作,數(shù)據(jù)量大的時(shí)候,設(shè)置一個(gè)定時(shí)任務(wù)腳本,進(jìn)行緩存的刷新;數(shù)據(jù)量太大的時(shí)候,優(yōu)先保證熱點(diǎn)數(shù)據(jù)進(jìn)行提前加載到緩存。
總結(jié)
- 上一篇: 《软件过程管理》 第二章 软件过程成熟
- 下一篇: Django构建数据库缓存