chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何對(duì)靜態(tài)數(shù)據(jù)做緩存

馬哥Linux運(yùn)維 ? 來源:馬哥Linux運(yùn)維 ? 作者:馬哥Linux運(yùn)維 ? 2022-07-04 11:34 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1. Overview

1.1 并發(fā)讀寫

秒殺要解決的主要問題是:并發(fā)讀與并發(fā)寫。

并發(fā)讀的優(yōu)化理念是盡量減少用戶到服務(wù)端來讀數(shù)據(jù),或者讓他們讀更少的數(shù)據(jù);并發(fā)寫的處理原則一樣,要求我們?cè)跀?shù)據(jù)庫層面獨(dú)立出一個(gè)庫,做特殊的處理。

其次,還需要針對(duì)秒殺系統(tǒng)做一些保護(hù),針對(duì)意料之外的情況設(shè)計(jì)兜底方案,以防止最壞的情況發(fā)生。

1.2 API設(shè)計(jì)原則

值得注意的地方是:如果想打造并維護(hù)一個(gè)超大流量并發(fā)讀寫、高性能、高可用的系統(tǒng),在整個(gè)用戶請(qǐng)求路徑上從瀏覽器到服務(wù)端我們要遵循幾個(gè)原則,就是保證**用戶請(qǐng)求的數(shù)據(jù)盡量少、請(qǐng)求數(shù)盡量少、路徑盡量短、依賴盡量少,不要有單點(diǎn)**

1.3 秒殺架構(gòu)原則

1.3.1 高可用

整個(gè)系統(tǒng)架構(gòu)需要滿足高可用性,流量符合預(yù)期的時(shí)候肯定要穩(wěn)定,就是超出預(yù)期也同樣不能掉鏈子,保證秒殺產(chǎn)品順利賣出。

1.3.2 一致性

數(shù)據(jù)必須一致,即成交總量必須和設(shè)定的數(shù)量一致。

1.3.3 高可用

系統(tǒng)的性能要足夠強(qiáng),支撐足夠大的流量,不僅是服務(wù)端要做極致的性能優(yōu)化,而且在整個(gè)請(qǐng)求鏈路上都要做協(xié)同的優(yōu)化,每個(gè)地方都要快一點(diǎn),整個(gè)系統(tǒng)就完美了。

本文將從這三個(gè)原則上來分別進(jìn)行詳細(xì)說明。

2. 架構(gòu)原則

秒殺系統(tǒng)本質(zhì)上是一個(gè)滿足大并發(fā)、高性能和高可用的分布式系統(tǒng)。

2.1 數(shù)據(jù)盡量少

用戶請(qǐng)求的數(shù)據(jù)能少就少,請(qǐng)求的數(shù)據(jù)包括上傳給系統(tǒng)的數(shù)據(jù)和系統(tǒng)返回給用戶的數(shù)據(jù)。

因?yàn)檫@些數(shù)據(jù)在網(wǎng)絡(luò)上傳輸需要時(shí)間,其次不管是請(qǐng)求數(shù)據(jù)還是返回?cái)?shù)據(jù)都需要服務(wù)器處理,而服務(wù)器在寫網(wǎng)絡(luò)的時(shí)候通常都要做壓縮和字符編碼,這些都非常消耗CPU,所以減少傳輸?shù)臄?shù)據(jù)量可以顯著減少CPU的使用。

同樣,數(shù)據(jù)盡量少還要求系統(tǒng)依賴的數(shù)據(jù)能少就少,包括系統(tǒng)完成某些業(yè)務(wù)邏輯需要讀取和保存的數(shù)據(jù),這些數(shù)據(jù)一般是和后臺(tái)服務(wù)以及數(shù)據(jù)庫打交道的。調(diào)用其他服務(wù)會(huì)涉及數(shù)據(jù)的序列化和反序列化,這也是CPU的一大殺手,同樣也會(huì)增加延時(shí)。而且數(shù)據(jù)庫本身也很容易成為瓶頸,因此越少和數(shù)據(jù)庫打交道越好。

2.2 請(qǐng)求數(shù)盡量少

用戶請(qǐng)求的頁面返回后,瀏覽器渲染這個(gè)頁面還要包含其他的額外請(qǐng)求,比如說,這個(gè)頁面依賴的 CSS/JavaScript、圖片,以及 Ajax 請(qǐng)求等等都定義為“額外請(qǐng)求”,這些額外請(qǐng)求應(yīng)該盡量少。因?yàn)闉g覽器每發(fā)出一個(gè)請(qǐng)求都多少會(huì)有一些消耗,例如建立連接要做三次握手,有的時(shí)候有頁面依賴或者連接數(shù)限制,一些請(qǐng)求(例如 JavaScript)還需要串行加載等。另外,如果不同請(qǐng)求的域名不一樣的話,還涉及這些域名的 DNS 解析,可能會(huì)耗時(shí)更久。所以你要記住的是,減少請(qǐng)求數(shù)可以顯著減少以上這些因素導(dǎo)致的資源消耗。

例如,減少請(qǐng)求數(shù)最常用的一個(gè)實(shí)踐就是合并 CSS 和 JavaScript 文件,把多個(gè) JavaScript 文件合并成一個(gè)文件,在 URL 中用逗號(hào)隔開([https://g.xxx.com/tm/xx-b/4.0.94/mods/??module-preview/index.xtpl.js,module-jhs/index.xtpl.js,module-focus/index.xtpl.js](https://g.xxx.com/tm/xx-b/4.0.94/mods/??module-preview/index.xtpl.js,module-jhs/index.xtpl.js,module-focus/index.xtpl.js))。這種方式在服務(wù)端仍然是單個(gè)文件各自存放,只是服務(wù)端會(huì)有一個(gè)組件解析這個(gè) URL,然后動(dòng)態(tài)把這些文件合并起來一起返回。

2.3 路徑要盡量短

路徑指的是用戶發(fā)出請(qǐng)求到返回?cái)?shù)據(jù)這個(gè)過程中需要經(jīng)過的中間節(jié)點(diǎn)的數(shù)量。

通常,這些節(jié)點(diǎn)可以表示為一個(gè)系統(tǒng)或者一個(gè)新的 Socket 連接(比如代理服務(wù)器只是創(chuàng)建一個(gè)新的 Socket 連接來轉(zhuǎn)發(fā)請(qǐng)求)。每經(jīng)過一個(gè)節(jié)點(diǎn),一般都會(huì)產(chǎn)生一個(gè)新的 Socket 連接。

然而,每增加一個(gè)連接都會(huì)增加新的不確定性。從概率統(tǒng)計(jì)上來說,假如一次請(qǐng)求經(jīng)過 5 個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)的可用性是 99.9% 的話,那么整個(gè)請(qǐng)求的可用性是:99.9% 的 5 次方,約等于 99.5%。

所以縮短請(qǐng)求路徑不僅可以增加可用性,同樣可以有效提升性能(減少中間節(jié)點(diǎn)可以減少數(shù)據(jù)的序列化與反序列化),并減少延時(shí)(可以減少網(wǎng)絡(luò)傳輸耗時(shí))。

要縮短訪問路徑可以將多個(gè)相互有強(qiáng)依賴的應(yīng)用合并部署在一起,將遠(yuǎn)程過程調(diào)用變成JVM內(nèi)部的方法調(diào)用。

2.4 依賴要盡量少

所謂依賴,指的是要完成一次用戶請(qǐng)求必須依賴的系統(tǒng)或者服務(wù)。

舉個(gè)例子,比如說你要展示秒殺頁面,而這個(gè)頁面必須強(qiáng)依賴商品信息、用戶信息,還有其他如優(yōu)惠券、成交列表等這些對(duì)秒殺不是非要不可的信息(弱依賴),這些弱依賴在緊急情況下就可以去掉。

要減少依賴,我們可以給系統(tǒng)進(jìn)行分級(jí),比如 0 級(jí)系統(tǒng)、1 級(jí)系統(tǒng)、2 級(jí)系統(tǒng)、3 級(jí)系統(tǒng),0 級(jí)系統(tǒng)如果是最重要的系統(tǒng),那么 0 級(jí)系統(tǒng)強(qiáng)依賴的系統(tǒng)也同樣是最重要的系統(tǒng),以此類推。

注意,0 級(jí)系統(tǒng)要盡量減少對(duì) 1 級(jí)系統(tǒng)的強(qiáng)依賴,防止重要的系統(tǒng)被不重要的系統(tǒng)拖垮。例如支付系統(tǒng)是 0 級(jí)系統(tǒng),而優(yōu)惠券是 1 級(jí)系統(tǒng)的話,在極端情況下可以把優(yōu)惠券給降級(jí),防止支付系統(tǒng)被優(yōu)惠券這個(gè) 1 級(jí)系統(tǒng)給拖垮。

2.5 不要有單點(diǎn)

不能有單點(diǎn),因?yàn)閱吸c(diǎn)意味著沒有備份,風(fēng)險(xiǎn)不可控,設(shè)計(jì)分布式系統(tǒng)的一個(gè)最重要的原則就是消除單點(diǎn)。

如何避免單點(diǎn)?—-> 避免將服務(wù)的狀態(tài)和機(jī)器綁定,即把服務(wù)無狀態(tài)化,這樣服務(wù)就可以在機(jī)器中隨意移動(dòng)了。

如何那把服務(wù)的狀態(tài)和機(jī)器解耦呢?這里也有很多實(shí)現(xiàn)方式。例如把和機(jī)器相關(guān)的配置動(dòng)態(tài)化,這些參數(shù)可以通過配置中心來動(dòng)態(tài)推送,在服務(wù)啟動(dòng)時(shí)動(dòng)態(tài)拉取下來,我們?cè)谶@些配置中心設(shè)置一些規(guī)則來方便地改變這些映射關(guān)系。

應(yīng)用無狀態(tài)化是有效避免單點(diǎn)的一種方式,但是像存儲(chǔ)服務(wù)本身很難無狀態(tài)化,因?yàn)閿?shù)據(jù)要存儲(chǔ)在磁盤上,本身就要和機(jī)器綁定,那么這種場景一般要通過冗余多個(gè)備份的方式來解決單點(diǎn)問題。

3. 不同場景下的不同架構(gòu)案例

如果你想快速搭建一個(gè)簡單的秒殺系統(tǒng),只需要把你的商品購買頁面增加一個(gè)“定時(shí)上架”功能,僅在秒殺開始時(shí)才讓用戶看到購買按鈕,當(dāng)商品的庫存賣完了也就結(jié)束了。這就是當(dāng)時(shí)第一個(gè)版本的秒殺系統(tǒng)實(shí)現(xiàn)方式。

但隨著請(qǐng)求量的加大(比如從 1w/s 到了 10w/s 的量級(jí)),這個(gè)簡單的架構(gòu)很快就遇到了瓶頸,因此需要做架構(gòu)改造來提升系統(tǒng)性能。這些架構(gòu)改造包括:

把秒殺系統(tǒng)獨(dú)立出來單獨(dú)打造一個(gè)系統(tǒng),這樣可以有針對(duì)性地做優(yōu)化,例如這個(gè)獨(dú)立出來的系統(tǒng)就減少了店鋪裝修的功能,減少了頁面的復(fù)雜度;

在系統(tǒng)部署上也獨(dú)立做一個(gè)機(jī)器集群,這樣秒殺的大流量就不會(huì)影響到正常的商品購買集群的機(jī)器負(fù)載;

將熱點(diǎn)數(shù)據(jù)(如庫存數(shù)據(jù))單獨(dú)放到一個(gè)緩存系統(tǒng)中,以提高“讀性能”;

增加秒殺答題,防止有秒殺器搶單。

此時(shí)秒殺已經(jīng)成為了一個(gè)獨(dú)立的新系統(tǒng),另外核心的一些數(shù)據(jù)放到了緩存當(dāng)中,其他的關(guān)聯(lián)系統(tǒng)也都以獨(dú)立集群的方式進(jìn)行部署。

438e0a4a-f947-11ec-ba43-dac502259ad0.png

fig1.jpg

但是這個(gè)架構(gòu)仍然無法支持超過100w/s的請(qǐng)求量,因此為了進(jìn)一步提高秒殺系統(tǒng)的性能,又對(duì)架構(gòu)做了進(jìn)一步的升級(jí),比如:

對(duì)頁面進(jìn)行徹底的動(dòng)靜分離,使得用戶秒殺時(shí)不需要刷新整個(gè)頁面,而只需要點(diǎn)擊搶寶按鈕,借此把頁面刷新的數(shù)據(jù)降到最少;

在服務(wù)端對(duì)秒殺商品進(jìn)行本地緩存,不需要再調(diào)用依賴系統(tǒng)的后臺(tái)服務(wù)獲取數(shù)據(jù),甚至不需要去公共的緩存集群中查詢數(shù)據(jù),這樣不僅可以減少系統(tǒng)調(diào)用,而且能夠避免壓垮公共緩存集群。

增加系統(tǒng)限流保護(hù),防止最壞的情況發(fā)生

此時(shí)整個(gè)系統(tǒng)架構(gòu)變成了這個(gè)樣子,已經(jīng)對(duì)頁面進(jìn)行了進(jìn)一步的靜態(tài)化,秒殺過程當(dāng)中就不需要刷新整個(gè)頁面了,只需要向服務(wù)端請(qǐng)求很少的動(dòng)態(tài)數(shù)據(jù)。而且最關(guān)鍵的詳情和交易系統(tǒng)都增加了本地緩存,來提前緩存秒殺商品的信息,熱點(diǎn)數(shù)據(jù)庫也做了獨(dú)立部署。

43d0079c-f947-11ec-ba43-dac502259ad0.png

fig2.jpg

從前面的幾次升級(jí)來看,其實(shí)越到后面需要定制的地方越多,也就是越“不通用”。例如,把秒殺商品緩存在每臺(tái)機(jī)器的內(nèi)存中,這種方式顯然不適合太多的商品同時(shí)進(jìn)行秒殺的情況,因?yàn)閱螜C(jī)的內(nèi)存始終有限。所以要取得極致的性能,就要在其他地方(比如,通用性、易用性、成本等方面)有所犧牲。

4. 動(dòng)靜分離的方案

秒殺系統(tǒng)需要讓請(qǐng)求效率足夠高 - 提高單次請(qǐng)求的效率,減少?zèng)]必要的請(qǐng)求。

4.1 何為動(dòng)靜數(shù)據(jù)

將用戶請(qǐng)求的數(shù)據(jù)(如HTML)劃分為動(dòng)態(tài)數(shù)據(jù)和靜態(tài)數(shù)據(jù)。而動(dòng)態(tài)靜態(tài)數(shù)據(jù)的劃分,在于看頁面中輸出的數(shù)據(jù)是否和URL,瀏覽者,時(shí)間,地域相關(guān),以及是否含有Cookie等私密數(shù)據(jù)。

對(duì)很多媒體類的網(wǎng)站來說,無論誰來看文章,展示的數(shù)據(jù)都是一樣的,那么哪怕這是個(gè)動(dòng)態(tài)頁面,它仍然是個(gè)典型的靜態(tài)數(shù)據(jù)。

訪問淘寶的首頁,每個(gè)人看到的頁面可能都是不一樣的,其中包含了很多根據(jù)訪問者個(gè)人信息進(jìn)行的推薦,這些個(gè)性化的數(shù)據(jù)就稱為動(dòng)態(tài)數(shù)據(jù)。

這里再強(qiáng)調(diào)一下,我們所說的靜態(tài)數(shù)據(jù),不能僅僅理解為傳統(tǒng)意義上完全存在磁盤上的 HTML 頁面,它也可能是經(jīng)過 Java 系統(tǒng)產(chǎn)生的頁面,但是它輸出的頁面本身不包含上面所說的那些因素。也就是所謂“動(dòng)態(tài)”還是“靜態(tài)”,并不是說數(shù)據(jù)本身是否動(dòng)靜,而是數(shù)據(jù)中是否含有和訪問者相關(guān)的個(gè)性化數(shù)據(jù)。

這樣做動(dòng)靜分離的時(shí)候,我們就可以對(duì)分離出來的靜態(tài)數(shù)據(jù)做緩存,有了緩存以后,靜態(tài)數(shù)據(jù)的訪問效率肯定就提高了。

4.2 如何對(duì)靜態(tài)數(shù)據(jù)做緩存?

4.2.1 距離用戶最近

將靜態(tài)數(shù)據(jù)緩存到離用戶最近的地方。靜態(tài)數(shù)據(jù)就是那些相對(duì)不會(huì)變化的數(shù)據(jù),因此可以做緩存。常見的,我們可以緩存在:

用戶瀏覽器

CDN上

服務(wù)端的Cache中

4.2.2 靜態(tài)化改造要直接緩存HTTP連接

系統(tǒng)的靜態(tài)化改造是直接緩存HTTP連接而不僅僅是數(shù)據(jù)了。如下圖所示,Web代理服務(wù)器根據(jù)請(qǐng)求URL直接去除對(duì)應(yīng)的HTTP響應(yīng)頭和響應(yīng)體然后直接返回,這個(gè)響應(yīng)過程連HTTP協(xié)議都不用重新組裝,甚至連HTTP請(qǐng)求頭也不需要解析。

43ff4214-f947-11ec-ba43-dac502259ad0.png

fig3.jpg

4.2.3 緩存語言

不同語言寫的cache軟件處理緩存數(shù)據(jù)的效率也各不相同。以Java為例,Java不擅長處理大量連接請(qǐng)求,每個(gè)連接消耗的內(nèi)存會(huì)比較多,Servlet容器解析HTTP協(xié)議比較慢。所以可以不在Java層做緩存,而是直接在Web服務(wù)器層上做,這樣就可以屏蔽Java的一些弱點(diǎn);而相比起來,Web服務(wù)器(Nginx, Apache, Varnish)會(huì)更加擅長處理大并發(fā)的靜態(tài)文件請(qǐng)求。

4.3 靜態(tài)數(shù)據(jù)處理方案

以商品詳情頁為例:

4.3.1 URL唯一化

要緩存整個(gè)HTTP連接,以URL作為緩存的key

4.3.2 分離瀏覽者相關(guān)的因素

分離用戶的相關(guān)信息,是否登錄以及登錄身份等等。

4.3.3 分離時(shí)間因素

服務(wù)端輸出的是哪也通過動(dòng)態(tài)請(qǐng)求獲取

4.3.4 異步化地域因素

詳情頁面上與地域相關(guān)的因素做成異步獲取的方式

4.3.5 去掉Cookie

服務(wù)端輸出的頁面包含的 Cookie 可以通過代碼軟件來刪除,如 Web 服務(wù)器 Varnish 可以通過 unset req.http.cookie 命令去掉 Cookie。注意,這里說的去掉 Cookie 并不是用戶端收到的頁面就不含 Cookie 了,而是說,在緩存的靜態(tài)數(shù)據(jù)中不含有 Cookie。

4.4 動(dòng)態(tài)數(shù)據(jù)處理方案

4.4.1 ESI (Edge Side Includes)

在Web代理服務(wù)器上做動(dòng)態(tài)內(nèi)容請(qǐng)求,并將請(qǐng)求插入到靜態(tài)頁面中,當(dāng)用戶拿到頁面時(shí)已經(jīng)是一個(gè)完整的頁面了。對(duì)服務(wù)端性能有影響,但是用戶體驗(yàn)會(huì)比較好

4.4.2 CSI (Client Side Include)

單獨(dú)發(fā)出異步Javascript請(qǐng)求,向服務(wù)端獲取動(dòng)態(tài)內(nèi)容。這種方式服務(wù)端性能更好,但是用戶端可能會(huì)有延時(shí),體驗(yàn)會(huì)差一些

4.5 動(dòng)靜分離架構(gòu)方案

4.5.1 實(shí)體機(jī)單機(jī)部署

這種方案是將虛擬機(jī)改為實(shí)體機(jī),以增大 Cache 的容量,并且采用了一致性 Hash 分組的方式來提升命中率。這里將 Cache 分成若干組,是希望能達(dá)到命中率和訪問熱點(diǎn)的平衡。Hash 分組越少,緩存的命中率肯定就會(huì)越高,但短板是也會(huì)使單個(gè)商品集中在一個(gè)分組中,容易導(dǎo)致 Cache 被擊穿,所以我們應(yīng)該適當(dāng)增加多個(gè)相同的分組,來平衡訪問熱點(diǎn)和命中率的問題。

Nginx+Cache+Java結(jié)構(gòu)實(shí)體機(jī)單機(jī)部署

441e0d8e-f947-11ec-ba43-dac502259ad0.png

fig4.jpg

這種部署方式有以下幾個(gè)優(yōu)點(diǎn):

沒有網(wǎng)絡(luò)瓶頸,而且能使用大內(nèi)存;

既能提升命中率,又能減少 Gzip 壓縮;

減少 Cache 失效壓力,因?yàn)椴捎枚〞r(shí)失效方式,例如只緩存 3 秒鐘,過期即自動(dòng)失效。

這個(gè)方案中,雖然把通常只需要虛擬機(jī)或者容器運(yùn)行的 Java 應(yīng)用換成實(shí)體機(jī),優(yōu)勢(shì)很明顯,它會(huì)增加單機(jī)的內(nèi)存容量,但是一定程度上也造成了 CPU 的浪費(fèi),因?yàn)閱蝹€(gè)的 Java 進(jìn)程很難用完整個(gè)實(shí)體機(jī)的 CPU。

另外就是,一個(gè)實(shí)體機(jī)上部署了 Java 應(yīng)用又作為 Cache 來使用,這造成了運(yùn)維上的高復(fù)雜度,所以這是一個(gè)折中的方案。如果你的公司里,沒有更多的系統(tǒng)有類似需求,那么這樣做也比較合適,如果你們有多個(gè)業(yè)務(wù)系統(tǒng)都有靜態(tài)化改造的需求,那還是建議把 Cache 層單獨(dú)抽出來公用比較合理,如下面的方案 2 所示。

4.5.2 統(tǒng)一Cache層

所謂統(tǒng)一 Cache 層,就是將單機(jī)的 Cache 統(tǒng)一分離出來,形成一個(gè)單獨(dú)的 Cache 集群。統(tǒng)一 Cache 層是個(gè)更理想的可推廣方案,該方案的結(jié)構(gòu)圖如下:

442d77ce-f947-11ec-ba43-dac502259ad0.png

fig5.jpg

統(tǒng)一Cache層,可以減少運(yùn)維成本,也方便接入其他靜態(tài)化系統(tǒng),還有以下優(yōu)點(diǎn):

單獨(dú)一個(gè) Cache 層,可以減少多個(gè)應(yīng)用接入時(shí)使用 Cache 的成本。這樣接入的應(yīng)用只要維護(hù)自己的 Java 系統(tǒng)就好,不需要單獨(dú)維護(hù) Cache,而只關(guān)心如何使用即可。

統(tǒng)一 Cache 的方案更易于維護(hù),如后面加強(qiáng)監(jiān)控、配置的自動(dòng)化,只需要一套解決方案就行,統(tǒng)一起來維護(hù)升級(jí)也比較方便。

可以共享內(nèi)存,最大化利用內(nèi)存,不同系統(tǒng)之間的內(nèi)存可以動(dòng)態(tài)切換,從而能夠有效應(yīng)對(duì)各種攻擊。

這種方案也會(huì)帶來一些問題。比如:

Cache 層內(nèi)部交換網(wǎng)絡(luò)成為瓶頸;

緩存服務(wù)器的網(wǎng)卡也會(huì)是瓶頸;

機(jī)器少風(fēng)險(xiǎn)較大,掛掉一臺(tái)就會(huì)影響很大一部分緩存數(shù)據(jù)。

要解決上面這些問題,可以再對(duì) Cache 做 Hash 分組,即一組 Cache 緩存的內(nèi)容相同,這樣能夠避免熱點(diǎn)數(shù)據(jù)過度集中導(dǎo)致新的瓶頸產(chǎn)生。

4.5.3 使用CDN

在將整個(gè)系統(tǒng)做動(dòng)靜分離后,我們自然會(huì)想到更進(jìn)一步的方案,就是將 Cache 進(jìn)一步前移到 CDN 上,因?yàn)?CDN 離用戶最近,效果會(huì)更好。

有幾個(gè)問題需要解決:

失效問題

前面我們也有提到過緩存時(shí)效的問題,不知道你有沒有理解,我再來解釋一下。談到靜態(tài)數(shù)據(jù)時(shí),我說過一個(gè)關(guān)鍵詞叫“相對(duì)不變”,它的言外之意是“可能會(huì)變化”。比如一篇文章,現(xiàn)在不變,但如果你發(fā)現(xiàn)個(gè)錯(cuò)別字,是不是就會(huì)變化了?如果你的緩存時(shí)效很長,那用戶端在很長一段時(shí)間內(nèi)看到的都是錯(cuò)的。所以,這個(gè)方案中也是,我們需要保證 CDN 可以在秒級(jí)時(shí)間內(nèi),讓分布在全國各地的 Cache 同時(shí)失效,這對(duì) CDN 的失效系統(tǒng)要求很高。

命中率問題

Cache 最重要的一個(gè)衡量指標(biāo)就是“高命中率”,不然 Cache 的存在就失去了意義。同樣,如果將數(shù)據(jù)全部放到全國的 CDN 上,必然導(dǎo)致 Cache 分散,而 Cache 分散又會(huì)導(dǎo)致訪問請(qǐng)求命中同一個(gè) Cache 的可能性降低,那么命中率就成為一個(gè)問題。

發(fā)布更新問題

如果一個(gè)業(yè)務(wù)系統(tǒng)每周都有日常業(yè)務(wù)需要發(fā)布,那么發(fā)布系統(tǒng)必須足夠簡潔高效,而且你還要考慮有問題時(shí)快速回滾和排查問題的簡便性。

從前面的分析來看,將商品詳情系統(tǒng)放到全國的所有 CDN 節(jié)點(diǎn)上是不太現(xiàn)實(shí)的,因?yàn)榇嬖谑栴}、命中率問題以及系統(tǒng)的發(fā)布更新問題。那么是否可以選擇若干個(gè)節(jié)點(diǎn)來嘗試實(shí)施呢?答案是“可以”,但是這樣的節(jié)點(diǎn)需要滿足幾個(gè)條件:

靠近訪問量比較集中的地區(qū)

離主站相對(duì)較遠(yuǎn)

節(jié)點(diǎn)到主站間的網(wǎng)絡(luò)比較好,比較穩(wěn)定

節(jié)點(diǎn)容量大,不會(huì)占用其他CDN太多的資源

基于上面幾個(gè)因素,選擇 CDN 的二級(jí) Cache 比較合適,因?yàn)槎?jí) Cache 數(shù)量偏少,容量也更大,讓用戶的請(qǐng)求先回源的 CDN 的二級(jí) Cache 中,如果沒命中再回源站獲取數(shù)據(jù),部署方式如下圖所示:

4443c664-f947-11ec-ba43-dac502259ad0.png

fig6.jpg

使用 CDN 的二級(jí) Cache 作為緩存,可以達(dá)到和當(dāng)前服務(wù)端靜態(tài)化 Cache 類似的命中率,因?yàn)楣?jié)點(diǎn)數(shù)不多,Cache 不是很分散,訪問量也比較集中,這樣也就解決了命中率問題,同時(shí)能夠給用戶最好的訪問體驗(yàn),是當(dāng)前比較理想的一種 CDN 化方案。

5. 如何處理熱點(diǎn)數(shù)據(jù)

有一部分?jǐn)?shù)據(jù)是會(huì)被大量用戶訪問的熱賣商品,這部分商品是需要特殊關(guān)注的,因?yàn)槠鋾?huì)對(duì)系統(tǒng)產(chǎn)生一系列的影響。

首先,熱點(diǎn)請(qǐng)求會(huì)大量占用服務(wù)器處理資源,雖然這個(gè)熱點(diǎn)可能占總量的很小的一部分,然而卻可能搶占90%以上的服務(wù)器資源,如果這個(gè)熱點(diǎn)請(qǐng)求還是沒有價(jià)值的無效請(qǐng)求,那么對(duì)系統(tǒng)資源來說完全是浪費(fèi)。

5.1 什么是熱點(diǎn)

5.1.1 熱點(diǎn)操作

例如大量的刷新頁面,大量添加購物車,零點(diǎn)大量的下單等。這些操作可以抽象為“讀請(qǐng)求”和“寫請(qǐng)求”,這兩種請(qǐng)求的處理方式大相徑庭,讀請(qǐng)求的優(yōu)化空間比較大,而寫請(qǐng)求的瓶頸一般都在存儲(chǔ)層,優(yōu)化的思路就是根據(jù)CAP理論做平衡。

5.1.2 熱點(diǎn)數(shù)據(jù)

熱點(diǎn)數(shù)據(jù)就是用戶的熱點(diǎn)請(qǐng)求對(duì)應(yīng)的數(shù)據(jù),又可以分為靜態(tài)熱點(diǎn)數(shù)據(jù)和動(dòng)態(tài)熱點(diǎn)數(shù)據(jù)。

靜態(tài)熱點(diǎn)數(shù)據(jù),就是能夠提前預(yù)測(cè)的熱點(diǎn)數(shù)據(jù)。動(dòng)態(tài)熱點(diǎn)數(shù)據(jù),就是不能被提前預(yù)測(cè)到的,系統(tǒng)在運(yùn)行過程中臨時(shí)產(chǎn)生的熱點(diǎn)。

5.2 發(fā)現(xiàn)熱點(diǎn)數(shù)據(jù)

5.2.1 發(fā)現(xiàn)靜態(tài)熱點(diǎn)數(shù)據(jù)

如前面講的,靜態(tài)熱點(diǎn)數(shù)據(jù)可以通過商業(yè)手段,例如強(qiáng)制讓賣家通過報(bào)名參加的方式提前把熱點(diǎn)商品篩選出來,實(shí)現(xiàn)方式是通過一個(gè)運(yùn)營系統(tǒng),把參加活動(dòng)的商品數(shù)據(jù)進(jìn)行打標(biāo),然后通過一個(gè)后臺(tái)系統(tǒng)對(duì)這些熱點(diǎn)商品進(jìn)行預(yù)處理,如提前進(jìn)行緩存。但是這種通過報(bào)名提前篩選的方式也會(huì)帶來新的問題,即增加賣家的使用成本,而且實(shí)時(shí)性較差,也不太靈活。

不過,除了提前報(bào)名篩選這種方式,你還可以通過技術(shù)手段提前預(yù)測(cè),例如對(duì)買家每天訪問的商品進(jìn)行大數(shù)據(jù)計(jì)算,然后統(tǒng)計(jì)出 TOP N 的商品,我們可以認(rèn)為這些 TOP N 的商品就是熱點(diǎn)商品。

5.2.2 發(fā)現(xiàn)動(dòng)態(tài)熱點(diǎn)數(shù)據(jù)

具體實(shí)現(xiàn)

構(gòu)建異步系統(tǒng),用來收集交易鏈路上各個(gè)環(huán)節(jié)中的中間件產(chǎn)品的熱點(diǎn)Key,例如Nginx、緩存、RPC服務(wù)框架

建立一個(gè)熱點(diǎn)上報(bào)和可以按照需求訂閱的熱點(diǎn)服務(wù)的下發(fā)規(guī)范。因?yàn)榻灰祖溌飞细鱾€(gè)系統(tǒng)(包括詳情,購物車,交易,優(yōu)惠,庫存等等)會(huì)有訪問上的時(shí)間差,需要將上游已經(jīng)發(fā)現(xiàn)的熱點(diǎn)透傳給下游系統(tǒng),提前做好保護(hù)。例如,對(duì)于大促高峰期,詳情系統(tǒng)是最早知道的。

將上游系統(tǒng)收集的熱點(diǎn)數(shù)據(jù)發(fā)送到熱點(diǎn)服務(wù)臺(tái),讓下游系統(tǒng)提前知道信息,做熱電保護(hù)

44509268-f947-11ec-ba43-dac502259ad0.png

fig7.jpg

我們通過部署在每臺(tái)機(jī)器上的 Agent 把日志匯總到聚合和分析集群中,然后把符合一定規(guī)則的熱點(diǎn)數(shù)據(jù),通過訂閱分發(fā)系統(tǒng)再推送到相應(yīng)的系統(tǒng)中。你可以是把熱點(diǎn)數(shù)據(jù)填充到 Cache 中,或者直接推送到應(yīng)用服務(wù)器的內(nèi)存中,還可以對(duì)這些數(shù)據(jù)進(jìn)行攔截,總之下游系統(tǒng)可以訂閱這些數(shù)據(jù),然后根據(jù)自己的需求決定如何處理這些數(shù)據(jù)。

Tips:

熱點(diǎn)服務(wù)的后臺(tái)抓取熱點(diǎn)數(shù)據(jù)日志的方式最好采用異步的方式;可以保證通過性,不會(huì)影響業(yè)務(wù)系統(tǒng)和中間件產(chǎn)品的主流程。

熱點(diǎn)服務(wù)和中間件自身需要有熱電保護(hù)模塊,每個(gè)中間件和應(yīng)用和需要保護(hù)自己

熱點(diǎn)發(fā)現(xiàn)需要接近實(shí)時(shí),因?yàn)橹挥薪咏鼘?shí)時(shí)才有意義,能及時(shí)對(duì)下游系統(tǒng)提供保護(hù)

5.3 如何處理熱點(diǎn)數(shù)據(jù)

5.3.1 優(yōu)化

緩存熱點(diǎn)數(shù)據(jù),如果熱點(diǎn)數(shù)據(jù)做了動(dòng)靜分離,那么可以長期緩存靜態(tài)數(shù)據(jù)。

5.3.2 限制

保護(hù)機(jī)制,比如對(duì)商品的ASIN做一致性hash,然后根據(jù)hash做分桶,每個(gè)分桶處置一個(gè)處理隊(duì)列,通過這種方式將熱點(diǎn)商品限制在一個(gè)請(qǐng)求隊(duì)列當(dāng)中,防止因?yàn)槟承狳c(diǎn)商品占用太多的服務(wù)器資源,而使得其他請(qǐng)求始終得不到服務(wù)器的處理資源。

5.3.3 隔離

將熱點(diǎn)數(shù)據(jù)隔離出來,針對(duì)熱點(diǎn)數(shù)據(jù)可以再做優(yōu)化

業(yè)務(wù)隔離 - 商業(yè)邏輯上運(yùn)行上的隔離

系統(tǒng)隔離 - 運(yùn)行時(shí)的隔離

數(shù)據(jù)隔離 - 單獨(dú)數(shù)據(jù)庫 Cache集群

6. 流量削峰

秒殺請(qǐng)求在時(shí)間上是高度集中于某一特定的時(shí)間點(diǎn)的,這樣一來會(huì)有一個(gè)特別高的流量峰值,它對(duì)資源的消耗是瞬時(shí)的。

但是對(duì)于秒殺這個(gè)場景來說,最終能夠搶到的商品的人數(shù)是固定的,并發(fā)讀越高,無效請(qǐng)求也就越多了。

從業(yè)務(wù)角度上來說,秒殺希望更多的人能夠參與進(jìn)來,更多的人來刷新頁面,但是真正開始下單的時(shí)候,秒殺請(qǐng)求就不是越多越好了,可以設(shè)計(jì)一些規(guī)則,讓并發(fā)的請(qǐng)求更多的延緩,甚至我們可以過濾掉一些無效請(qǐng)求。

6.1 削峰的原因

我們知道服務(wù)器的處理資源是恒定的,你用或者不用它的處理能力都是一樣的,所以出現(xiàn)峰值的話,很容易導(dǎo)致忙到處理不過來,閑的時(shí)候卻又沒有什么要處理。但是由于要保證服務(wù)質(zhì)量,我們的很多處理資源只能按照忙的時(shí)候來預(yù)估,而這會(huì)導(dǎo)致資源的一個(gè)浪費(fèi)。

削峰主要是為了能夠讓服務(wù)端處理變得更加平穩(wěn),也為了能夠節(jié)省服務(wù)器的資源成本。從秒殺這個(gè)場景來說,就是更多延緩用戶請(qǐng)求的發(fā)出,以便減少或者過濾掉一些無效請(qǐng)求,遵從請(qǐng)求數(shù)要盡量少的原則。

6.2 無損削峰方式

6.2.1 排隊(duì)

用消息隊(duì)列緩沖瞬時(shí)流量,將同步的直接調(diào)用轉(zhuǎn)換成異步的間接推送,中間通過一個(gè)隊(duì)列在一端承接瞬時(shí)的流量洪峰,在另外一端平滑地將信息推送出去。

44656792-f947-11ec-ba43-dac502259ad0.png

fig8.jpg

但是如果流量峰值持續(xù)一段時(shí)間,超過了消息隊(duì)列的處理上限,還是會(huì)被壓垮的。

其他常見的排隊(duì)方式有:

利用線程池加鎖等待

先進(jìn)先出、先進(jìn)后出等常用的內(nèi)存排隊(duì)算法的實(shí)現(xiàn)

將請(qǐng)求序列化到文件當(dāng)中,然后再順序讀文件

6.2.2 答題

第一個(gè)目的是防止部分買家使用秒殺器在參加秒殺時(shí)作弊。2011 年秒殺非?;鸬臅r(shí)候,秒殺器也比較猖獗,因而沒有達(dá)到全民參與和營銷的目的,所以系統(tǒng)增加了答題來限制秒殺器。增加答題后,下單的時(shí)間基本控制在 2s 后,秒殺器的下單比例也大大下降。

第二個(gè)目的其實(shí)就是延緩請(qǐng)求,起到對(duì)請(qǐng)求流量進(jìn)行削峰的作用,從而讓系統(tǒng)能夠更好地支持瞬時(shí)的流量高峰。這個(gè)重要的功能就是把峰值的下單請(qǐng)求拉長,從以前的 1s 之內(nèi)延長到 2s~10s。這樣一來,請(qǐng)求峰值基于時(shí)間分片了。這個(gè)時(shí)間的分片對(duì)服務(wù)端處理并發(fā)非常重要,會(huì)大大減輕壓力。而且,由于請(qǐng)求具有先后順序,靠后的請(qǐng)求到來時(shí)自然也就沒有庫存了,因此根本到不了最后的下單步驟,所以真正的并發(fā)寫就非常有限了。這種設(shè)計(jì)思路目前用得非常普遍,如當(dāng)年支付寶的“咻一咻”、微信的“搖一搖”都是類似的方式。

6.2.3 分層過濾

采用漏斗式的設(shè)計(jì)

4483f040-f947-11ec-ba43-dac502259ad0.png

fig9.jpg

假如請(qǐng)求分別經(jīng)過 CDN、前臺(tái)讀系統(tǒng)(如商品詳情系統(tǒng))、后臺(tái)系統(tǒng)(如交易系統(tǒng))和數(shù)據(jù)庫這幾層,那么:

大部分?jǐn)?shù)據(jù)和流量在用戶瀏覽器或者 CDN 上獲取,這一層可以攔截大部分?jǐn)?shù)據(jù)的讀取

經(jīng)過第二層(即前臺(tái)系統(tǒng))時(shí)數(shù)據(jù)(包括強(qiáng)一致性的數(shù)據(jù))盡量得走 Cache,過濾一些無效的請(qǐng)求

再到第三層后臺(tái)系統(tǒng),主要做數(shù)據(jù)的二次檢驗(yàn),對(duì)系統(tǒng)做好保護(hù)和限流,這樣數(shù)據(jù)量和請(qǐng)求就進(jìn)一步減少

最后在數(shù)據(jù)層完成數(shù)據(jù)的強(qiáng)一致性校驗(yàn)

分層過濾的核心思想是:在不同的層次盡可能地過濾掉無效請(qǐng)求,讓漏斗最末端的才是有效的請(qǐng)求。而達(dá)到這種效果,我們就必須對(duì)數(shù)據(jù)做分層的校驗(yàn)。

分層校驗(yàn)的基本原則有:

將動(dòng)態(tài)請(qǐng)求的讀數(shù)據(jù)緩存在Web端,過濾掉無效的數(shù)據(jù)讀

對(duì)讀數(shù)據(jù)不做強(qiáng)一致性校驗(yàn),減少因?yàn)橐恢滦孕r?yàn)產(chǎn)生的瓶頸問題

對(duì)寫數(shù)據(jù)進(jìn)行基于時(shí)間的合理分片,過濾掉過期的失效請(qǐng)求

對(duì)寫請(qǐng)求做限流保護(hù),將超出系統(tǒng)承載能力的請(qǐng)求過濾掉

對(duì)寫數(shù)據(jù)進(jìn)行強(qiáng)一致性校驗(yàn),只保留最后有效的數(shù)據(jù)

分層校驗(yàn)的目的是:在讀系統(tǒng)中,盡量減少由于一致性校驗(yàn)帶來的系統(tǒng)瓶頸,但是盡量將不影響性能的檢查條件提前,如用戶是否具有秒殺資格、商品狀態(tài)是否正常、用戶答題是否正確、秒殺是否已經(jīng)結(jié)束、是否非法請(qǐng)求、營銷等價(jià)物是否充足等;在寫數(shù)據(jù)系統(tǒng)中,主要對(duì)寫的數(shù)據(jù)(如“庫存”)做一致性檢查,最后在數(shù)據(jù)庫層保證數(shù)據(jù)的最終準(zhǔn)確性(如“庫存”不能減為負(fù)數(shù))。

7. 影響性能的因素

7.1 性能的定義

服務(wù)設(shè)備的不同對(duì)于性能的定義也是不一樣的,例如CPU主要看主頻,磁盤主要看IOPS(Input/ output Operations Per Second, 即每秒進(jìn)行讀寫操作的次數(shù))。

關(guān)于秒殺,我們主要討論系統(tǒng)服務(wù)端的性能,一般使用QPS來衡量,還有一個(gè)影響和QPS息息相關(guān),即響應(yīng)時(shí)間(Response Time, RT),可以理解為服務(wù)器處理響應(yīng)的耗時(shí)。

正常情況下響應(yīng)時(shí)間越短,一秒鐘處理的請(qǐng)求數(shù)就會(huì)越多,這在單線程處理的情況下看起來是線性關(guān)系,即我們只要把每個(gè)請(qǐng)求的響應(yīng)時(shí)間降到最低,那么性能就會(huì)最高。而在多線程當(dāng)中,總QPS = (1000ms/ 響應(yīng)時(shí)間)x 線程數(shù),從這個(gè)角度上來看,性能和兩個(gè)因素相關(guān),一個(gè)是一次響應(yīng)的服務(wù)端的耗時(shí),一個(gè)是處理請(qǐng)求的線程數(shù)。

7.1.1 響應(yīng)時(shí)間

對(duì)于大部分的Web系統(tǒng)而言,響應(yīng)時(shí)間一般是由CPU執(zhí)行時(shí)間和線程等待時(shí)間組成的,即服務(wù)器在處理一個(gè)請(qǐng)求時(shí),一部分是CPU本身在做運(yùn)算,還有一部分是各種等待。

理解了服務(wù)器處理請(qǐng)求的邏輯,估計(jì)你會(huì)說為什么我們不去減少這種等待時(shí)間。很遺憾,根據(jù)我們實(shí)際的測(cè)試發(fā)現(xiàn),減少線程等待時(shí)間對(duì)提升性能的影響沒有我們想象得那么大,它并不是線性的提升關(guān)系,這點(diǎn)在很多代理服務(wù)器(Proxy)上可以做驗(yàn)證。

如果代理服務(wù)器本身沒有CPU消耗,我們?cè)诿看谓o代理服務(wù)器代理的請(qǐng)求加個(gè)延時(shí),即增加響應(yīng)時(shí)間,但是這對(duì)代理服務(wù)器本身的吞吐量并沒有多大的影響,因?yàn)榇矸?wù)器本身的資源并沒有被消耗,可以通過增加代理服務(wù)器的處理線程數(shù),來彌補(bǔ)響應(yīng)時(shí)間對(duì)代理服務(wù)器的 QPS 的影響。

其實(shí),真正對(duì)性能有影響的是 CPU 的執(zhí)行時(shí)間。這也很好理解,因?yàn)?CPU 的執(zhí)行真正消耗了服務(wù)器的資源。經(jīng)過實(shí)際的測(cè)試,如果減少 CPU 一半的執(zhí)行時(shí)間,就可以增加一倍的 QPS。

7.1.2 線程數(shù)

并不是線程數(shù)越多越好,總QPS就會(huì)越大,因?yàn)榫€程本身也消耗資源,會(huì)受到其他因素的制約。例如,線程越多系統(tǒng)的線程切換成本就會(huì)越高,而且每個(gè)線程都會(huì)耗費(fèi)一定的內(nèi)存。

默認(rèn)的配置一般為:

線程數(shù) = 2 x CPU核數(shù) + 1

還有一個(gè)根據(jù)最佳實(shí)踐得出來的公式為:

線程數(shù) = [(線程等待時(shí)間 + 線程CPU時(shí)間) / 線程CPU時(shí)間] x CPU數(shù)量

因此要提升性能,我們就要減少CPU的執(zhí)行時(shí)間,另外就是要設(shè)置一個(gè)合理的并發(fā)線程數(shù)量,通過這兩方面來顯著提升服務(wù)器的性能。

7.2 如何發(fā)現(xiàn)瓶頸

服務(wù)器會(huì)出現(xiàn)瓶頸的地方很多,例如CPU, 內(nèi)存, 磁盤以及網(wǎng)絡(luò)等可能都會(huì)導(dǎo)致瓶頸。另外不同的系統(tǒng)對(duì)于瓶頸的關(guān)注度不一樣,例如對(duì)緩存系統(tǒng)來說,制約的是內(nèi)存,而對(duì)存儲(chǔ)型的系統(tǒng)來說I/O 更容易出現(xiàn)瓶頸。

而對(duì)于秒殺,瓶頸更容易發(fā)生在CPU上。

那么,如何發(fā)現(xiàn) CPU 的瓶頸呢?其實(shí)有很多 CPU 診斷工具可以發(fā)現(xiàn) CPU 的消耗,最常用的就是 JProfiler 和 Yourkit 這兩個(gè)工具,它們可以列出整個(gè)請(qǐng)求中每個(gè)函數(shù)的 CPU 執(zhí)行時(shí)間,可以發(fā)現(xiàn)哪個(gè)函數(shù)消耗的 CPU 時(shí)間最多,以便你有針對(duì)性地做優(yōu)化。

當(dāng)然還有一些辦法也可以近似地統(tǒng)計(jì) CPU 的耗時(shí),例如通過 jstack 定時(shí)地打印調(diào)用棧,如果某些函數(shù)調(diào)用頻繁或者耗時(shí)較多,那么那些函數(shù)就會(huì)多次出現(xiàn)在系統(tǒng)調(diào)用棧里,這樣相當(dāng)于采樣的方式也能夠發(fā)現(xiàn)耗時(shí)較多的函數(shù)。

雖說秒殺系統(tǒng)的瓶頸大部分在 CPU,但這并不表示其他方面就一定不出現(xiàn)瓶頸。例如,如果海量請(qǐng)求涌過來,你的頁面又比較大,那么網(wǎng)絡(luò)就有可能出現(xiàn)瓶頸。

怎樣簡單地判斷 CPU 是不是瓶頸呢?一個(gè)辦法就是看當(dāng) QPS 達(dá)到極限時(shí),你的服務(wù)器的 CPU 使用率是不是超過了 95%,如果沒有超過,那么表示 CPU 還有提升的空間,要么是有鎖限制,要么是有過多的本地 I/O 等待發(fā)生。

7.3 如何優(yōu)化系統(tǒng)

針對(duì)Java來說的:

7.3.1 減少編碼

Java的編碼運(yùn)行比較慢,在很多場景下,只要涉及字符串的操作都會(huì)比較消耗CPU資源,不管是磁盤IO還是網(wǎng)絡(luò)IO,因?yàn)槎夹枰獙⒆址D(zhuǎn)換成字節(jié),這個(gè)轉(zhuǎn)換必須編碼。

每個(gè)字符的編碼都需要查表,而這種查表的操作非常耗資源,所以減少字符到字節(jié)或者相反的轉(zhuǎn)換、減少字符編碼會(huì)非常有成效。減少編碼就可以大大提升性能。

那么如何才能減少編碼呢?例如,網(wǎng)頁輸出是可以直接進(jìn)行流輸出的,即用 resp.getOutputStream() 函數(shù)寫數(shù)據(jù),把一些靜態(tài)的數(shù)據(jù)提前轉(zhuǎn)化成字節(jié),等到真正往外寫的時(shí)候再直接用 OutputStream() 函數(shù)寫,就可以減少靜態(tài)數(shù)據(jù)的編碼轉(zhuǎn)換。

7.3.2 減少序列化

序列化也是Java性能的一大天敵,減少Java當(dāng)中的序列化操作也能大大提升性能。又因?yàn)樾蛄谢呛途幋a同時(shí)發(fā)生的,所以減少序列化也就減少了編碼。

序列化大部分是在 RPC 中發(fā)生的,因此避免或者減少 RPC 就可以減少序列化,當(dāng)然當(dāng)前的序列化協(xié)議也已經(jīng)做了很多優(yōu)化來提升性能。有一種新的方案,就是可以將多個(gè)關(guān)聯(lián)性比較強(qiáng)的應(yīng)用進(jìn)行“合并部署”,而減少不同應(yīng)用之間的 RPC 也可以減少序列化的消耗。

所謂“合并部署”,就是把兩個(gè)原本在不同機(jī)器上的不同應(yīng)用合并部署到一臺(tái)機(jī)器上,當(dāng)然不僅僅是部署在一臺(tái)機(jī)器上,還要在同一個(gè) Tomcat 容器中,且不能走本機(jī)的 Socket,這樣才能避免序列化的產(chǎn)生。

7.3.3 Java 秒殺場景的針對(duì)性優(yōu)化

Java 和通用的 Web 服務(wù)器(如 Nginx 或 Apache 服務(wù)器)相比,在處理大并發(fā)的 HTTP 請(qǐng)求時(shí)要弱一點(diǎn),所以一般我們都會(huì)對(duì)大流量的 Web 系統(tǒng)做靜態(tài)化改造,讓大部分請(qǐng)求和數(shù)據(jù)直接在 Nginx 服務(wù)器或者 Web 代理服務(wù)器(如 Varnish、Squid 等)上直接返回(這樣可以減少數(shù)據(jù)的序列化與反序列化),而 Java 層只需處理少量數(shù)據(jù)的動(dòng)態(tài)請(qǐng)求。針對(duì)這些請(qǐng)求,我們可以使用以下手段進(jìn)行優(yōu)化:

直接使用 Servlet 處理請(qǐng)求。避免使用傳統(tǒng)的 MVC 框架,這樣可以繞過一大堆復(fù)雜且用處不大的處理邏輯,節(jié)省 1ms 時(shí)間(具體取決于你對(duì) MVC 框架的依賴程度)。

直接輸出流數(shù)據(jù)。使用 resp.getOutputStream() 而不是 resp.getWriter() 函數(shù),可以省掉一些不變字符數(shù)據(jù)的編碼,從而提升性能;數(shù)據(jù)輸出時(shí)推薦使用 JSON 而不是模板引擎(一般都是解釋執(zhí)行)來輸出頁面。

7.3.4 并發(fā)讀優(yōu)化

也許有讀者會(huì)覺得這個(gè)問題很容易解決,無非就是放到 Tair 緩存里面。集中式緩存為了保證命中率一般都會(huì)采用一致性 Hash,所以同一個(gè) key 會(huì)落到同一臺(tái)機(jī)器上。雖然單臺(tái)緩存機(jī)器也能支撐 30w/s 的請(qǐng)求,但還是遠(yuǎn)不足以應(yīng)對(duì)像“大秒”這種級(jí)別的熱點(diǎn)商品。那么,該如何徹底解決單點(diǎn)的瓶頸呢?

答案是采用應(yīng)用層的 LocalCache,即在秒殺系統(tǒng)的單機(jī)上緩存商品相關(guān)的數(shù)據(jù)。

那么,又如何緩存(Cache)數(shù)據(jù)呢?你需要?jiǎng)澐殖蓜?dòng)態(tài)數(shù)據(jù)和靜態(tài)數(shù)據(jù)分別進(jìn)行處理:

像商品中的“標(biāo)題”和“描述”這些本身不變的數(shù)據(jù),會(huì)在秒殺開始之前全量推送到秒殺機(jī)器上,并一直緩存到秒殺結(jié)束;

像庫存這類動(dòng)態(tài)數(shù)據(jù),會(huì)采用“被動(dòng)失效”的方式緩存一定時(shí)間(一般是數(shù)秒),失效后再去緩存拉取最新的數(shù)據(jù)。

還有關(guān)于一致性的問題,因?yàn)閹齑媸窃诓粩喔碌?,這就要用到前面介紹的讀數(shù)據(jù)的分層校驗(yàn)原則了,讀的場景可以允許一定的臟數(shù)據(jù),因?yàn)檫@里的誤判只會(huì)導(dǎo)致少量原本無庫存的下單請(qǐng)求被誤認(rèn)為有庫存,可以等到真正寫數(shù)據(jù)時(shí)再保證最終的一致性,通過在數(shù)據(jù)的高可用性和一致性之間的平衡,來解決高并發(fā)的數(shù)據(jù)讀取問題。

8. 減庫存設(shè)計(jì)的核心邏輯

不超賣是秒殺系統(tǒng)的前提。減庫存到底應(yīng)該是在下單階段還是付款階段呢?

8.1 減庫存的方式

8.1.1 下單減庫存

即當(dāng)買家下單之后,在商品的總庫存中減去買家購買的數(shù)量。這種方式控制最精確,下單時(shí)直接通過數(shù)據(jù)庫的事務(wù)機(jī)制控制商品庫存,這樣一定不會(huì)出現(xiàn)超賣的現(xiàn)象。但是有些人下完單以后并不會(huì)付款。

8.1.2 付款減庫存

即買家下單后,并不立即減庫存,而是等到有用戶付款后才真正減庫存,否則庫存一直保留給其他買家。但因?yàn)楦犊顣r(shí)才減庫存,如果并發(fā)比較高,有可能出現(xiàn)買家下單后付不了款的情況,因?yàn)榭赡苌唐芬呀?jīng)被其他人買走了。

8.1.3 預(yù)扣庫存

這種方式相對(duì)復(fù)雜一些,買家下單后,庫存為其保留一定的時(shí)間(如 10 分鐘),超過這個(gè)時(shí)間,庫存將會(huì)自動(dòng)釋放,釋放后其他買家就可以繼續(xù)購買。在買家付款前,系統(tǒng)會(huì)校驗(yàn)該訂單的庫存是否還有保留:如果沒有保留,則再次嘗試預(yù)扣;如果庫存不足(也就是預(yù)扣失?。﹦t不允許繼續(xù)付款;如果預(yù)扣成功,則完成付款并實(shí)際地減去庫存。

8.2 可能存在的問題

假如我們采用“下單減庫存”的方式,即用戶下單后就減去庫存,正常情況下,買家下單后付款的概率會(huì)很高,所以不會(huì)有太大問題。但是有一種場景例外,就是當(dāng)賣家參加某個(gè)活動(dòng)時(shí),此時(shí)活動(dòng)的有效時(shí)間是商品的黃金售賣時(shí)間,如果有競爭對(duì)手通過惡意下單的方式將該賣家的商品全部下單,讓這款商品的庫存減為零,那么這款商品就不能正常售賣了。要知道,這些惡意下單的人是不會(huì)真正付款的,這正是“下單減庫存”方式的不足之處。

既然“下單減庫存”可能導(dǎo)致惡意下單,從而影響賣家的商品銷售,那么有沒有辦法解決呢?你可能會(huì)想,采用“付款減庫存”的方式是不是就可以了?的確可以。但是,“付款減庫存”又會(huì)導(dǎo)致另外一個(gè)問題:庫存超賣。

假如有 100 件商品,就可能出現(xiàn) 300 人下單成功的情況,因?yàn)橄聠螘r(shí)不會(huì)減庫存,所以也就可能出現(xiàn)下單成功數(shù)遠(yuǎn)遠(yuǎn)超過真正庫存數(shù)的情況,這尤其會(huì)發(fā)生在做活動(dòng)的熱門商品上。這樣一來,就會(huì)導(dǎo)致很多買家下單成功但是付不了款,買家的購物體驗(yàn)自然比較差。

那么,既然“下單減庫存”和“付款減庫存”都有缺點(diǎn),我們能否把兩者相結(jié)合,將兩次操作進(jìn)行前后關(guān)聯(lián)起來,下單時(shí)先預(yù)扣,在規(guī)定時(shí)間內(nèi)不付款再釋放庫存,即采用“預(yù)扣庫存”這種方式呢?

這種方案確實(shí)可以在一定程度上緩解上面的問題。但是否就徹底解決了呢?其實(shí)沒有!針對(duì)惡意下單這種情況,雖然把有效的付款時(shí)間設(shè)置為 10 分鐘,但是惡意買家完全可以在 10 分鐘后再次下單,或者采用一次下單很多件的方式把庫存減完。針對(duì)這種情況,解決辦法還是要結(jié)合安全和反作弊的措施來制止。

例如,給經(jīng)常下單不付款的買家進(jìn)行識(shí)別打標(biāo)(可以在被打標(biāo)的買家下單時(shí)不減庫存)、給某些類目設(shè)置最大購買件數(shù)(例如,參加活動(dòng)的商品一人最多只能買 3 件),以及對(duì)重復(fù)下單不付款的操作進(jìn)行次數(shù)限制等。

針對(duì)“庫存超賣”這種情況,在 10 分鐘時(shí)間內(nèi)下單的數(shù)量仍然有可能超過庫存數(shù)量,遇到這種情況我們只能區(qū)別對(duì)待:對(duì)普通的商品下單數(shù)量超過庫存數(shù)量的情況,可以通過補(bǔ)貨來解決;但是有些賣家完全不允許庫存為負(fù)數(shù)的情況,那只能在買家付款時(shí)提示庫存不足。

8.3 大型秒殺中如何減庫存

對(duì)于一般業(yè)務(wù)系統(tǒng)而言,一般是預(yù)扣庫存的方案,超出有效付款時(shí)間訂單就會(huì)自動(dòng)釋放。而對(duì)于秒殺場景,一般采用下單減庫存。

“下單減庫存”在數(shù)據(jù)一致性上,主要就是保證大并發(fā)請(qǐng)求時(shí)庫存數(shù)據(jù)不能為負(fù)數(shù),也就是要保證數(shù)據(jù)庫中的庫存字段值不能為負(fù)數(shù),一般我們有多種解決方案:一種是在應(yīng)用程序中通過事務(wù)來判斷,即保證減后庫存不能為負(fù)數(shù),否則就回滾;另一種辦法是直接設(shè)置數(shù)據(jù)庫的字段數(shù)據(jù)為無符號(hào)整數(shù),這樣減后庫存字段值小于零時(shí)會(huì)直接執(zhí)行 SQL 語句來報(bào)錯(cuò);再有一種就是使用 CASE WHEN 判斷語句,例如這樣的 SQL 語句:

UPDATEitemSETinventory=CASEWHENinventory>=xxxTHENinventory-xxxELSEinventoryEND

秒殺商品和普通商品的減庫存還是有些差異的,例如商品數(shù)量比較少,交易時(shí)間段也比較短,因此這里有一個(gè)大膽的假設(shè),即能否把秒殺商品減庫存直接放到緩存系統(tǒng)中實(shí)現(xiàn),也就是直接在緩存中減庫存或者在一個(gè)帶有持久化功能的緩存系統(tǒng)(如 Redis)中完成呢?

如果你的秒殺商品的減庫存邏輯非常單一,比如沒有復(fù)雜的 SKU 庫存和總庫存這種聯(lián)動(dòng)關(guān)系的話,我覺得完全可以。但是如果有比較復(fù)雜的減庫存邏輯,或者需要使用事務(wù),你還是必須在數(shù)據(jù)庫中完成減庫存。

由于 MySQL 存儲(chǔ)數(shù)據(jù)的特點(diǎn),同一數(shù)據(jù)在數(shù)據(jù)庫里肯定是一行存儲(chǔ)(MySQL),因此會(huì)有大量線程來競爭 InnoDB 行鎖,而并發(fā)度越高時(shí)等待線程會(huì)越多,TPS(Transaction Per Second,即每秒處理的消息數(shù))會(huì)下降,響應(yīng)時(shí)間(RT)會(huì)上升,數(shù)據(jù)庫的吞吐量就會(huì)嚴(yán)重受影響。

這就可能引發(fā)一個(gè)問題,就是單個(gè)熱點(diǎn)商品會(huì)影響整個(gè)數(shù)據(jù)庫的性能, 導(dǎo)致 0.01% 的商品影響 99.99% 的商品的售賣,這是我們不愿意看到的情況。一個(gè)解決思路是遵循前面介紹的原則進(jìn)行隔離,把熱點(diǎn)商品放到單獨(dú)的熱點(diǎn)庫中。但是這無疑會(huì)帶來維護(hù)上的麻煩,比如要做熱點(diǎn)數(shù)據(jù)的動(dòng)態(tài)遷移以及單獨(dú)的數(shù)據(jù)庫等。

而分離熱點(diǎn)商品到單獨(dú)的數(shù)據(jù)庫還是沒有解決并發(fā)鎖的問題,我們應(yīng)該怎么辦呢?要解決并發(fā)鎖的問題,有兩種辦法:

應(yīng)用層排隊(duì)

按照商品維度設(shè)置隊(duì)列順序執(zhí)行,這樣能減少同一臺(tái)機(jī)器對(duì)數(shù)據(jù)庫同一行記錄進(jìn)行操作的并發(fā)度,同時(shí)也能控制單個(gè)商品占用數(shù)據(jù)庫連接的數(shù)量,防止熱點(diǎn)商品占用太多的數(shù)據(jù)庫連接。

數(shù)據(jù)庫排隊(duì)

應(yīng)用層只能做到單機(jī)的排隊(duì),但是應(yīng)用機(jī)器數(shù)本身很多,這種排隊(duì)方式控制并發(fā)的能力仍然有限,所以如果能在數(shù)據(jù)庫層做全局排隊(duì)是最理想的。阿里的數(shù)據(jù)庫團(tuán)隊(duì)開發(fā)了針對(duì)這種 MySQL 的 InnoDB 層上的補(bǔ)丁程序(patch),可以在數(shù)據(jù)庫層上對(duì)單行記錄做到并發(fā)排隊(duì)。

9. 如何設(shè)計(jì)兜底方案?

9.1 高可用建設(shè)應(yīng)該從哪里著手?

44a43940-f947-11ec-ba43-dac502259ad0.png

fig10.jpg

架構(gòu)階段 - 考慮系統(tǒng)的可擴(kuò)展性和容錯(cuò)性,要避免出現(xiàn)單點(diǎn)問題。例如多機(jī)房單元化部署,即使某個(gè)城市的某個(gè)機(jī)房出現(xiàn)整體故障,仍然不會(huì)影響整體網(wǎng)站的運(yùn)轉(zhuǎn)。

編碼階段 - 保證代碼的健壯性,例如涉及到遠(yuǎn)程調(diào)用的問題的時(shí)候,要設(shè)置合理的超時(shí)退出機(jī)制,防止被其他系統(tǒng)拖垮,也要對(duì)調(diào)用的返回結(jié)果集有預(yù)期,防止返回的結(jié)果超出程序處理的范圍。即對(duì)錯(cuò)誤異常進(jìn)行捕獲,對(duì)無法預(yù)料的錯(cuò)誤要有默認(rèn)處理結(jié)果。

測(cè)試階段 - 測(cè)試主要是保證測(cè)試用例的覆蓋度,保證最壞情況發(fā)生的時(shí)候,我們也有相應(yīng)的處理流程。

發(fā)布階段 - 要有緊急的回滾機(jī)制

運(yùn)行階段 - 運(yùn)行態(tài)是常態(tài),重要的是對(duì)系統(tǒng)的監(jiān)控要準(zhǔn)確及時(shí),發(fā)現(xiàn)問題能夠準(zhǔn)確報(bào)警并且報(bào)警數(shù)據(jù)要準(zhǔn)確詳細(xì),以便于排查問題。

故障發(fā)生 - 及時(shí)止損,例如由于程序問題導(dǎo)致商品價(jià)格錯(cuò)誤,就要及時(shí)下架商品或者關(guān)閉購買鏈接,防止造成重大資產(chǎn)損失。

為什么系統(tǒng)的高可用建設(shè)要放到整個(gè)生命周期中全面考慮?因?yàn)槲覀冊(cè)诿總€(gè)環(huán)節(jié)中都可能犯錯(cuò),而有些環(huán)節(jié)犯的錯(cuò),你在后面是無法彌補(bǔ)的。例如在架構(gòu)階段,你沒有消除單點(diǎn)問題,那么系統(tǒng)上線后,遇到突發(fā)流量把單點(diǎn)給掛了,你就只能干瞪眼,有時(shí)候想加機(jī)器都加不進(jìn)去。所以高可用建設(shè)是一個(gè)系統(tǒng)工程,必須在每個(gè)環(huán)節(jié)都做好。

那么針對(duì)秒殺系統(tǒng),我們重點(diǎn)介紹在遇到大流量時(shí),應(yīng)該從哪些方面來保障系統(tǒng)的穩(wěn)定運(yùn)行,所以更多的是看如何針對(duì)運(yùn)行階段進(jìn)行處理,這就引出了接下來的內(nèi)容:降級(jí)、限流和拒絕服務(wù)。

9.2 降級(jí)

所謂“降級(jí)”,就是當(dāng)系統(tǒng)的容量達(dá)到一定程度時(shí),限制或者關(guān)閉系統(tǒng)的某些非核心功能,從而把有限的資源保留給更核心的業(yè)務(wù)。它是一個(gè)有目的、有計(jì)劃的執(zhí)行過程,所以對(duì)降級(jí)我們一般需要有一套預(yù)案來配合執(zhí)行。如果我們把它系統(tǒng)化,就可以通過預(yù)案系統(tǒng)和開關(guān)系統(tǒng)來實(shí)現(xiàn)降級(jí)。

降級(jí)方案可以這樣設(shè)計(jì):當(dāng)秒殺流量達(dá)到 5w/s 時(shí),把成交記錄的獲取從展示 20 條降級(jí)到只展示 5 條?!皬?20 改到 5”這個(gè)操作由一個(gè)開關(guān)來實(shí)現(xiàn),也就是設(shè)置一個(gè)能夠從開關(guān)系統(tǒng)動(dòng)態(tài)獲取的系統(tǒng)參數(shù)。

這里,我給出開關(guān)系統(tǒng)的示意圖。它分為兩部分,一部分是開關(guān)控制臺(tái),它保存了開關(guān)的具體配置信息,以及具體執(zhí)行開關(guān)所對(duì)應(yīng)的機(jī)器列表;另一部分是執(zhí)行下發(fā)開關(guān)數(shù)據(jù)的 Agent,主要任務(wù)就是保證開關(guān)被正確執(zhí)行,即使系統(tǒng)重啟后也會(huì)生效。

44d0cc94-f947-11ec-ba43-dac502259ad0.png

fig11.jpg

9.3 限流

如果說降級(jí)是犧牲了一部分次要的功能和用戶的體驗(yàn)效果,那么限流就是更極端的一種保護(hù)措施了。限流就是當(dāng)系統(tǒng)容量達(dá)到瓶頸時(shí),我們需要通過限制一部分流量來保護(hù)系統(tǒng),并做到既可以人工執(zhí)行開關(guān),也支持自動(dòng)化保護(hù)的措施。

這里,我同樣給出了限流系統(tǒng)的示意圖??傮w來說,限流既可以是在客戶端限流,也可以是在服務(wù)端限流。此外,限流的實(shí)現(xiàn)方式既要支持 URL 以及方法級(jí)別的限流,也要支持基于 QPS 和線程的限流。

客戶端限流

好處可以限制請(qǐng)求的發(fā)出,通過減少發(fā)出無用請(qǐng)求從而減少對(duì)系統(tǒng)的消耗。缺點(diǎn)就是當(dāng)客戶端比較分散時(shí),沒法設(shè)置合理的限流閾值:如果閾值設(shè)的太小,會(huì)導(dǎo)致服務(wù)端沒有達(dá)到瓶頸時(shí)客戶端已經(jīng)被限制;而如果設(shè)的太大,則起不到限制的作用。

服務(wù)端限流

好處是可以根據(jù)服務(wù)端的性能設(shè)置合理的閾值,而缺點(diǎn)就是被限制的請(qǐng)求都是無效的請(qǐng)求,處理這些無效的請(qǐng)求本身也會(huì)消耗服務(wù)器資源。

fig12.jpg

在限流的實(shí)現(xiàn)手段上來講,基于 QPS 和線程數(shù)的限流應(yīng)用最多,最大 QPS 很容易通過壓測(cè)提前獲取,例如我們的系統(tǒng)最高支持 1w QPS 時(shí),可以設(shè)置 8000 來進(jìn)行限流保護(hù)。線程數(shù)限流在客戶端比較有效,例如在遠(yuǎn)程調(diào)用時(shí)我們?cè)O(shè)置連接池的線程數(shù),超出這個(gè)并發(fā)線程請(qǐng)求,就將線程進(jìn)行排隊(duì)或者直接超時(shí)丟棄。

限流無疑會(huì)影響用戶的正常請(qǐng)求,所以必然會(huì)導(dǎo)致一部分用戶請(qǐng)求失敗,因此在系統(tǒng)處理這種異常時(shí)一定要設(shè)置超時(shí)時(shí)間,防止因被限流的請(qǐng)求不能 fast fail(快速失敗)而拖垮系統(tǒng)。

9.4 拒絕服務(wù)

當(dāng)系統(tǒng)負(fù)載達(dá)到一定閾值時(shí),例如 CPU 使用率達(dá)到 90% 或者系統(tǒng) load 值達(dá)到 2*CPU 核數(shù)時(shí),系統(tǒng)直接拒絕所有請(qǐng)求,這種方式是最暴力但也最有效的系統(tǒng)保護(hù)方式。例如秒殺系統(tǒng),我們?cè)谌缦聨讉€(gè)環(huán)節(jié)設(shè)計(jì)過載保護(hù):

在最前端的 Nginx 上設(shè)置過載保護(hù),當(dāng)機(jī)器負(fù)載達(dá)到某個(gè)值時(shí)直接拒絕 HTTP 請(qǐng)求并返回 503 錯(cuò)誤碼,在 Java 層同樣也可以設(shè)計(jì)過載保護(hù)。

拒絕服務(wù)可以說是一種不得已的兜底方案,用以防止最壞情況發(fā)生,防止因把服務(wù)器壓跨而長時(shí)間徹底無法提供服務(wù)。像這種系統(tǒng)過載保護(hù)雖然在過載時(shí)無法提供服務(wù),但是系統(tǒng)仍然可以運(yùn)作,當(dāng)負(fù)載下降時(shí)又很容易恢復(fù),所以每個(gè)系統(tǒng)和每個(gè)環(huán)節(jié)都應(yīng)該設(shè)置這個(gè)兜底方案,對(duì)系統(tǒng)做最壞情況下的保護(hù)。

原文標(biāo)題:9. 如何設(shè)計(jì)兜底方案?

文章出處:【微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

審核編輯:彭靜

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    7256

    瀏覽量

    91910
  • 數(shù)據(jù)緩存
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    7338
  • HTTP協(xié)議
    +關(guān)注

    關(guān)注

    0

    文章

    67

    瀏覽量

    10215

原文標(biāo)題:9. 如何設(shè)計(jì)兜底方案?

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    高性能緩存設(shè)計(jì):如何解決緩存偽共享問題

    在多核高并發(fā)場景下, 緩存偽共享(False Sharing) 是導(dǎo)致性能驟降的“隱形殺手”。當(dāng)不同線程頻繁修改同一緩存行(Cache Line)中的獨(dú)立變量時(shí),CPU緩存一致性協(xié)議會(huì)強(qiáng)制同步整個(gè)
    的頭像 發(fā)表于 07-01 15:01 ?132次閱讀
    高性能<b class='flag-5'>緩存</b>設(shè)計(jì):如何解決<b class='flag-5'>緩存</b>偽共享問題

    MCU緩存設(shè)計(jì)

    MCU 設(shè)計(jì)通過優(yōu)化指令與數(shù)據(jù)的訪問效率,顯著提升系統(tǒng)性能并降低功耗,其核心架構(gòu)與實(shí)現(xiàn)策略如下: 一、緩存類型與結(jié)構(gòu) 指令緩存(I-Cache)與數(shù)據(jù)
    的頭像 發(fā)表于 05-07 15:29 ?360次閱讀

    Nginx緩存配置詳解

    Nginx 是一個(gè)功能強(qiáng)大的 Web 服務(wù)器和反向代理服務(wù)器,它可以用于實(shí)現(xiàn)靜態(tài)內(nèi)容的緩存,緩存可以分為客戶端緩存和服務(wù)端緩存。
    的頭像 發(fā)表于 05-07 14:03 ?598次閱讀
    Nginx<b class='flag-5'>緩存</b>配置詳解

    高速SSD存儲(chǔ)系統(tǒng)中數(shù)據(jù)緩存控制器整體頂層設(shè)計(jì)

    數(shù)據(jù)緩存控制器主要實(shí)現(xiàn)了對(duì)大量突發(fā)數(shù)據(jù)緩存、AXI4接口與AXI4-Stream接口之間的轉(zhuǎn)換和NVMe命令的生成等功能。這里主要介紹相關(guān)開發(fā)流程。
    的頭像 發(fā)表于 04-14 10:46 ?283次閱讀
    高速SSD存儲(chǔ)系統(tǒng)中<b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>緩存</b>控制器整體頂層設(shè)計(jì)

    nginx中強(qiáng)緩存和協(xié)商緩存介紹

    強(qiáng)緩存直接告訴瀏覽器:在緩存過期前,無需與服務(wù)器通信,直接使用本地緩存。
    的頭像 發(fā)表于 04-01 16:01 ?384次閱讀

    MPC5777C如何在禁用其余數(shù)據(jù)緩存的同時(shí)繼續(xù)保持堆棧工作?

    我按照 AN5191指南啟動(dòng)MPC5777C自定義板,它的一些內(nèi)置測(cè)試要求我禁用緩存以執(zhí)行某些作,然后重新啟用它們以進(jìn)行正常作。考慮到我把一半的數(shù)據(jù)緩存作為我的堆棧(使用基于 dcbz 和 dcbtls 指令的 AN5191代碼
    發(fā)表于 03-27 06:01

    ADS4125數(shù)據(jù)輸出口接了緩存器和排阻,這排阻的作用是什么呢?

    什么都沒變,什么原因引起這么大差異呢?問題2:在ADS4125數(shù)據(jù)輸出口接了緩存器和排阻,這排阻的作用是什么呢,是匹配呢還是當(dāng)上拉電阻用呢,或者可不可以不接 直接短接? 請(qǐng)教各位大蝦,謝謝!
    發(fā)表于 02-07 08:45

    ADS4129后級(jí)接緩存器,緩存器出現(xiàn)過熱的原因?

    使用25M的采樣頻率對(duì)1M的信號(hào)進(jìn)行采樣,ADS4129以12位cmos電平輸出,出來后的數(shù)據(jù)緩存器SN74AVC16244,緩存器工作電壓是3.3V,在工作過程中緩存器很燙,芯片
    發(fā)表于 02-07 08:42

    緩存對(duì)大數(shù)據(jù)處理的影響分析

    緩存對(duì)大數(shù)據(jù)處理的影響顯著且重要,主要體現(xiàn)在以下幾個(gè)方面: 一、提高數(shù)據(jù)訪問速度 在大數(shù)據(jù)環(huán)境中,數(shù)據(jù)存儲(chǔ)通常采用分布式存儲(chǔ)系統(tǒng),
    的頭像 發(fā)表于 12-18 09:45 ?777次閱讀

    HTTP緩存頭的使用 本地緩存與遠(yuǎn)程緩存的區(qū)別

    HTTP緩存頭是一組HTTP響應(yīng)頭,它們控制瀏覽器和中間代理服務(wù)器如何緩存網(wǎng)頁內(nèi)容。合理使用HTTP緩存頭可以顯著提高網(wǎng)站的加載速度和性能,減少服務(wù)器的負(fù)載。 1. HTTP緩存頭概述
    的頭像 發(fā)表于 12-18 09:41 ?473次閱讀

    Web緩存的類型及功能分析

    隨著互聯(lián)網(wǎng)的迅速發(fā)展,用戶對(duì)網(wǎng)絡(luò)內(nèi)容的訪問需求日益增長。為了提高用戶體驗(yàn)和降低服務(wù)器負(fù)擔(dān),Web緩存技術(shù)應(yīng)運(yùn)而生。Web緩存通過存儲(chǔ)重復(fù)請(qǐng)求的數(shù)據(jù),減少了對(duì)原始服務(wù)器的訪問次數(shù),從而加快了數(shù)據(jù)
    的頭像 發(fā)表于 12-18 09:35 ?784次閱讀

    緩存技術(shù)在軟件開發(fā)中的應(yīng)用

    在現(xiàn)代軟件開發(fā)中,隨著數(shù)據(jù)量的爆炸性增長和用戶對(duì)響應(yīng)速度的高要求,緩存技術(shù)成為了提升系統(tǒng)性能的重要手段。緩存技術(shù)通過將數(shù)據(jù)存儲(chǔ)在離用戶更近的位置,減少
    的頭像 發(fā)表于 12-18 09:32 ?719次閱讀

    什么是緩存(Cache)及其作用

    緩存(Cache)是一種高速存儲(chǔ)器,用于臨時(shí)存儲(chǔ)數(shù)據(jù),以便快速訪問。在計(jì)算機(jī)系統(tǒng)中,緩存的作用是減少處理器訪問主存儲(chǔ)器(如隨機(jī)存取存儲(chǔ)器RAM)所需的時(shí)間。 緩存(Cache)概述
    的頭像 發(fā)表于 12-18 09:28 ?1.2w次閱讀

    緩存之美——如何選擇合適的本地緩存

    Guava cache是Google開發(fā)的Guava工具包中一套完善的JVM本地緩存框架,底層實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)類似于ConcurrentHashMap,但是進(jìn)行了更多的能力拓展,包括緩存過期時(shí)間設(shè)置、
    的頭像 發(fā)表于 11-17 14:24 ?823次閱讀
    <b class='flag-5'>緩存</b>之美——如何選擇合適的本地<b class='flag-5'>緩存</b>?

    什么是CPU緩存?它有哪些作用?

    CPU緩存(Cache Memory)是計(jì)算機(jī)系統(tǒng)中一個(gè)至關(guān)重要的組成部分,它位于CPU與內(nèi)存之間,作為兩者之間的臨時(shí)存儲(chǔ)器。CPU緩存的主要作用是減少CPU訪問內(nèi)存所需的時(shí)間,從而提高系統(tǒng)的整體性能。以下將詳細(xì)闡述CPU緩存
    的頭像 發(fā)表于 08-22 14:54 ?6177次閱讀