性能設(shè)計-緩存
分布式系統(tǒng)或者微服務(wù)中最耗性能的地方,就是最后端的數(shù)據(jù)庫。
一般來說,只要小心維護(hù)好數(shù)據(jù)庫的四種操作中的三個寫操作insert、update和delete,就不太會出現(xiàn)性能問題。
insert一般不會有性能問題,update和delete一般也會有主見,不會太慢。
除非是索引太多,數(shù)據(jù)庫里的數(shù)據(jù)也太多,這三個操作才會變慢。
絕大多數(shù)情況下,select 是出現(xiàn)性能問題最大的地方。
一方面,select 會有很多像 join、group、order、like 等這樣豐富的語義,而這些語義是非常耗性能的;
另一方面,大多數(shù)應(yīng)用都是讀多寫少,所以加劇了慢查詢的問題。
分布式系統(tǒng)中遠(yuǎn)程調(diào)用也會消耗很多資源,因?yàn)榫W(wǎng)絡(luò)開銷會導(dǎo)致整體的響應(yīng)時間下降。
為了挽救這樣的性能開銷,在業(yè)務(wù)允許的情況(不需要太實(shí)時的數(shù)據(jù))下,使用緩存是非常必要的事情。
但緩存技術(shù)如何選型,redis還是memcached還是自定義,則需要根據(jù)業(yè)務(wù)場景和具體的架構(gòu)配套選擇。
比如筆者最近參與的一個信貸上云項(xiàng)目,就沒有用到redis,而是自己實(shí)現(xiàn)了一個簡易的jvm本地緩存。
原因在于該銀行的技術(shù)委員會要求,redis掛了的話,業(yè)務(wù)要完全不受影響,也就是所謂的退化方案。
開發(fā)組開發(fā)完本地緩存后,經(jīng)過性能測試和壓力測試,發(fā)現(xiàn)完全滿足需求。
與其在redis掛了后退化到本地緩存,還不如直接使用本地緩存,因此,redis就被棄用了。
另外,金融系統(tǒng)一般首要考慮的是其正確性和安全性,其次才會考慮性能問題。
因此,這樣的方案,看上去是合理的。
Cache Aside 更新模式
這是最常用的設(shè)計模式了,其具體邏輯如下。
失效:應(yīng)用程序先從 Cache 取數(shù)據(jù),如果沒有得到,則從數(shù)據(jù)庫中取數(shù)據(jù),成功后,放到緩存中。
命中:應(yīng)用程序從 Cache 中取數(shù)據(jù),取到后返回。
更新:先把數(shù)據(jù)存到數(shù)據(jù)庫中,成功后,再讓緩存失效。
這是標(biāo)準(zhǔn)的設(shè)計模式,包括 Facebook 的論文《Scaling Memcache at Facebook》中也使用了這個策略。
為什么不是寫完數(shù)據(jù)庫后更新緩存?主要是怕兩個并發(fā)的寫操作導(dǎo)致臟數(shù)據(jù)。
