缓存级别与缓存更新问题
緩存失效問(wèn)題被認(rèn)為是計(jì)算機(jī)科學(xué)中最難的兩件事之一,這篇文章來(lái)自翻譯,內(nèi)容主要包括緩存級(jí)別與緩存更新常見(jiàn)的幾種模式。
緩存應(yīng)用模式
常見(jiàn)緩存應(yīng)用模式
緩存常用來(lái)加快頁(yè)面的加載速度,減少服務(wù)器或數(shù)據(jù)庫(kù)服務(wù)的負(fù)載。緩存應(yīng)用的常見(jiàn)模式如上圖所示:
數(shù)據(jù)庫(kù)常常得益于對(duì)均勻分布的數(shù)據(jù)的讀寫(xiě),但是熱點(diǎn)數(shù)據(jù)使得這種均勻被打破,從而出現(xiàn)了系統(tǒng)瓶頸。通過(guò)數(shù)據(jù)庫(kù)服務(wù)前置緩存服務(wù),可以有效吸收不均勻的負(fù)載和抵擋流量高峰。
緩存級(jí)別
緩存級(jí)別關(guān)注的問(wèn)題是在什么時(shí)候做緩存(When)以及在什么地方做緩存(Where),下面介紹幾種常見(jiàn)的緩存級(jí)別。
客戶端緩存
緩存可以存儲(chǔ)在客戶端(操作系統(tǒng)或?yàn)g覽器、服務(wù)端、或者是獨(dú)立的緩存系統(tǒng)中。
CDN緩存
CDN也可以被認(rèn)為是一種緩存。
Web服務(wù)器緩存
反向代理或者像Varnish這樣的緩存服務(wù)可以直接保存靜態(tài)的或動(dòng)態(tài)的緩存內(nèi)容。Web服務(wù)器也可以緩存請(qǐng)求直接響應(yīng)客戶端從而避免請(qǐng)求再次觸達(dá)應(yīng)用。
數(shù)據(jù)庫(kù)緩存
我們的數(shù)據(jù)庫(kù)服務(wù)在默認(rèn)的配置或者稍微針對(duì)通用場(chǎng)景進(jìn)行優(yōu)化的情況下通常包含不同級(jí)別的緩存,針對(duì)特定的使用場(chǎng)景進(jìn)行適當(dāng)?shù)恼{(diào)整可以進(jìn)一步提高性能。
應(yīng)用緩存
像Memcached和Redis這種內(nèi)存key-value緩存服務(wù),通常是置于應(yīng)用和數(shù)據(jù)庫(kù)服務(wù)之間,因?yàn)閿?shù)據(jù)存儲(chǔ)在內(nèi)存中,因此這要比將數(shù)據(jù)存儲(chǔ)在磁盤(pán)的數(shù)據(jù)庫(kù)要快的多。但是內(nèi)存與磁盤(pán)相比往往受限于空間,因此類(lèi)似LRU(Least Recently Used)這種緩存淘汰算法應(yīng)運(yùn)而生,他們將相對(duì)較少訪問(wèn)的”冷”數(shù)據(jù)從內(nèi)存置換出來(lái)將訪問(wèn)頻率較高的“熱”數(shù)據(jù)放入內(nèi)存(將內(nèi)存的使用價(jià)值最大化,譯者注)。
Redis還有很多其他的功能,包括:
- 持久化選項(xiàng);
- 內(nèi)建數(shù)據(jù)結(jié)構(gòu)(如sets、lists);
下面是針對(duì)數(shù)據(jù)庫(kù)查詢級(jí)別和對(duì)象級(jí)別的一般緩存:
- 行級(jí)緩存;
- 查詢級(jí)別緩存;
- 完全序列化的緩存;
- 渲染后的HTML緩存;
值得一提的是,我們通常要避免文件級(jí)別的緩存,因?yàn)榛谖募木彺娉3ky于擴(kuò)展和維護(hù)。
查詢級(jí)別緩存:
每當(dāng)我們查詢數(shù)據(jù)庫(kù)的時(shí)候,將查詢(比如SQL)進(jìn)行hash并作為key和查詢結(jié)果關(guān)聯(lián)存儲(chǔ),這種方法會(huì)遇到緩存過(guò)期的問(wèn)題:
- 對(duì)于復(fù)雜的查詢很難刪除緩存的結(jié)果;
- 緩存粒度較大,如果查詢結(jié)果中只有丁點(diǎn)數(shù)據(jù)被更新,則整個(gè)查詢都要過(guò)期;
對(duì)象級(jí)別緩存:
對(duì)象級(jí)別緩存是將數(shù)據(jù)看做對(duì)象:
- 如果數(shù)據(jù)被修改則將數(shù)據(jù)從緩存中移除;
- 使用異步的任務(wù)來(lái)更新緩存;
對(duì)象級(jí)別的緩存建議的使用場(chǎng)景:
- 用戶會(huì)話;
- 渲染后的頁(yè)面;
- 活動(dòng)流;
- 用戶圖形數(shù)據(jù);
緩存更新問(wèn)題
因?yàn)閮?nèi)存受限于空間緩存只能存儲(chǔ)有限的數(shù)據(jù),因此我們需要決定在我們的應(yīng)用場(chǎng)景中,使用何種緩存更新策略,下面介紹幾種常見(jiàn)的模式。
Cache-Aside
Cache-Aside模式
應(yīng)用負(fù)責(zé)基于存儲(chǔ)讀寫(xiě)數(shù)據(jù),緩存不直接和存儲(chǔ)打交道,應(yīng)用的行為如下:
代碼示例如下:
| 1 2 3 4 5 6 7 | def get_user(self, user_id): ????user = cache.get("user.{0}", user_id) ????if user is None: ????????user = db.query("SELECT * FROM users WHERE user_id = {0}", user_id) ????????if user is not None: ????????????cache.set(key, json.dumps(user)) ????return user |
這種模式的缺點(diǎn)如下:Memcached通常被應(yīng)用于這種方式,這種模式對(duì)于接下來(lái)的數(shù)據(jù)讀取將非???#xff0c;Cache-Aside也叫做延遲加載,只有需要的數(shù)據(jù)被緩存,避免不需要的數(shù)據(jù)占用緩存空間。
- 每次緩存沒(méi)命中都增加系統(tǒng)之間的交互,這將會(huì)增加響應(yīng)延遲;
- 當(dāng)對(duì)應(yīng)數(shù)據(jù)庫(kù)中的數(shù)據(jù)被更新之后將出現(xiàn)臟數(shù)據(jù)問(wèn)題,這個(gè)問(wèn)題可以通過(guò)設(shè)置過(guò)期時(shí)間(TTL)來(lái)緩解,當(dāng)時(shí)間過(guò)期將發(fā)生強(qiáng)制更新緩存;
- 當(dāng)一個(gè)節(jié)點(diǎn)壞了之后,新的節(jié)點(diǎn)代替舊的節(jié)點(diǎn),這個(gè)時(shí)候?qū)⒊霈F(xiàn)大量的緩存穿透問(wèn)題;
Write-Though
Write-Though模式
應(yīng)用將緩存作為主要存儲(chǔ),讀寫(xiě)都直接和緩存打交道,緩存負(fù)責(zé)基于存儲(chǔ)進(jìn)行讀寫(xiě):
應(yīng)用代碼示例:
| 1 | set_user(12345, {"foo":"bar"}) |
緩存代碼如下:
| 1 2 3 | def set_user(user_id, values): ????user = db.query("UPDATE Users WHERE id = {0}", user_id, values) ????cache.set(user_id, user) |
Write-Though對(duì)于所有的寫(xiě)操作都是比較慢的,但是對(duì)于讀來(lái)說(shuō)很快,用戶通常需要容忍寫(xiě)延遲,但是不會(huì)出現(xiàn)臟數(shù)據(jù)。
這種模式的缺點(diǎn)如下:
- 由于failure或者scaling帶來(lái)的新增節(jié)點(diǎn)的時(shí)候,新增節(jié)點(diǎn)在下次更新數(shù)據(jù)之前將沒(méi)有數(shù)據(jù),這個(gè)問(wèn)題可以結(jié)合Cache-Aside模式來(lái)緩解;
- 對(duì)于很多寫(xiě)入的數(shù)據(jù)將永遠(yuǎn)不會(huì)讀取到,這個(gè)問(wèn)題可以通過(guò)設(shè)置過(guò)期時(shí)間解決;
Write-Behind(Write-Back)
Write-Behind模式
在這種模式下,應(yīng)用的行為如:
這種模式的缺點(diǎn)如下:
- 如果在數(shù)據(jù)被更新到存儲(chǔ)之前緩存掛了,則數(shù)據(jù)將會(huì)丟失;
- 實(shí)現(xiàn)起來(lái)比Write-Though和Cache-Aside模式更為復(fù)雜;
Refresh-Ahead
Refresh-Ahead模式
我們可以配置緩存自動(dòng)在最近訪問(wèn)的數(shù)據(jù)過(guò)期之前更新它們,如果可以準(zhǔn)確預(yù)測(cè)將要訪問(wèn)的數(shù)據(jù),Refresh-Ahead模式可以有效地減少讀寫(xiě)的延遲。
這種模式的缺點(diǎn)如下:
- 如果預(yù)測(cè)數(shù)據(jù)不準(zhǔn)確,則比不做什么更有損性能;
緩存的缺點(diǎn)
一種解決方案通常會(huì)帶來(lái)一些問(wèn)題,我們來(lái)看看引入緩存帶來(lái)的問(wèn)題:
- 緩存的引入帶來(lái)了一致性問(wèn)題,我們需要處理緩存中的數(shù)據(jù)與原數(shù)據(jù)不一致的問(wèn)題;
- 緩存的引入增加了軟件架構(gòu)的復(fù)雜性;;
- 緩存過(guò)期是個(gè)難題,這個(gè)問(wèn)題主要體現(xiàn)在何時(shí)更新緩存上;
擴(kuò)展閱讀
- From cache to in-memory data grid
- Scalable system design patterns
- Introduction to architecting systems for scale
- Scalability, availability, stability, patterns
- Scalability
- AWS ElastiCache strategies
- Wikipedia
from:?http://www.importnew.com/23967.html
總結(jié)
以上是生活随笔為你收集整理的缓存级别与缓存更新问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: HTTPS协议原理分析
- 下一篇: 玩转Eclipse — 自动生成sett