扛并發(fā)主力軍,引入應(yīng)用層緩存
1.背景
緩存的使用一定是今后開發(fā)中100%會用到的技術(shù),尤其是Redis相關(guān)的問題,如果面試官不問我我?guī)讉€緩存相關(guān)的問題,那我覺得我可能是去了個假的互聯(lián)網(wǎng)公司。
這里考慮到有些初學(xué)者剛剛出校園或者自學(xué)中,準(zhǔn)許我多費(fèi)口舌介紹下關(guān)于緩存的基礎(chǔ)知識,我們買電腦的時候關(guān)心三個比較重要的參數(shù):1.CPU or GPU 型號。2.內(nèi)存大小。3.硬盤大小。這三個硬件直接決定你電腦性能的好壞。
兩個最關(guān)鍵的因素就是 CPU 和 內(nèi)存,如何衡量一個CPU的好壞?
這是我日常開發(fā)用的電腦,我們發(fā)現(xiàn)有三個關(guān)于內(nèi)存的參數(shù):
- L2 緩存:每個核心 256 KB
- L3 緩存:6 M
- 內(nèi)存:16 G
緩存和內(nèi)存的大小是決定你電腦性能的重要參數(shù),我們都知道內(nèi)存價格遠(yuǎn)高于磁盤,高速緩存(L2/L3)價格高于內(nèi)存。
速度:寄存器 > 高速緩存(SRCM) > 內(nèi)存(DRAM) > 磁盤(SSD > HDD)
畫圖工具:VisualParadigm
緩存概念
“Cache一詞來源于1967年的一篇電子工程期刊論文。其作者將法語詞“cache”賦予“safekeeping storage”的涵義,用于計算機(jī)工程領(lǐng)域。當(dāng)CPU處理數(shù)據(jù)時,它會先到Cache中去尋找,如果數(shù)據(jù)因之前的操作已經(jīng)讀取而被暫存其中,就不需要再從隨機(jī)存取存儲器(Random Access Memory)中讀取數(shù)據(jù)——由于CPU的運(yùn)行速度一般比主內(nèi)存的讀取速度快,主存儲器周期(訪問主存儲器所需要的時間)為數(shù)個時鐘周期。因此若要訪問主內(nèi)存的話,就必須等待數(shù)個CPU周期從而造成浪費(fèi)。提供“緩存”的目的是為了讓數(shù)據(jù)訪問的速度適應(yīng)CPU的處理速度,其基于的原理是內(nèi)存中“程序執(zhí)行與數(shù)據(jù)訪問的局域性行為”,即一定程序執(zhí)行時間和空間內(nèi),被訪問的代碼集中于一部分。為了充分發(fā)揮緩存的作用,不僅依靠“暫存剛剛訪問過的數(shù)據(jù)”,還要使用硬件實現(xiàn)的指令預(yù)測與數(shù)據(jù)預(yù)取技術(shù)——盡可能把將要使用的數(shù)據(jù)預(yù)先從內(nèi)存中取到緩存里。CPU的緩存曾經(jīng)是用在超級計算機(jī)上的一種高級技術(shù),不過現(xiàn)今計算機(jī)上使用的的AMD或Intel微處理器都在芯片內(nèi)部集成了大小不等的數(shù)據(jù)緩存和指令緩存,通稱為L1緩存(L1 Cache即Level 1 On-die Cache,第一級片上高速緩沖存儲器);而比L1更大容量的L2緩存曾經(jīng)被放在CPU外部(主板或者CPU接口卡上),但是現(xiàn)在已經(jīng)成為CPU內(nèi)部的標(biāo)準(zhǔn)組件;更昂貴的CPU會配備比L2緩存還要大的L3緩存(level 3 On-die Cache第三級高速緩沖存儲器)。
面試官:你過去的項目中使用了緩存技術(shù)嗎?哪些業(yè)務(wù)場景使用了?
分析:不管是C端還是B端業(yè)務(wù)場景,都會使用緩存,如果系統(tǒng)設(shè)計不會使用緩存,那實在是無法說服面試官發(fā)offer出來,使用緩存優(yōu)勢就是快,缺點是速度越快價格越昂貴,傳統(tǒng)的基于硬盤存儲的Mysql已經(jīng)無法滿足現(xiàn)有互聯(lián)網(wǎng)公司的流量,為了提高系統(tǒng)的性能,應(yīng)對大流量高并發(fā),cache 在企業(yè)里也有也會廣泛應(yīng)用。
我:
項目中我主要在4個地方使用到緩存
- CDN:
- 代理
- 本地緩存
- 分布式緩存
CDN 廣泛應(yīng)用于網(wǎng)站與應(yīng)用加速、游戲加速、音視頻點播、文件等場景,通過高性能緩存機(jī)制,靜態(tài)加速,靜態(tài)資源如各類型圖片、css、js小文件等,提高訪問效率和資源可用性。
代理在前面的小節(jié)講到 《Nginx下的負(fù)載均衡》 ,Nginx 可作為 http 緩存工具。
后面的章節(jié)主要圍繞“本地緩存”和“分布式緩存”重點介紹應(yīng)用層緩存的使用,因為作為開發(fā)工程師,應(yīng)用層你接觸相對比較多。
緩存分布圖
緩存使用場景
使用緩存,通常考慮兩種情況:
- 短時間內(nèi)相同數(shù)據(jù)重復(fù)查詢多次且數(shù)據(jù)更新不頻繁,這個時候可以選擇先從緩存查詢,查詢不到再從數(shù)據(jù)庫加載并回設(shè)到緩存的方式。此種場景較適合用單機(jī)緩存。
- 高并發(fā)查詢熱點數(shù)據(jù),后端數(shù)據(jù)庫不堪重負(fù),可以用緩存來扛。
具體應(yīng)用場景:
- 排行榜相關(guān)的問題,如新浪微博熱門話題榜,百度當(dāng)前熱搜榜,一定是在緩存了。
- 熱門商品列表
- 計數(shù)問題的功能,比如記錄網(wǎng)站訪問次數(shù)或用戶訪問ip個數(shù)。
4.常用緩存框架
在應(yīng)用服務(wù)器本地緩存著熱點數(shù)據(jù),應(yīng)用程序可以在本機(jī)內(nèi)存中直接訪問數(shù)據(jù),而無需訪問數(shù)據(jù)庫。在Java里,本地緩存就是緩存在JVM所在主機(jī)的內(nèi)存中,常規(guī)設(shè)計中,本地緩存處于分布式緩存上一層,客戶端請求優(yōu)先查詢本地緩存,如果本地緩存未命中,再去查找 Redis,如果 Redis 依舊沒命中,最后查找數(shù)據(jù)庫。也可以直接設(shè)計分布式緩存+數(shù)據(jù)庫兩層架構(gòu)。
本地緩存流行框架
- Guavn Cache :Google開源的Java重用工具集庫Guava里的一款緩存工具。
- Ehcache:非常流行的純Java開源緩存框架,使用簡單,高速,實現(xiàn)線程安全的緩存管理類庫。
- 編程語言自帶數(shù)據(jù)結(jié)構(gòu):如 Java 的 HashMap,CurrentHashMap 等。
- Spring 緩存:Spring 全家桶無所不能,如果你的項目組人少事兒多,Spring Cache 或許是不錯的選擇。
分布式緩存流行框架
- Reids:一個遠(yuǎn)程非關(guān)系型內(nèi)存數(shù)據(jù)庫
- Memcached:應(yīng)用較廣的開源分布式緩存產(chǎn)品之一
- 阿里Tair:阿里開源產(chǎn)品
Redis 是當(dāng)前最流行的分布式緩存框架,企業(yè)廣泛使用,也是面試中要求較高的,每個程序員都必須了解掌握,后面會針對 Redis 詳細(xì)介紹。
為什么要使用緩存
在高并發(fā)請求時,為何我們頻繁提到緩存技術(shù)?最直接的原因是,磁盤IO及網(wǎng)絡(luò)開銷是直接請求內(nèi)存IO千百上千倍,做個簡單計算,如果我們需要某個數(shù)據(jù),該數(shù)據(jù)從數(shù)據(jù)庫磁盤讀出來需要0.0045S,經(jīng)過網(wǎng)絡(luò)請求傳輸需要0.0005S,那么每個請求完成最少需要0.005S,該數(shù)據(jù)服務(wù)器每秒最多只能響應(yīng)200個請求,而如果該數(shù)據(jù)存于本機(jī)內(nèi)存里,讀出來只需要100us,那么每秒能夠響應(yīng)10000個請求。通過將數(shù)據(jù)存儲到離CPU更近的位置,減少數(shù)據(jù)傳輸時間,提高處理效率,這就是緩存的意義。
下圖是小編工作中負(fù)責(zé)過的一個風(fēng)控系統(tǒng)在日常24H中 Redis集群 QPS 曲線圖,從業(yè)務(wù)低峰期幾千或晚高峰最高30W,一個 Redis 集群都可輕松應(yīng)對,30W QPS 在大型系統(tǒng)中流量并不算高,且不是核心系統(tǒng),如果在多幾倍幾十倍多流量,一個結(jié)構(gòu)優(yōu)良的 Redis 集群都可輕松應(yīng)對,這充分說明了我們?yōu)槭裁匆褂镁彺妫彺婵梢园严到y(tǒng)系統(tǒng)響應(yīng)能力提高N個數(shù)量級,遠(yuǎn)高于傳統(tǒng)基于硬盤的關(guān)系型數(shù)據(jù)庫。所以學(xué)會在系統(tǒng)中設(shè)計使用緩存也是企業(yè)招聘時要求工程師必會的技能。
5.關(guān)于緩存的一些算法
常用緩存數(shù)據(jù)淘汰策略
緩存是非常寶貴的資源,不能把所有數(shù)據(jù)都放入緩存,只能把最重要的或者要求查詢速度最快的數(shù)據(jù)緩存起來,比如微博熱門話題排行榜功能,通常使用緩存查詢,而不是數(shù)據(jù)庫。
- FIFO(First In First Out): 先進(jìn)先出算法,即先放入緩存的先被移除。
- LRU(Least Recently Used): 最近最少使用算法,使用時間距離現(xiàn)在最久的那個被移除。
- LFU(Least Frequently Used): 最不常用算法,一定時間段內(nèi)使用次數(shù)(頻率)最少的那個被移除。
緩存數(shù)據(jù)更新策略
- 定時任務(wù)從數(shù)據(jù)庫直接更新緩存:適用于對時間不敏感的數(shù)據(jù)。
- 查詢時寫緩存,即查詢優(yōu)先查詢緩存,若緩存未命中,查詢數(shù)據(jù)庫,將返回結(jié)果寫入緩存,數(shù)據(jù)更新時先 delete 緩存,再更新緩存。
- MQ 消息異步更新緩存,后文中會針對MQ的應(yīng)用做單獨講解。
6.總結(jié)
思考:關(guān)于緩存淘汰策略和更新策略,各自有什么優(yōu)點?有什么缺點?讀者可以作為延伸學(xué)習(xí)。
為什么要了解每種策略的優(yōu)缺點,工作中業(yè)務(wù)場景千差萬別,只有知道不同策略的優(yōu)缺點才能知道哪種策略最適合當(dāng)前的業(yè)務(wù)場景。
高并發(fā)網(wǎng)站后臺一定離不開緩存的使用,所以面試中要求工程師必須掌握。
關(guān)于緩存常見面試題舉例:
- 為什么使用緩存,有什么優(yōu)點?
- Redis 與 Memcached 區(qū)別。
- 緩存更新策略 & 淘汰策略。
- 關(guān)于 Redis 的知識點,如 Redis 常用數(shù)據(jù)結(jié)構(gòu),持久化策略,線程模型等。
參考資料
- 維基百科:https://zh.wikipedia.org/wiki/緩存
- 美團(tuán)點評技術(shù)博客:https://tech.meituan.com/
本文轉(zhuǎn)載自微信公眾號「轉(zhuǎn)行程序員」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系轉(zhuǎn)行程序員公眾號。