日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

缓存架构设计细节二三事

發(fā)布時(shí)間:2025/7/25 64 豆豆
生活随笔 收集整理的這篇文章主要介紹了 缓存架构设计细节二三事 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

緩存架構(gòu)設(shè)計(jì)細(xì)節(jié)二三事

?2016-03-08?58沈劍?架構(gòu)師之路

本文主要討論這么幾個(gè)問(wèn)題:

1)“緩存與數(shù)據(jù)庫(kù)”需求緣起

2)“淘汰緩存”還是“更新緩存”

3)緩存和數(shù)據(jù)庫(kù)的操作時(shí)序

4)緩存和數(shù)據(jù)庫(kù)架構(gòu)簡(jiǎn)析

?

一、需求緣起

場(chǎng)景介紹

緩存是一種提高系統(tǒng)讀性能的常見(jiàn)技術(shù),對(duì)于讀多寫(xiě)少的應(yīng)用場(chǎng)景,我們經(jīng)常使用緩存來(lái)進(jìn)行優(yōu)化。

例如對(duì)于用戶的余額信息表account(uid, money),業(yè)務(wù)上的需求是:

1)查詢用戶的余額,SELECT money FROM account WHERE uid=XXX,占99%的請(qǐng)求

2)更改用戶余額,UPDATE account SET money=XXX WHERE uid=XXX,占1%的請(qǐng)求


由于大部分的請(qǐng)求是查詢,我們?cè)诰彺嬷薪?/span>uidmoney的鍵值對(duì),能夠極大降低數(shù)據(jù)庫(kù)的壓力。

?

讀操作流程

有了數(shù)據(jù)庫(kù)和緩存兩個(gè)地方存放數(shù)據(jù)之后(uid->money),每當(dāng)需要讀取相關(guān)數(shù)據(jù)時(shí)(money),操作流程一般是這樣的:

1)讀取緩存中是否有相關(guān)數(shù)據(jù),uid->money

2)如果緩存中有相關(guān)數(shù)據(jù)money,則返回【這就是所謂的數(shù)據(jù)命中hit”】

3)如果緩存中沒(méi)有相關(guān)數(shù)據(jù)money,則從數(shù)據(jù)庫(kù)讀取相關(guān)數(shù)據(jù)money【這就是所謂的數(shù)據(jù)未命中miss”】,放入緩存中uid->money,再返回

緩存的命中率 = 命中緩存請(qǐng)求個(gè)數(shù)/總緩存訪問(wèn)請(qǐng)求個(gè)數(shù) = hit/(hit+miss)

上面舉例的余額場(chǎng)景,99%的讀,1%的寫(xiě),這個(gè)緩存的命中率是非常高的,會(huì)在95%以上。

?

那么問(wèn)題來(lái)了

當(dāng)數(shù)據(jù)money發(fā)生變化的時(shí)候:

1)是更新緩存中的數(shù)據(jù),還是淘汰緩存中的數(shù)據(jù)呢?

2)是先操縱數(shù)據(jù)庫(kù)中的數(shù)據(jù)再操縱緩存中的數(shù)據(jù),還是先操縱緩存中的數(shù)據(jù)再操縱數(shù)據(jù)庫(kù)中的數(shù)據(jù)呢?

3)緩存與數(shù)據(jù)庫(kù)的操作,在架構(gòu)上是否有優(yōu)化的空間呢?

這是本文關(guān)注的三個(gè)核心問(wèn)題。

?

二、更新緩存 VS 淘汰緩存

什么是更新緩存:數(shù)據(jù)不但寫(xiě)入數(shù)據(jù)庫(kù),還會(huì)寫(xiě)入緩存

什么是淘汰緩存:數(shù)據(jù)只會(huì)寫(xiě)入數(shù)據(jù)庫(kù),不會(huì)寫(xiě)入緩存,只會(huì)把數(shù)據(jù)淘汰掉

?

更新緩存的優(yōu)點(diǎn):緩存不會(huì)增加一次miss,命中率高

淘汰緩存的優(yōu)點(diǎn):簡(jiǎn)單(我去,更新緩存我也覺(jué)得很簡(jiǎn)單呀,樓主你太敷衍了吧)

?

那到底是選擇更新緩存還是淘汰緩存呢,主要取決于“更新緩存的復(fù)雜度”。

例如,上述場(chǎng)景,只是簡(jiǎn)單的把余額money設(shè)置成一個(gè)值,那么:

1)淘汰緩存的操作為deleteCache(uid)

2)更新緩存的操作為setCache(uid, money)

更新緩存的代價(jià)很小,此時(shí)我們應(yīng)該更傾向于更新緩存,以保證更高的緩存命中率

?

如果余額是通過(guò)很復(fù)雜的數(shù)據(jù)計(jì)算得出來(lái)的,例如業(yè)務(wù)上除了賬戶表account,還有商品表product,折扣表discount

account(uid, money)

product(pid, type, price, pinfo)

discount(type, zhekou)

業(yè)務(wù)場(chǎng)景是用戶買(mǎi)了一個(gè)商品product,這個(gè)商品的價(jià)格是price,這個(gè)商品從屬于type類(lèi)商品,type類(lèi)商品在做促銷(xiāo)活動(dòng)要打折扣zhekou,購(gòu)買(mǎi)了商品過(guò)后,這個(gè)余額的計(jì)算就復(fù)雜了,需要:

1)先把商品的品類(lèi),價(jià)格取出來(lái):SELECT type, price FROM product WHERE pid=XXX

2)再把這個(gè)品類(lèi)的折扣取出來(lái):SELECT zhekou FROM discount WHERE type=XXX

3)再把原有余額從緩存中查詢出來(lái)money = getCache(uid)

4)再把新的余額寫(xiě)入到緩存中去setCache(uid, money-price*zhekou)

更新緩存的代價(jià)很大,此時(shí)我們應(yīng)該更傾向于淘汰緩存。

?

however,淘汰緩存操作簡(jiǎn)單,并且?guī)?lái)的副作用只是增加了一次cache miss,建議作為通用的處理方式。

?

三、先操作數(shù)據(jù)庫(kù) vs 先操作緩存

OK,當(dāng)寫(xiě)操作發(fā)生時(shí),假設(shè)淘汰緩存作為對(duì)緩存通用的處理方式,又面臨兩種抉擇:

1)先寫(xiě)數(shù)據(jù)庫(kù),再淘汰緩存

2)先淘汰緩存,再寫(xiě)數(shù)據(jù)庫(kù)

究竟采用哪種時(shí)序呢?

?

還記得在《冗余表如何保證數(shù)據(jù)一致性》文章(點(diǎn)擊查看)里“究竟先寫(xiě)正表還是先寫(xiě)反表”的結(jié)論么?

對(duì)于一個(gè)不能保證事務(wù)性的操作,一定涉及“哪個(gè)任務(wù)先做,哪個(gè)任務(wù)后做”的問(wèn)題,解決這個(gè)問(wèn)題的方向是:

如果出現(xiàn)不一致,誰(shuí)先做對(duì)業(yè)務(wù)的影響較小,就誰(shuí)先執(zhí)行。

?

由于寫(xiě)數(shù)據(jù)庫(kù)與淘汰緩存不能保證原子性,誰(shuí)先誰(shuí)后同樣要遵循上述原則。


假設(shè)先寫(xiě)數(shù)據(jù)庫(kù),再淘汰緩存:第一步寫(xiě)數(shù)據(jù)庫(kù)操作成功,第二步淘汰緩存失敗,則會(huì)出現(xiàn)DB中是新數(shù)據(jù),Cache中是舊數(shù)據(jù),數(shù)據(jù)不一致。

?


假設(shè)先淘汰緩存,再寫(xiě)數(shù)據(jù)庫(kù):第一步淘汰緩存成功,第二步寫(xiě)數(shù)據(jù)庫(kù)失敗,則只會(huì)引發(fā)一次Cache miss。

?

結(jié)論:數(shù)據(jù)和緩存的操作時(shí)序,結(jié)論是清楚的:先淘汰緩存,再寫(xiě)數(shù)據(jù)庫(kù)。

?

四、緩存架構(gòu)優(yōu)化


上述緩存架構(gòu)有一個(gè)缺點(diǎn)業(yè)務(wù)方需要同時(shí)關(guān)注緩存與DB,有沒(méi)有進(jìn)一步的優(yōu)化空間呢?有兩種常見(jiàn)的方案,一種主流方案,一種非主流方案(一家之言,勿拍)。

?


主流優(yōu)化方案服務(wù)化:加入一個(gè)服務(wù)層,向上游提供帥氣的數(shù)據(jù)訪問(wèn)接口,向上游屏蔽底層數(shù)據(jù)存儲(chǔ)的細(xì)節(jié),這樣業(yè)務(wù)線不需要關(guān)注數(shù)據(jù)是來(lái)自于cache還是DB。

?


非主流方案異步緩存更新:業(yè)務(wù)線所有的寫(xiě)操作都走數(shù)據(jù)庫(kù),所有的讀操作都總緩存,由一個(gè)異步的工具來(lái)做數(shù)據(jù)庫(kù)與緩存之間數(shù)據(jù)的同步,具體細(xì)節(jié)是:

1)要有一個(gè)init cache的過(guò)程,將需要緩存的數(shù)據(jù)全量寫(xiě)入cache

2)如果DB有寫(xiě)操作,異步更新程序讀取binlog,更新cache

在(1)和(2)的合作下,cache中有全部的數(shù)據(jù),這樣:

a)業(yè)務(wù)線讀cache,一定能夠hit(很短的時(shí)間內(nèi),可能有臟數(shù)據(jù)),無(wú)需關(guān)注數(shù)據(jù)庫(kù)

b)業(yè)務(wù)線寫(xiě)DBcache中能得到異步更新,無(wú)需關(guān)注緩存

這樣將大大簡(jiǎn)化業(yè)務(wù)線的調(diào)用邏輯存在的缺點(diǎn)是,如果緩存的數(shù)據(jù)業(yè)務(wù)邏輯比較復(fù)雜,async-update異步更新的邏輯可能也會(huì)比較復(fù)雜。

?

五、其他未盡事宜

本文只討論了緩存架構(gòu)設(shè)計(jì)中需要注意的幾個(gè)細(xì)節(jié)點(diǎn),如果數(shù)據(jù)庫(kù)架構(gòu)采用了一主多從,讀寫(xiě)分離的架構(gòu),在特殊時(shí)序下,還很可能引發(fā)數(shù)據(jù)庫(kù)與緩存的不一致,這個(gè)不一致如何優(yōu)化,后續(xù)的文章再討論吧。

?

六、結(jié)論強(qiáng)調(diào)

1淘汰緩存是一種通用的緩存處理方式

2先淘汰緩存,再寫(xiě)數(shù)據(jù)庫(kù)的時(shí)序是毋庸置疑的

3服務(wù)化是向業(yè)務(wù)方屏蔽底層數(shù)據(jù)庫(kù)與緩存復(fù)雜性的一種通用方式


七、關(guān)于infoQ

架構(gòu)師之路并不好走。這需要過(guò)硬的技術(shù)能力、出色的綜合素質(zhì)、靈活的大腦,更需要豐富的專(zhuān)業(yè)知識(shí)。

總結(jié)

以上是生活随笔為你收集整理的缓存架构设计细节二三事的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。