前言:
這篇文章主要是總結(jié)在高并發(fā)場(chǎng)景下應(yīng)該什么時(shí)候使用緩存溢陪,怎樣使用緩存萍虽。同時(shí)介紹了目前主要的三個(gè)緩存工具。
為什么需要使用緩存形真?
下面我們來(lái)看看瀏覽器請(qǐng)求的大致流程:
上面就是我們?yōu)g覽器訪問(wèn)服務(wù)器的大致流程杉编,隨著用戶量增多,服務(wù)器的壓力和數(shù)據(jù)庫(kù)的壓力也會(huì)隨之來(lái)臨咆霜。要想使系統(tǒng)擁有高吞吐量我們可以在任意環(huán)節(jié)加入緩存邓馒,使得請(qǐng)求能夠直接從緩存中獲取,從而減少服務(wù)器的計(jì)算量蛾坯,從而提升響應(yīng)速度光酣。其實(shí)緩存可以出現(xiàn)在上面4個(gè)環(huán)節(jié)的任意環(huán)節(jié),但是作為后臺(tái)開(kāi)發(fā)的人員來(lái)說(shuō)我們更加關(guān)心的是服務(wù)器方面和數(shù)據(jù)庫(kù)方面的緩存脉课。
緩存的特征
命中率=命中數(shù)/(命中數(shù)+沒(méi)有命中數(shù)):在這里命中數(shù)就可以理解為用戶請(qǐng)求的資源在緩存中救军,而沒(méi)有命中就是指用戶無(wú)法直接從緩存中獲取資源,需要查詢數(shù)據(jù)庫(kù)或者由服務(wù)器計(jì)算分發(fā)資源
最大元素:也就是緩存中能存放的最大數(shù)據(jù)倘零,可以理解為緩存的容量唱遭,當(dāng)緩存中的數(shù)據(jù)超出了最大元素,那么就會(huì)觸發(fā)緩存清空策略呈驶。合理設(shè)置最大元素值可以有效的幫我們提高命中率拷泽。
清空策略(部分):
FIFO:先進(jìn)先出策略,最先進(jìn)入緩存的數(shù)據(jù)在緩存空間不足的情況下最先清除俐东,是主要比較資源創(chuàng)建的時(shí)間跌穗,在數(shù)據(jù)要求實(shí)時(shí)性的情況下,可以使用該策略虏辫,優(yōu)先保障最新數(shù)據(jù)可用
LFU:最少使用策略,無(wú)論創(chuàng)建時(shí)間什么時(shí)候锈拨,當(dāng)緩存空間不足時(shí)砌庄,清除使用次數(shù)較少的緩存,保留使用次數(shù)較多的緩存,這類策略有效的保證高命中率
LRU:最近最少使用策略娄昆,根據(jù)元素最后一次使用的時(shí)間進(jìn)行排序佩微,清除最近沒(méi)有使用過(guò)的資源。在熱點(diǎn)場(chǎng)景下適用萌焰,優(yōu)先保證熱點(diǎn)數(shù)據(jù)的有效性
緩存命中率影響因素
緩存適合讀多寫少的業(yè)務(wù)場(chǎng)景哺眯,如果是在寫多讀少的場(chǎng)景使用緩存的意義就不大,并且可以根據(jù)清空策略來(lái)保證緩存的命中率扒俯。實(shí)時(shí)性要求越低的場(chǎng)景就越適合緩存
緩存的粒度越小奶卓,命中率就越高
緩存容量和基礎(chǔ)設(shè)施,目前的緩存工具和中間件大多采用LRU算法撼玄,并且采用分布式架構(gòu)能更好的擴(kuò)展緩存夺姑。
緩存應(yīng)該聚焦于高頻訪問(wèn)且時(shí)效性低的熱點(diǎn)數(shù)據(jù)上
緩存的分類和應(yīng)用場(chǎng)景
1、本地緩存:編程實(shí)現(xiàn)掌猛、Guava Cache
2盏浙、分布式緩存:Memcache、Redis
Guava Cache:架構(gòu)設(shè)計(jì)靈感來(lái)源于J.U.C包中的ConcurrentHashMap荔茬。在Guava Cache中使用多個(gè)segment細(xì)粒度鎖在保證線程安全的同時(shí)能夠保證高并發(fā)場(chǎng)景的需求废膘,Cache實(shí)際上是存取鍵值對(duì)的集合,與ConcurrentHashMap不同的是Cache需要處理緩存過(guò)期慕蔚,動(dòng)態(tài)加載等算法的問(wèn)題殖卑,下面是Cache內(nèi)部示意圖:
主要實(shí)現(xiàn)的功能有:自動(dòng)將節(jié)點(diǎn)加載進(jìn)緩存結(jié)構(gòu)中,當(dāng)緩存的數(shù)據(jù)超過(guò)最大值時(shí)坊萝,就通過(guò)LRU算法來(lái)移除孵稽,還可以計(jì)算出緩存的命中率,未命中數(shù)等統(tǒng)計(jì)數(shù)據(jù)十偶。
MemCache:應(yīng)用較為廣泛的開(kāi)源分布式緩存之一菩鲜,MemCache分布式是在客戶端實(shí)現(xiàn)的,通過(guò)客戶端的路由來(lái)處理惦积。具體原理是:在客戶端設(shè)置了key和value接校,并采用一致性的哈希算法作為的路由策略,MemCache除了計(jì)算key的哈希值還會(huì)計(jì)算服務(wù)器的哈希值狮崩,然后將這兩個(gè)哈希值映射到有限的值域上蛛勉,通過(guò)尋找服務(wù)器哈希值大于且最接近key的哈希值的服務(wù)器作為這個(gè)客戶端的緩存,即通過(guò)將key映射到不同的服務(wù)器上實(shí)現(xiàn)分布式睦柴。
Redis:遠(yuǎn)程的非關(guān)系型數(shù)據(jù)庫(kù)诽凌,性能強(qiáng)勁,具有復(fù)制特性等坦敌,可以存儲(chǔ)鍵值對(duì)侣诵,與五種不同類型(String痢法,hash,list杜顺,set财搁,sorted set)值之間的映射,還可以將存儲(chǔ)在內(nèi)存的數(shù)據(jù)持久化到硬盤躬络,使用復(fù)制特性擴(kuò)展讀性能尖奔,使用分片擴(kuò)展寫性能。支持主從數(shù)據(jù)備份穷当。Redis底層是通過(guò)C語(yǔ)言編寫提茁,最高每秒可讀11萬(wàn)次,可寫8萬(wàn)1千次膘滨。Redis的所有操作都具有原子性甘凭,也支持對(duì)幾個(gè)操作合并后的原子性執(zhí)行。
高并發(fā)下緩存常見(jiàn)問(wèn)題
緩存一致性:當(dāng)數(shù)據(jù)時(shí)效要求很高火邓,就必須保證數(shù)據(jù)庫(kù)中的數(shù)據(jù)和緩存中的數(shù)據(jù)一致丹弱,而且要保證緩存中的節(jié)點(diǎn)和副本中的節(jié)點(diǎn)要保持一致。這就比較依賴于緩存的過(guò)期的更新策略铲咨,一般在數(shù)據(jù)發(fā)生更改的時(shí)候主動(dòng)更新緩存中的數(shù)據(jù)躲胳。也就是會(huì)出現(xiàn)以下4種情況:
更新數(shù)據(jù)庫(kù)成功 ----> 更新緩存失敗 ---->數(shù)據(jù)不一致
更新緩存成功 ----> 更新數(shù)據(jù)庫(kù)失敗 ---->數(shù)據(jù)不一致
更新數(shù)據(jù)庫(kù)成功 ----> 刪除緩存失敗 ---->數(shù)據(jù)不一致
刪除緩存成功 ----> 更新數(shù)據(jù)庫(kù)失敗 ---->數(shù)據(jù)不一致
緩存并發(fā):當(dāng)緩存過(guò)期后會(huì)嘗試從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)。在高并發(fā)的時(shí)候可能會(huì)存在多個(gè)緩存請(qǐng)求獲取數(shù)據(jù)庫(kù)纤勒,這會(huì)對(duì)后端數(shù)據(jù)庫(kù)造成極大的沖擊坯苹。這時(shí)候在緩存更新或者淘汰的時(shí)候就需要加鎖,然后當(dāng)數(shù)據(jù)庫(kù)更新完或者從數(shù)據(jù)庫(kù)獲取到數(shù)據(jù)時(shí)候之后再釋放鎖摇天。
緩存穿透:在高并發(fā)時(shí)粹湃,如果某個(gè)key被高并發(fā)的訪問(wèn),但是沒(méi)有被命中泉坐,這時(shí)候請(qǐng)求就有可能通過(guò)緩存直接達(dá)到數(shù)據(jù)庫(kù)为鳄,數(shù)據(jù)庫(kù)中也不存在該數(shù)據(jù),使得數(shù)據(jù)庫(kù)執(zhí)行了很多不必要的查詢操作腕让。并且會(huì)對(duì)數(shù)據(jù)庫(kù)造成特別大的沖擊孤钦。解決方案:接口層增加校驗(yàn)與緩存空對(duì)象。
緩存的雪崩:緩存中數(shù)據(jù)大批量到過(guò)期時(shí)間纯丸,且查詢數(shù)據(jù)量巨大偏形,使得請(qǐng)求直接來(lái)到數(shù)據(jù)庫(kù),讓數(shù)據(jù)庫(kù)壓力過(guò)大觉鼻。與緩存穿透不同的是:緩存穿透是大量請(qǐng)求查一條數(shù)據(jù)俊扭,而緩存雪崩是多條數(shù)據(jù)。解決方案:設(shè)置過(guò)期時(shí)間為隨機(jī)滑凉,防止同一時(shí)間數(shù)據(jù)大量過(guò)期统扳,若緩存是分布式部署喘帚,應(yīng)將熱點(diǎn)數(shù)據(jù)均勻分布在不同的緩存數(shù)據(jù)庫(kù)中畅姊。
最后
對(duì)于很多初級(jí)Java工程師而言咒钟,想要提升技能,往往是自己摸索成長(zhǎng)若未,不成體系的學(xué)習(xí)效果低效漫長(zhǎng)且無(wú)助朱嘴。而正值金九銀十的跳槽季,想要漲薪的看這里啦~
小架整理了一些關(guān)于分布式粗合,微服務(wù)萍嬉,性能優(yōu)化,Spring隙疚,MyBatis的等源碼知識(shí)點(diǎn)視頻資料和大廠面試題及答案壤追,是給讀者的福利哦!這些架構(gòu)技術(shù)和資料希望對(duì)Java開(kāi)發(fā)的朋友們有所參考以及少走彎路供屉,小架發(fā)文章的初衷就是想分享技術(shù)和在學(xué)習(xí)中遇到的問(wèn)題行冰,每一篇文章的重點(diǎn)是你有沒(méi)有收獲與成長(zhǎng),其余的都不重要伶丐,希望讀者們能謹(jǐn)記這一點(diǎn)悼做。希望大家在成為架構(gòu)師的路上越走越平坦。
誠(chéng)意滿滿:特別適合有3-5年開(kāi)發(fā)經(jīng)驗(yàn)的Java程序員們學(xué)習(xí)哗魂。關(guān)注+轉(zhuǎn)發(fā)肛走,加我的Java交流群獲取哦~