您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)用戶訪問一個(gè)熱Key該如何優(yōu)化緩存架構(gòu),小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
為什么要用緩存集群
啥叫熱 Key 和大 Value 呢?簡單來說,熱 Key,就是你的緩存集群中的某個(gè) Key 瞬間被數(shù)萬甚至十萬的并發(fā)請求打爆。
大 Value,就是你的某個(gè) Key 對應(yīng)的 Value 可能有 GB 級的大小,導(dǎo)致查詢 Value 的時(shí)候出現(xiàn)網(wǎng)絡(luò)相關(guān)的故障問題。
先來看看下面的一幅圖:
簡單來說,假設(shè)你手頭有個(gè)系統(tǒng),他本身是集群部署的,然后后面有一套緩存集群,這個(gè)集群不管你用 Redis Cluster,還是 Memcached,或者是公司自研緩存集群,都可以。
那么,這套系統(tǒng)用緩存集群干什么呢?很簡單,在緩存里放一些平時(shí)不怎么變動(dòng)的數(shù)據(jù),然后用戶在查詢大量的平時(shí)不怎么變動(dòng)的數(shù)據(jù)的時(shí)候,不就可以直接從緩存里走了嗎?
緩存集群的并發(fā)能力是很強(qiáng)的,而且讀緩存的性能是很高的。舉個(gè)例子,假設(shè)你每秒有 2 萬請求,但是其中 90% 都是讀請求,那么每秒 1.8 萬請求都是在讀一些不太變化的數(shù)據(jù),而不是寫數(shù)據(jù)。
那此時(shí)你把數(shù)據(jù)都放在數(shù)據(jù)庫里,然后每秒發(fā)送 2 萬請求到數(shù)據(jù)庫上讀寫數(shù)據(jù),你覺得合適嗎?
當(dāng)然不太合適了,如果你要用數(shù)據(jù)庫承載每秒 2 萬請求的話,那么不好意思,你很可能就得搞分庫分表 + 讀寫分離。
比如你得分 3 個(gè)主庫,承載每秒 2000 的寫入請求,然后每個(gè)主庫掛 3 個(gè)從庫,一共 9 個(gè)從庫承載每秒 1.8 萬的讀請求。
這樣的話,你可能就需要一共是 12 臺高配置的數(shù)據(jù)庫服務(wù)器,這是很耗費(fèi)錢的,成本非常高,而且很不合適。
大家看看下面的圖,來體會(huì)下這種情況:
所以,此時(shí)你完全就可以把平時(shí)不太變化的數(shù)據(jù)放在緩存集群里,緩存集群可以采用 2 主 2 從,主節(jié)點(diǎn)用來寫入緩存,從節(jié)點(diǎn)用來讀緩存。
以緩存集群的性能,2 個(gè)從節(jié)點(diǎn)完全可以用來承載每秒 1.8 萬的大量讀了,然后 3 個(gè)數(shù)據(jù)庫主庫就是承載每秒 2000 的寫請求和少量其他讀請求就可以了。
大家看看下面的圖,你耗費(fèi)的機(jī)器瞬間變成了 4 臺緩存機(jī)器 + 3 臺數(shù)據(jù)庫機(jī)器 = 7 臺機(jī)器,是不是比之前的 12 臺機(jī)器減少了很大的資源開銷?
沒錯(cuò),緩存其實(shí)在系統(tǒng)架構(gòu)里是非常重要的組成部分。很多時(shí)候,對于那些很少變化但是大量高并發(fā)讀的數(shù)據(jù),通過緩存集群來抗高并發(fā)讀,是非常合適的。
這里所有的機(jī)器數(shù)量、并發(fā)請求量都是一個(gè)示例,大家主要是體會(huì)一下這個(gè)意思就好,其目的主要是給一些不太熟悉緩存相關(guān)技術(shù)的同學(xué)一點(diǎn)背景性的闡述,讓這些同學(xué)能夠理解在系統(tǒng)里用緩存集群承載讀請求是什么意思。
20 萬用戶同時(shí)訪問一個(gè)熱點(diǎn)緩存的問題
好了,背景是已經(jīng)給大家解釋清楚了,那么現(xiàn)在就可以給大家說說今天重點(diǎn)要討論的問題:熱點(diǎn)緩存。
我們來做一個(gè)假設(shè),你現(xiàn)在有 10 個(gè)緩存節(jié)點(diǎn)來抗大量的讀請求。正常情況下,讀請求應(yīng)該是均勻的落在 10 個(gè)緩存節(jié)點(diǎn)上的,對吧!
這 10 個(gè)緩存節(jié)點(diǎn),每秒承載 1 萬請求是差不多的。然后我們再做一個(gè)假設(shè),你一個(gè)節(jié)點(diǎn)承載 2 萬請求是極限,所以一般你就限制一個(gè)節(jié)點(diǎn)正常承載 1 萬請求就 OK 了,稍微留一點(diǎn) Buffer 出來。
好,所謂的熱點(diǎn)緩存問題是什么意思呢?很簡單,就是突然因?yàn)槟脑?,出現(xiàn)大量的用戶訪問同一條緩存數(shù)據(jù)。
舉個(gè)例子,某個(gè)明星突然宣布跟某某結(jié)婚,這個(gè)時(shí)候是不是會(huì)引發(fā)可能短時(shí)間內(nèi)每秒都是數(shù)十萬的用戶去查看這個(gè)明星跟某某結(jié)婚的那條新聞?
那么假設(shè)那條新聞就是一個(gè)緩存,然后對應(yīng)就是一個(gè)緩存 Key,就存在一臺緩存機(jī)器上,此時(shí)瞬時(shí)假設(shè)有 20 萬請求奔向那一臺機(jī)器上的一個(gè) Key。
此時(shí)會(huì)如何?我們看看下面的圖,來體會(huì)一下這種絕望的感受:
這個(gè)時(shí)候很明顯了,我們剛才假設(shè)的是一個(gè)緩存 Slave 節(jié)點(diǎn)最多每秒就是 2 萬的請求,當(dāng)然實(shí)際緩存單機(jī)承載 5 萬~10 萬讀請求也是可能的,我們這里就是一個(gè)假設(shè)。
結(jié)果此時(shí),每秒突然奔過來 20 萬請求到這臺機(jī)器上,會(huì)怎么樣?很簡單,上面圖里那臺被 20 萬請求指向的緩存機(jī)器會(huì)過度操勞而宕機(jī)的。
那么如果緩存集群開始出現(xiàn)機(jī)器的宕機(jī),此時(shí)會(huì)如何?接著,讀請求發(fā)現(xiàn)讀不到數(shù)據(jù),會(huì)從數(shù)據(jù)庫里提取原始數(shù)據(jù),然后放入剩余的其他緩存機(jī)器里去。
但是接踵而來的每秒 20 萬請求,會(huì)再次壓垮其他的緩存機(jī)器。以此類推,最終導(dǎo)致緩存集群全盤崩潰,引發(fā)系統(tǒng)整體宕機(jī)。
咱們看看下面的圖,再感受一下這個(gè)恐怖的現(xiàn)場:
基于流式計(jì)算技術(shù)的緩存熱點(diǎn)自動(dòng)發(fā)現(xiàn)
其實(shí)這里關(guān)鍵的一點(diǎn),就是對于這種熱點(diǎn)緩存,你的系統(tǒng)需要能夠在熱點(diǎn)緩存突然發(fā)生的時(shí)候,直接發(fā)現(xiàn)他,然后瞬間立馬實(shí)現(xiàn)毫秒級的自動(dòng)負(fù)載均衡。
那么我們就先來說說,你如何自動(dòng)發(fā)現(xiàn)熱點(diǎn)緩存問題?首先你要知道,一般出現(xiàn)緩存熱點(diǎn)的時(shí)候,你的每秒并發(fā)肯定是很高的,可能每秒都幾十萬甚至上百萬的請求量過來,這都是有可能的。
所以,此時(shí)完全可以基于大數(shù)據(jù)領(lǐng)域的流式計(jì)算技術(shù)來進(jìn)行實(shí)時(shí)數(shù)據(jù)訪問次數(shù)的統(tǒng)計(jì),比如 Storm、Spark Streaming、Flink,這些技術(shù)都是可以的。
然后一旦在實(shí)時(shí)數(shù)據(jù)訪問次數(shù)統(tǒng)計(jì)的過程中,比如發(fā)現(xiàn)一秒之內(nèi),某條數(shù)據(jù)突然訪問次數(shù)超過了 1000,就直接立馬把這條數(shù)據(jù)判定為是熱點(diǎn)數(shù)據(jù),可以將這個(gè)發(fā)現(xiàn)出來的熱點(diǎn)數(shù)據(jù)寫入比如 Zookeeper 中。
當(dāng)然,你的系統(tǒng)如何判定熱點(diǎn)數(shù)據(jù),可以根據(jù)自己的業(yè)務(wù)還有經(jīng)驗(yàn)值來就可以了。
大家看看下面這張圖,看看整個(gè)流程是如何進(jìn)行的:
當(dāng)然肯定有人會(huì)問,那你的流式計(jì)算系統(tǒng)在進(jìn)行數(shù)據(jù)訪問次數(shù)統(tǒng)計(jì)的時(shí)候,會(huì)不會(huì)也存在說單臺機(jī)器被請求每秒幾十萬次的問題呢?
答案是否,因?yàn)榱魇接?jì)算技術(shù),尤其是 Storm 這種系統(tǒng),他可以做到同一條數(shù)據(jù)的請求過來,先分散在很多機(jī)器里進(jìn)行本地計(jì)算,***再匯總局部計(jì)算結(jié)果到一臺機(jī)器進(jìn)行全局匯總。
所以幾十萬請求可以先分散在比如 100 臺機(jī)器上,每臺機(jī)器統(tǒng)計(jì)了這條數(shù)據(jù)的幾千次請求。
然后 100 條局部計(jì)算好的結(jié)果匯總到一臺機(jī)器做全局計(jì)算即可,所以基于流式計(jì)算技術(shù)來進(jìn)行統(tǒng)計(jì)是不會(huì)有熱點(diǎn)問題的。
熱點(diǎn)緩存自動(dòng)加載為 JVM 本地緩存
我們自己的系統(tǒng)可以對 Zookeeper 指定的熱點(diǎn)緩存對應(yīng)的 Znode 進(jìn)行監(jiān)聽,如果有變化他立馬就可以感知到了。
此時(shí)系統(tǒng)層就可以立馬把相關(guān)的緩存數(shù)據(jù)從數(shù)據(jù)庫加載出來,然后直接放在自己系統(tǒng)內(nèi)部的本地緩存里即可。
這個(gè)本地緩存,你用 Ehcache、Hashmap,其實(shí)都可以,一切都看自己的業(yè)務(wù)需求,主要說的就是將緩存集群里的集中式緩存,直接變成每個(gè)系統(tǒng)自己本地實(shí)現(xiàn)緩存即可,每個(gè)系統(tǒng)自己本地是無法緩存過多數(shù)據(jù)的。
因?yàn)橐话氵@種普通系統(tǒng)單實(shí)例部署機(jī)器可能就一個(gè) 4 核 8G 的機(jī)器,留給本地緩存的空間是很少的,所以用來放這種熱點(diǎn)數(shù)據(jù)的本地緩存是最合適的,剛剛好。
假設(shè)你的系統(tǒng)層集群部署了 100 臺機(jī)器,那么好了,此時(shí)你 100 臺機(jī)器瞬間在本地都會(huì)有一份熱點(diǎn)緩存的副本。
然后接下來對熱點(diǎn)緩存的讀操作,直接系統(tǒng)本地緩存讀出來就給返回了,不用再走緩存集群了。
這樣的話,也不可能允許每秒 20 萬的讀請求到達(dá)緩存機(jī)器的一臺機(jī)器上讀一個(gè)熱點(diǎn)緩存了,而是變成 100 臺機(jī)器每臺機(jī)器承載數(shù)千請求,那么那數(shù)千請求就直接從機(jī)器本地緩存返回?cái)?shù)據(jù)了,這是沒有問題的。
我們再來畫一幅圖,一起來看看這個(gè)過程:
限流熔斷保護(hù)
除此之外,在每個(gè)系統(tǒng)內(nèi)部,還應(yīng)該專門加一個(gè)對熱點(diǎn)數(shù)據(jù)訪問的限流熔斷保護(hù)措施。
每個(gè)系統(tǒng)實(shí)例內(nèi)部,都可以加一個(gè)熔斷保護(hù)機(jī)制,假設(shè)緩存集群最多每秒承載4萬讀請求,那么你一共有 100 個(gè)系統(tǒng)實(shí)例。
你自己就該限制好,每個(gè)系統(tǒng)實(shí)例每秒最多請求緩存集群讀操作不超過 400 次,一超過就可以熔斷掉,不讓請求緩存集群,直接返回一個(gè)空白信息,然后用戶稍后會(huì)自行再次重新刷新頁面之類的。
通過系統(tǒng)層自己直接加限流熔斷保護(hù)措施,可以很好的保護(hù)后面的緩存集群、數(shù)據(jù)庫集群之類的不要被打死,我們來看看下面的圖:
總結(jié)
具體要不要在系統(tǒng)里實(shí)現(xiàn)這種復(fù)雜的緩存熱點(diǎn)優(yōu)化架構(gòu)呢?這個(gè)還要看你們自己的系統(tǒng)有沒有這種場景了。
如果你的系統(tǒng)有熱點(diǎn)緩存問題,那么就要實(shí)現(xiàn)類似本文的復(fù)雜熱點(diǎn)緩存支撐架構(gòu)。
但是如果沒有的話,那么也別過度設(shè)計(jì),其實(shí)你的系統(tǒng)可能根本不需要這么復(fù)雜的架構(gòu)。
以上就是用戶訪問一個(gè)熱Key該如何優(yōu)化緩存架構(gòu),小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。