對(duì)于高并發(fā)架構(gòu)敲茄,毫無(wú)疑問(wèn)緩存是最重要的一環(huán)哎迄,對(duì)于大量的高并發(fā)挑格,可以采用三層緩存架構(gòu)來(lái)實(shí)現(xiàn)nginx+redis+ehcache专控。
Nginx
對(duì)于中間件nginx常用來(lái)做流量的分發(fā),同時(shí)nginx本身也有自己的緩存(容量有限)诬滩,我們可以用來(lái)緩存熱點(diǎn)數(shù)據(jù)霹粥,讓用戶的請(qǐng)求直接走緩存并返回,減少流向服務(wù)器的流量疼鸟。
1.模板引擎
通常我們可以配合使用freemaker/velocity等模板引擎來(lái)抗住大量的請(qǐng)求:
小型系統(tǒng)可能直接在服務(wù)器端渲染出所有的頁(yè)面并放入緩存后控,之后的相同頁(yè)面請(qǐng)求就可以直接返回,不用去查詢數(shù)據(jù)源或者做數(shù)據(jù)邏輯處理空镜。
對(duì)于頁(yè)面非常之多的系統(tǒng)浩淘,當(dāng)模板有改變,上述方法就需要重新渲染所有的頁(yè)面模板吴攒,毫無(wú)疑問(wèn)是不可取的张抄。因此配合nginx+lua(OpenResty),將模板單獨(dú)保存在nginx緩存中洼怔,同時(shí)對(duì)于用來(lái)渲染的數(shù)據(jù)也存在nginx緩存中署惯,但是需要設(shè)置一個(gè)緩存過(guò)期的時(shí)間,以盡可能保證模板的實(shí)時(shí)性镣隶。
2.雙層nginx來(lái)提升緩存命中率
對(duì)于部署多個(gè)nginx而言极谊,如果不加入一些數(shù)據(jù)的路由策略什荣,那么可能導(dǎo)致每個(gè)nginx的緩存命中率很低。因此可以部署雙層nginx:
分發(fā)層nginx負(fù)責(zé)流量分發(fā)的邏輯和策略怀酷,根據(jù)自己定義的一些規(guī)則稻爬,比如根據(jù)productId進(jìn)行hash,然后對(duì)后端nginx數(shù)量取模將某一個(gè)商品的訪問(wèn)請(qǐng)求固定路由到一個(gè)nginx后端服務(wù)器上去蜕依。
后端nginx用來(lái)緩存一些熱點(diǎn)數(shù)據(jù)到自己的緩存區(qū)(分發(fā)層只能配置1個(gè)嗎)桅锄。
Redis
用戶的請(qǐng)求,在nginx沒(méi)有緩存相應(yīng)的數(shù)據(jù)样眠,那么會(huì)進(jìn)入到redis緩存中友瘤,redis可以做到全量數(shù)據(jù)的緩存,通過(guò)水平擴(kuò)展能夠提升并發(fā)檐束、高可用的能力辫秧。
1.持久化機(jī)制
將redis內(nèi)存中的數(shù)據(jù)持久化到磁盤中,然后可以定期將磁盤文件上傳至S3(AWS)或者ODPS(阿里云)等一些云存儲(chǔ)服務(wù)上去被丧。
如果同時(shí)使用RDB和AOF兩種持久化機(jī)制盟戏,那么在redis重啟的時(shí)候,會(huì)使用AOF來(lái)重新構(gòu)建數(shù)據(jù)甥桂,因?yàn)锳OF中的數(shù)據(jù)更加完整柿究,建議將兩種持久化機(jī)制都開(kāi)啟,用AO F來(lái)保證數(shù)據(jù)不丟失黄选,作為數(shù)據(jù)恢復(fù)的第一選擇蝇摸;用RDB來(lái)作不同程度的冷備,在AOF文件都丟失或損壞不可用的時(shí)候來(lái)快速進(jìn)行數(shù)據(jù)的恢復(fù)办陷。
實(shí)戰(zhàn)踩坑:對(duì)于想從RDB恢復(fù)數(shù)據(jù)貌夕,同時(shí)AOF開(kāi)關(guān)也是打開(kāi)的,一直無(wú)法正趁窬担恢復(fù)啡专,因?yàn)槊看味紩?huì)優(yōu)先從AOF獲取數(shù)據(jù)(如果臨時(shí)關(guān)閉AOF,就可以正逞旰悖恢復(fù))植旧。此時(shí)首先停止redis,然后關(guān)閉AOF离唐,拷貝RDB到相應(yīng)目錄,啟動(dòng)redis之后熱修改配置參數(shù)redis config set appendonly yes问窃,此時(shí)會(huì)自動(dòng)生成一個(gè)當(dāng)前內(nèi)存數(shù)據(jù)的AOF文件亥鬓,然后再次停止redis,打開(kāi)AOF配置域庇,再次啟動(dòng)數(shù)據(jù)就正常啟動(dòng)嵌戈。
RDB
對(duì)redis中的數(shù)據(jù)執(zhí)行周期性的持久化覆积,每一刻持久化的都是全量數(shù)據(jù)的一個(gè)快照。對(duì)redis性能影響較小熟呛,基于RDB能夠快速異晨淼担恢復(fù)。
AOF
以append-only的模式寫(xiě)入一個(gè)日志文件中庵朝,在redis重啟的時(shí)候可以通過(guò)回放AOF日志中的寫(xiě)入指令來(lái)重新構(gòu)建整個(gè)數(shù)據(jù)集吗冤。(實(shí)際上每次寫(xiě)的日志數(shù)據(jù)會(huì)先到linux os cache,然后redis每隔一秒調(diào)用操作系統(tǒng)fsync將os cache中的數(shù)據(jù)寫(xiě)入磁盤)九府。對(duì)redis有一定的性能影響椎瘟,能夠盡量保證數(shù)據(jù)的完整性。redis通過(guò)rewrite機(jī)制來(lái)保障AOF文件不會(huì)太龐大侄旬,基于當(dāng)前內(nèi)存數(shù)據(jù)并可以做適當(dāng)?shù)闹噶钪貥?gòu)肺蔚。
2.redis集群
replication
一主多從架構(gòu),主節(jié)點(diǎn)負(fù)責(zé)寫(xiě)儡羔,并且將數(shù)據(jù)同步到其他salve節(jié)點(diǎn)(異步執(zhí)行)宣羊,從節(jié)點(diǎn)負(fù)責(zé)讀,主要就是用來(lái)做讀寫(xiě)分離的橫向擴(kuò)容架構(gòu)汰蜘。這種架構(gòu)的master節(jié)點(diǎn)數(shù)據(jù)一定要做持久化段只,否則,當(dāng)master宕機(jī)重啟之后內(nèi)存數(shù)據(jù)清空鉴扫,那么就會(huì)將空數(shù)據(jù)復(fù)制到slave赞枕,導(dǎo)致所有數(shù)據(jù)消失。
sentinal哨兵
哨兵是redis集群架構(gòu)中很重要的一個(gè)組件坪创,負(fù)責(zé)監(jiān)控redis master和slave進(jìn)程是否正常工作炕婶,當(dāng)某個(gè)redis實(shí)例故障時(shí),能夠發(fā)送消息報(bào)警通知給管理員莱预,當(dāng)master node宕機(jī)能夠自動(dòng)轉(zhuǎn)移到slave node上柠掂,如果故障轉(zhuǎn)移發(fā)生來(lái),會(huì)通知client客戶端新的master地址依沮。sentinal至少需要3個(gè)實(shí)例來(lái)保證自己的健壯性涯贞,并且能夠更好地進(jìn)行quorum投票以達(dá)到majority來(lái)執(zhí)行故障轉(zhuǎn)移。
前兩種架構(gòu)方式最大的特點(diǎn)是危喉,每個(gè)節(jié)點(diǎn)的數(shù)據(jù)是相同的宋渔,無(wú)法存取海量的數(shù)據(jù)。因此哨兵集群的方式使用與數(shù)據(jù)量不大的情況辜限。
redis cluster
redis cluster支撐多master node皇拣,每個(gè)master node可以掛載多個(gè)slave node,如果mastre掛掉會(huì)自動(dòng)將對(duì)應(yīng)的某個(gè)slave切換成master。需要注意的是redis cluster架構(gòu)下slave節(jié)點(diǎn)主要是用來(lái)做高可用氧急、故障主備切換的颗胡,如果一定需要slave能夠提供讀的能力,修改配置也可以實(shí)現(xiàn)(同時(shí)也需要修改jedis源碼來(lái)支持該情況下的讀寫(xiě)分離操作)吩坝。redis cluster架構(gòu)下毒姨,master就是可以任意擴(kuò)展的,直接橫向擴(kuò)展master即可提高讀寫(xiě)吞吐量钉寝。slave節(jié)點(diǎn)能夠自動(dòng)遷移(讓master節(jié)點(diǎn)盡量平均擁有slave節(jié)點(diǎn))弧呐,對(duì)整個(gè)架構(gòu)過(guò)載冗余的slave就可以保障系統(tǒng)更高的可用性。
ehcache
tomcat jvm堆內(nèi)存緩存瘩蚪,主要是抗redis出現(xiàn)大規(guī)模災(zāi)難泉懦。如果redis出現(xiàn)了大規(guī)模的宕機(jī),導(dǎo)致nginx大量流量直接涌入數(shù)據(jù)生產(chǎn)服務(wù)疹瘦,那么最后的tomcat堆內(nèi)存緩存也可以處理部分請(qǐng)求崩哩,避免所有請(qǐng)求都直接流向DB
緩存數(shù)據(jù)更新策略
對(duì)時(shí)效性要求高的緩存數(shù)據(jù),當(dāng)發(fā)生變更的時(shí)候言沐,直接采取數(shù)據(jù)庫(kù)和redis緩存雙寫(xiě)的方案邓嘹,讓緩存時(shí)效性最高。
對(duì)時(shí)效性不高的數(shù)據(jù)险胰,當(dāng)發(fā)生變更之后汹押,采取MQ異步通知的方式,通過(guò)數(shù)據(jù)生產(chǎn)服務(wù)來(lái)監(jiān)聽(tīng)MQ消息起便,然后異步去拉取服務(wù)的數(shù)據(jù)更新tomcat jvm緩存和redis緩存棚贾,對(duì)于nginx本地緩存過(guò)期之后就可以從redis中拉取新的數(shù)據(jù)并更新到nginx本地。
經(jīng)典的緩存+數(shù)據(jù)庫(kù)讀寫(xiě)的模式
cache aside pattern
讀的時(shí)候榆综,先讀緩存妙痹,緩存沒(méi)有的話,那么就讀數(shù)據(jù)庫(kù)鼻疮,然后取出數(shù)據(jù)后放入緩存怯伊,同時(shí)返回響應(yīng)。
更新的時(shí)候判沟,先刪除緩存耿芹,然后再更新數(shù)據(jù)庫(kù)
之所以更新的時(shí)候只是刪除緩存,因?yàn)閷?duì)于一些復(fù)雜有邏輯的緩存數(shù)據(jù)挪哄,每次數(shù)據(jù)變更都更新一次緩存會(huì)造成額外的負(fù)擔(dān)吧秕,只是刪除緩存,讓該數(shù)據(jù)下一次被使用的時(shí)候再去執(zhí)行讀的操作來(lái)重新緩存中燥,這里采用的是懶加載的策略寇甸。
舉個(gè)例子,一個(gè)緩存涉及的表的字段疗涉,在1分鐘內(nèi)就修改了20次拿霉,或者是100次,那么緩存跟新20次咱扣,100次绽淘;但是這個(gè)緩存在1分鐘內(nèi)就被讀取了1次,因此每次更新緩存就會(huì)有大量的冷數(shù)據(jù)闹伪,對(duì)于緩存符合28黃金法則沪铭,20%的數(shù)據(jù),占用了80%的訪問(wèn)量偏瓤。
數(shù)據(jù)庫(kù)和redis緩存雙寫(xiě)不一致的問(wèn)題
1.最初級(jí)的緩存不一致問(wèn)題以及解決方案
問(wèn)題:
如果先修改數(shù)據(jù)庫(kù)再刪除緩存杀怠,那么當(dāng)緩存刪除失敗來(lái),那么會(huì)導(dǎo)致數(shù)據(jù)庫(kù)中是最新數(shù)據(jù)厅克,緩存中依舊是舊數(shù)據(jù)赔退,造成數(shù)據(jù)不一致。
解決方案:
可以先刪除緩存证舟,再修改數(shù)據(jù)庫(kù)硕旗,如果刪除緩存成功但是數(shù)據(jù)庫(kù)修改失敗,那么數(shù)據(jù)庫(kù)中是舊數(shù)據(jù)女责,緩存是空不會(huì)出現(xiàn)不一致漆枚。
2.比較復(fù)雜的數(shù)據(jù)不一致問(wèn)題分析
問(wèn)題:
問(wèn)題:對(duì)于數(shù)據(jù)發(fā)生來(lái)變更,先刪除緩存抵知,然后去修改數(shù)據(jù)庫(kù)墙基,此時(shí)數(shù)據(jù)庫(kù)中的數(shù)據(jù)還沒(méi)有修改成功,并發(fā)的讀請(qǐng)求到來(lái)去讀緩存發(fā)現(xiàn)是空刷喜,進(jìn)而去數(shù)據(jù)庫(kù)查詢到此時(shí)的舊數(shù)據(jù)放到緩存中残制,然后之前對(duì)數(shù)據(jù)庫(kù)數(shù)據(jù)的修改成功來(lái),就會(huì)造成數(shù)據(jù)不一致吱肌。
解決方案:
將數(shù)據(jù)庫(kù)與緩存更新與讀取操作進(jìn)行異步串行化痘拆。當(dāng)更新數(shù)據(jù)的時(shí)候,根據(jù)數(shù)據(jù)的唯一標(biāo)識(shí)氮墨,將更新數(shù)據(jù)操作路由到一個(gè)jvm內(nèi)部的隊(duì)列中纺蛆,一個(gè)隊(duì)列對(duì)應(yīng)一個(gè)工作線程,線程串行拿到隊(duì)列中的操作一條一條地執(zhí)行规揪。當(dāng)執(zhí)行隊(duì)列中的更新數(shù)據(jù)操作桥氏,刪除緩存,然后去更新數(shù)據(jù)庫(kù)猛铅,此時(shí)還沒(méi)有完成更新的時(shí)候過(guò)來(lái)一個(gè)讀請(qǐng)求字支,讀到了空的緩存那么可以先將緩存更新的請(qǐng)求發(fā)送至路由之后的隊(duì)列中,此時(shí)會(huì)在隊(duì)列積壓,然后同步等待緩存更新完成堕伪,一個(gè)隊(duì)列中多個(gè)相同數(shù)據(jù)緩存更新請(qǐng)求串在一起是沒(méi)有意義的揖庄,因此可以做過(guò)濾處理。等待前面的更新數(shù)據(jù)操作完成數(shù)據(jù)庫(kù)操作之后欠雌,才會(huì)去執(zhí)行下一個(gè)緩存更新的操作蹄梢,此時(shí)會(huì)從數(shù)據(jù)庫(kù)中讀取最新的數(shù)據(jù),然后寫(xiě)入緩存中富俄,如果請(qǐng)求還在等待時(shí)間范圍內(nèi)禁炒,不斷輪詢發(fā)現(xiàn)可以取到緩存中值就可以直接返回(此時(shí)可能會(huì)有對(duì)這個(gè)緩存數(shù)據(jù)的多個(gè)請(qǐng)求正在這樣處理);如果請(qǐng)求等待事件超過(guò)一定時(shí)長(zhǎng)霍比,那么這一次的請(qǐng)求直接讀取數(shù)據(jù)庫(kù)中的舊值
對(duì)于這種處理方式需要注意一些問(wèn)題:
1.讀請(qǐng)求長(zhǎng)時(shí)阻塞
由于讀請(qǐng)求進(jìn)行來(lái)非常輕度的異步化幕袱,所以對(duì)超時(shí)的問(wèn)題需要格外注意,超過(guò)超時(shí)時(shí)間會(huì)直接查詢DB悠瞬,處理不好會(huì)對(duì)DB造成壓力们豌,因此需要測(cè)試系統(tǒng)高峰期QPS來(lái)調(diào)整機(jī)器數(shù)以及對(duì)應(yīng)機(jī)器上的隊(duì)列數(shù)最終決定合理的請(qǐng)求等待超時(shí)時(shí)間
2.多實(shí)例部署的請(qǐng)求路由
可能這個(gè)服務(wù)會(huì)部署多個(gè)實(shí)例,那么必須保證對(duì)應(yīng)的請(qǐng)求都通過(guò)nginx服務(wù)器路由到相同的服務(wù)實(shí)例上
3.熱點(diǎn)數(shù)據(jù)的路由導(dǎo)師請(qǐng)求的傾斜
因?yàn)橹挥性谏唐窋?shù)據(jù)更新的時(shí)候才會(huì)清空緩存阁危,然后才會(huì)導(dǎo)致讀寫(xiě)并發(fā)玛痊,所以更新頻率不是太高的話,這個(gè)問(wèn)題的影響并不是特別大狂打,但是的確可能某些機(jī)器的負(fù)載會(huì)高一些
分布式緩存重建并發(fā)沖突解決方案
對(duì)于緩存生產(chǎn)服務(wù)擂煞,可能部署在多臺(tái)機(jī)器,當(dāng)redis和ehcache對(duì)應(yīng)的緩存數(shù)據(jù)都過(guò)期不存在時(shí)趴乡,此時(shí)可能nginx過(guò)來(lái)的請(qǐng)求和kafka監(jiān)聽(tīng)的請(qǐng)求同時(shí)到達(dá)对省,導(dǎo)致兩者最終都去拉取數(shù)據(jù)并且存入redis中,因此可能產(chǎn)生并發(fā)沖突的問(wèn)題晾捏,可以采用redis或者zookeeper類似的分布式鎖來(lái)解決蒿涎,讓請(qǐng)求的被動(dòng)緩存重建與監(jiān)聽(tīng)主動(dòng)的緩存重建操作避免并發(fā)的沖突,當(dāng)存入緩存的時(shí)候通過(guò)對(duì)比時(shí)間字段廢棄掉舊的數(shù)據(jù)惦辛,保存最新的數(shù)據(jù)到緩存
緩存冷啟動(dòng)以及緩存預(yù)熱解決方案
當(dāng)系統(tǒng)第一次啟動(dòng)劳秋,大量請(qǐng)求涌入,此時(shí)的緩存為空胖齐,可能會(huì)導(dǎo)致DB崩潰玻淑,進(jìn)而讓系統(tǒng)不可用,同樣當(dāng)redis所有緩存數(shù)據(jù)異常丟失呀伙,也會(huì)導(dǎo)致該問(wèn)題补履。因此,可以提前放入數(shù)據(jù)到redis避免上述冷啟動(dòng)的問(wèn)題剿另,當(dāng)然也不可能是全量數(shù)據(jù)箫锤,可以根據(jù)類似于當(dāng)天的具體訪問(wèn)情況贬蛙,實(shí)時(shí)統(tǒng)計(jì)出訪問(wèn)頻率較高的熱數(shù)據(jù),這里熱數(shù)據(jù)也比較多谚攒,需要多個(gè)服務(wù)并行的分布式去讀寫(xiě)到redis中(所以要基于zk分布式鎖)阳准。
通過(guò)nginx+lua將訪問(wèn)流量上報(bào)至kafka中,storm從kafka中消費(fèi)數(shù)據(jù)五鲫,實(shí)時(shí)統(tǒng)計(jì)處每個(gè)商品的訪問(wèn)次數(shù)溺职,訪問(wèn)次數(shù)基于LRU(apache commons collections LRUMap)內(nèi)存數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)方案岔擂,使用LRUMap去存放是因?yàn)閮?nèi)存中的性能高位喂,沒(méi)有外部依賴,每個(gè)storm task啟動(dòng)的時(shí)候基于zk分布式鎖將自己的id寫(xiě)入zk同一個(gè)節(jié)點(diǎn)中乱灵,每個(gè)storm task負(fù)責(zé)完成自己這里的熱數(shù)據(jù)的統(tǒng)計(jì)塑崖,每隔一段時(shí)間就遍歷一下這個(gè)map,然后維護(hù)一個(gè)前1000的數(shù)據(jù)list痛倚,然后去更新這個(gè)list规婆,最后開(kāi)啟一個(gè)后臺(tái)線程,每隔一段時(shí)間比如一分鐘都將排名的前1000的熱數(shù)據(jù)list同步到zk中去蝉稳,存儲(chǔ)到這個(gè)storm task對(duì)應(yīng)的一個(gè)znode中去抒蚜。
部署多個(gè)實(shí)例的服務(wù),每次啟動(dòng)的時(shí)候就會(huì)去拿到上述維護(hù)的storm task id列表的節(jié)點(diǎn)數(shù)據(jù)耘戚,然后根據(jù)taskid嗡髓,一個(gè)一個(gè)去嘗試獲取taskid對(duì)應(yīng)的znode的zk分布式鎖,如果能夠獲取到分布式鎖收津,再去獲取taskid status的鎖進(jìn)而查詢預(yù)熱狀態(tài)饿这,如果沒(méi)有被預(yù)熱過(guò),那么就將這個(gè)taskid對(duì)應(yīng)的熱數(shù)據(jù)list取出來(lái)撞秋,從而從DB中查詢出來(lái)寫(xiě)入緩存中长捧,如果taskid分布式鎖獲取失敗,快速拋錯(cuò)進(jìn)行下一次循環(huán)獲取下一個(gè)taskid的分布式鎖即可吻贿,此時(shí)就是多個(gè)服務(wù)實(shí)例基于zk分布式鎖做協(xié)調(diào)并行的進(jìn)行緩存的預(yù)熱串结。
緩存熱點(diǎn)導(dǎo)致系統(tǒng)不可用解決方案
對(duì)于瞬間大量的相同數(shù)據(jù)的請(qǐng)求涌入,可能導(dǎo)致該數(shù)據(jù)經(jīng)過(guò)hash策略之后對(duì)應(yīng)的應(yīng)用層nginx被壓垮舅列,如果請(qǐng)求繼續(xù)就會(huì)影響至其他的nginx肌割,最終導(dǎo)致所有nginx出現(xiàn)異常整個(gè)系統(tǒng)變得不可用。
基于nginx+lua+storm的熱點(diǎn)緩存的流量分發(fā)策略自動(dòng)降級(jí)來(lái)解決上述問(wèn)題的出現(xiàn)剧蹂,可以設(shè)定訪問(wèn)次數(shù)大于后95%平均值n倍的數(shù)據(jù)為熱點(diǎn)声功,在storm中直接發(fā)送http請(qǐng)求到流量分發(fā)的nginx上去,使其存入本地緩存宠叼,然后storm還會(huì)將熱點(diǎn)對(duì)應(yīng)的完整緩存數(shù)據(jù)沒(méi)發(fā)送到所有的應(yīng)用nginx服務(wù)器上去先巴,并直接存放到本地緩存其爵。對(duì)于流量分發(fā)nginx,訪問(wèn)對(duì)應(yīng)的數(shù)據(jù)伸蚯,如果發(fā)現(xiàn)是熱點(diǎn)標(biāo)識(shí)就立即做流量分發(fā)策略的降級(jí)摩渺,對(duì)同一個(gè)數(shù)據(jù)的訪問(wèn)從hash到一臺(tái)應(yīng)用層nginx降級(jí)成為分發(fā)至所有的應(yīng)用層nginx。storm需要保存上一次識(shí)別出來(lái)的熱點(diǎn)List剂邮,并同當(dāng)前計(jì)算出來(lái)的熱點(diǎn)list做對(duì)比摇幻,如果已經(jīng)不是熱點(diǎn)數(shù)據(jù),則發(fā)送對(duì)應(yīng)的http請(qǐng)求至流量分發(fā)nginx中來(lái)取消對(duì)應(yīng)數(shù)據(jù)的熱點(diǎn)標(biāo)識(shí)
緩存雪崩解決方案
redis集群徹底崩潰挥萌,緩存服務(wù)大量對(duì)redis的請(qǐng)求等待绰姻,占用資源,隨后緩存服務(wù)大量的請(qǐng)求進(jìn)入源頭服務(wù)去查詢DB引瀑,使DB壓力過(guò)大崩潰狂芋,此時(shí)對(duì)源頭服務(wù)的請(qǐng)求也大量等待占用資源,緩存服務(wù)大量的資源全部耗費(fèi)在訪問(wèn)redis和源服務(wù)無(wú)果憨栽,最后使自身無(wú)法提供服務(wù)帜矾,最終會(huì)導(dǎo)致整個(gè)網(wǎng)站崩潰。
事前解決方案:
搭建一套高可用架構(gòu)的redis cluster集群屑柔,主從架構(gòu)屡萤、一主多從,一旦主節(jié)點(diǎn)宕機(jī)掸宛,從節(jié)點(diǎn)自動(dòng)跟上死陆,并且最好使用雙機(jī)房部署集群。
事中解決方案:
部署一層ehcache緩存旁涤,在redis全部實(shí)現(xiàn)情況下能夠抗住部分壓力翔曲;對(duì)redis cluster的訪問(wèn)做資源隔離,避免所有資源都等待劈愚,對(duì)redis cluster的訪問(wèn)失敗時(shí)的情況去部署對(duì)應(yīng)的熔斷策略瞳遍,部署redis cluster的降級(jí)策略;對(duì)源服務(wù)訪問(wèn)的限流以及資源隔離菌羽。
事后解決方案:
redis數(shù)據(jù)做了備份可以直接恢復(fù)掠械,重啟redis即可;redis數(shù)據(jù)徹底失敗來(lái)或者數(shù)據(jù)過(guò)舊注祖,可以快速緩存預(yù)熱猾蒂,然后讓redis重新啟動(dòng)。然后由于資源隔離的half-open策略發(fā)現(xiàn)redis已經(jīng)能夠正常訪問(wèn)是晨,那么所有的請(qǐng)求將自動(dòng)恢復(fù)肚菠。
緩存穿透解決方案
對(duì)于在多級(jí)緩存中都沒(méi)有對(duì)應(yīng)的數(shù)據(jù),并且DB也沒(méi)有查詢到數(shù)據(jù)罩缴,此時(shí)大量的請(qǐng)求都會(huì)直接到達(dá)DB蚊逢,導(dǎo)致DB承載高并發(fā)的問(wèn)題层扶。解決緩存穿透的問(wèn)題可以對(duì)DB也沒(méi)有的數(shù)據(jù)返回一個(gè)空標(biāo)識(shí)的數(shù)據(jù),進(jìn)而保存到各級(jí)緩存中烙荷,因?yàn)橛袑?duì)數(shù)據(jù)修改的異步監(jiān)聽(tīng)镜会,所以當(dāng)數(shù)據(jù)有更新,新的數(shù)據(jù)會(huì)被更新到緩存匯中终抽。
nginx緩存失效導(dǎo)致redis壓力倍增
可以在nginx本地戳表,設(shè)置緩存數(shù)據(jù)的時(shí)候隨機(jī)緩存的有效期,避免同一時(shí)刻緩存都失效而大量請(qǐng)求直接進(jìn)入redis
這個(gè)過(guò)程值得我們?nèi)ド钊雽W(xué)習(xí)和思考昼伴。如果對(duì)你有幫助請(qǐng)動(dòng)動(dòng)小手關(guān)注下吧匾旭!