www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]一位七牛的資深架構(gòu)師曾經(jīng)說(shuō)過(guò)這樣一句話:Nginx+業(yè)務(wù)邏輯層+數(shù)據(jù)庫(kù)+緩存層+消息隊(duì)列,這種模型幾乎能適配絕大部分的業(yè)務(wù)場(chǎng)景。這么多年過(guò)去了,這句話或深或淺地影響了我的技術(shù)選擇,以至于后來(lái)我花了很多時(shí)間去重點(diǎn)學(xué)習(xí)緩存相關(guān)的技術(shù)。我在10年前開(kāi)始使用緩存,從本地緩存、到分布式緩存、再到多級(jí)緩存,踩過(guò)很多坑。下面我結(jié)合自己使用緩存的歷程,談?wù)勎覍?duì)緩存的認(rèn)識(shí)。

一位七牛的資深架構(gòu)師曾經(jīng)說(shuō)過(guò)這樣一句話:

Nginx+業(yè)務(wù)邏輯層+數(shù)據(jù)庫(kù)+緩存層+消息隊(duì)列,這種模型幾乎能適配絕大部分的業(yè)務(wù)場(chǎng)景。

這么多年過(guò)去了,這句話或深或淺地影響了我的技術(shù)選擇,以至于后來(lái)我花了很多時(shí)間去重點(diǎn)學(xué)習(xí)緩存相關(guān)的技術(shù)。

我在10年前開(kāi)始使用緩存,從本地緩存、到分布式緩存、再到多級(jí)緩存,踩過(guò)很多坑。下面我結(jié)合自己使用緩存的歷程,談?wù)勎覍?duì)緩存的認(rèn)識(shí)。

01?本地緩存

1. 頁(yè)面級(jí)緩存

我使用緩存的時(shí)間很早,2010年左右使用過(guò) OSCache,當(dāng)時(shí)主要用在 JSP 頁(yè)面中用于實(shí)現(xiàn)頁(yè)面級(jí)緩存。偽代碼類似這樣:
"foobar"?scope="session">?
??????some jsp?content?
中間的那段 JSP 代碼將會(huì)以 key="foobar" 緩存在 session 中,這樣其他頁(yè)面就能共享這段緩存內(nèi)容。 在使用 JSP 這種遠(yuǎn)古技術(shù)的場(chǎng)景下,通過(guò)引入 OSCache 之后 ,頁(yè)面的加載速度確實(shí)提升很快。
但隨著前后端分離以及分布式緩存的興起,服務(wù)端的頁(yè)面級(jí)緩存已經(jīng)很少使用了。但是在前端領(lǐng)域,頁(yè)面級(jí)緩存仍然很流行。

2. 對(duì)象緩存

2011年左右,開(kāi)源中國(guó)的紅薯哥寫(xiě)了很多篇關(guān)于緩存的文章。他提到:開(kāi)源中國(guó)每天百萬(wàn)的動(dòng)態(tài)請(qǐng)求,只用 1 臺(tái) 4 Core 8G 的服務(wù)器就扛住了,得益于緩存框架 Ehcache。
這讓我非常神往,一個(gè)簡(jiǎn)單的框架竟能將單機(jī)性能做到如此這般,讓我欲欲躍試。于是,我參考紅薯哥的示例代碼,在公司的余額提現(xiàn)服務(wù)上第一次使用了 Ehcache。
邏輯也很簡(jiǎn)單,就是將成功或者失敗狀態(tài)的訂單緩存起來(lái),這樣下次查詢的時(shí)候,不用再查詢支付寶服務(wù)了。偽代碼類似這樣:

一個(gè)架構(gòu)師的緩存修煉之路

添加緩存之后,優(yōu)化的效果很明顯 , 任務(wù)耗時(shí)從原來(lái)的40分鐘減少到了5~10分鐘。
上面這個(gè)示例就是典型的對(duì)象緩存,地緩存最常見(jiàn)的應(yīng)用場(chǎng)景。相比頁(yè)面緩存,它的粒度更細(xì)、更靈活,常用來(lái)緩存很少變化的數(shù)據(jù),比如:全局配置、狀態(tài)已完結(jié)的訂單等,用于提升整體的查詢速度。

3. 刷新策略

2018年,我和我的小伙伴自研了配置中心,為了讓客戶端以最快的速度讀取配置, 本地緩存使用了 Guava,整體架構(gòu)如下圖所示:

一個(gè)架構(gòu)師的緩存修煉之路

那本地緩存是如何更新的呢?有兩種機(jī)制:

  • 客戶端啟動(dòng)定時(shí)任務(wù),從配置中心拉取數(shù)據(jù)。
  • 當(dāng)配置中心有數(shù)據(jù)變化時(shí),主動(dòng)推送給客戶端。這里我并沒(méi)有使用websocket,而是使用了 RocketMQ Remoting 通訊框架。
后來(lái)我閱讀了 Soul 網(wǎng)關(guān)的源碼,它的本地緩存更新機(jī)制如下圖所示,共支持 3 種策略:
一個(gè)架構(gòu)師的緩存修煉之路

▍zookeeper watch機(jī)制

soul-admin 在啟動(dòng)的時(shí)候,會(huì)將數(shù)據(jù)全量寫(xiě)入 zookeeper,后續(xù)數(shù)據(jù)發(fā)生變更時(shí),會(huì)增量更新 zookeeper 的節(jié)點(diǎn)。與此同時(shí),soul-web 會(huì)監(jiān)聽(tīng)配置信息的節(jié)點(diǎn),一旦有信息變更時(shí),會(huì)更新本地緩存。

▍websocket 機(jī)制

websocket 和 zookeeper 機(jī)制有點(diǎn)類似,當(dāng)網(wǎng)關(guān)與 admin 首次建立好 websocket 連接時(shí),admin 會(huì)推送一次全量數(shù)據(jù),后續(xù)如果配置數(shù)據(jù)發(fā)生變更,則將增量數(shù)據(jù)通過(guò) websocket 主動(dòng)推送給 soul-web。

▍http 長(zhǎng)輪詢機(jī)制

http請(qǐng)求到達(dá)服務(wù)端后,并不是馬上響應(yīng),而是利用 Servlet 3.0 的異步機(jī)制響應(yīng)數(shù)據(jù)。當(dāng)配置發(fā)生變化時(shí),服務(wù)端會(huì)挨個(gè)移除隊(duì)列中的長(zhǎng)輪詢請(qǐng)求,告知是哪個(gè) Group 的數(shù)據(jù)發(fā)生了變更,網(wǎng)關(guān)收到響應(yīng)后,再次請(qǐng)求該 Group 的配置數(shù)據(jù)。

不知道大家發(fā)現(xiàn)了沒(méi)?
  • pull 模式必不可少
  • 增量推送大同小異
長(zhǎng)輪詢是一個(gè)有意思的話題 , 這種模式在 RocketMQ 的消費(fèi)者模型也同樣被使用,接近準(zhǔn)實(shí)時(shí),并且可以減少服務(wù)端的壓力。

02 分布式緩存

關(guān)于分布式緩存, memcached 和 Redis 應(yīng)該是最常用的技術(shù)選型。相信程序員朋友都非常熟悉了,我這里分享兩個(gè)案例。

1.? 合理控制對(duì)象大小及讀取策略

2013年,我服務(wù)一家彩票公司,我們的比分直播模塊也用到了分布式緩存。當(dāng)時(shí),遇到了一個(gè) Young GC 頻繁的線上問(wèn)題,通過(guò) jstat 工具排查后,發(fā)現(xiàn)新生代每隔兩秒就被占滿了。
進(jìn)一步定位分析,原來(lái)是某些 key 緩存的 value 太大了,平均在 300K左右,最大的達(dá)到了500K。這樣在高并發(fā)下,就很容易 導(dǎo)致 GC 頻繁。
找到了根本原因后,具體怎么改呢? 我當(dāng)時(shí)也沒(méi)有清晰的思路。 于是,我去同行的網(wǎng)站上研究他們是怎么實(shí)現(xiàn)相同功能的,包括: 360彩票,澳客網(wǎng)。我發(fā)現(xiàn)了兩點(diǎn):

1、數(shù)據(jù)格式非常精簡(jiǎn),只返回給前端必要的數(shù)據(jù),部分?jǐn)?shù)據(jù)通過(guò)數(shù)組的方式返回

2、使用 websocket,進(jìn)入頁(yè)面后推送全量數(shù)據(jù),數(shù)據(jù)發(fā)生變化推送增量數(shù)據(jù)

再回到我的問(wèn)題上,最終是用什么方案解決的呢?當(dāng)時(shí),我們的比分直播模塊緩存格式是 JSON 數(shù)組,每個(gè)數(shù)組元素包含 20 多個(gè)鍵值對(duì), 下面的 JSON 示例我僅僅列了其中 4 個(gè)屬性。

[{ "playId":"2399", "guestTeamName":"小牛", "hostTeamName":"湖人", "europe":"123" }]

這種數(shù)據(jù)結(jié)構(gòu),一般情況下沒(méi)有什么問(wèn)題。但是當(dāng)字段數(shù)多達(dá) 20 多個(gè),而且每天的比賽場(chǎng)次非常多時(shí),在高并發(fā)的請(qǐng)求下其實(shí)很容易引發(fā)問(wèn)題。

基于工期以及風(fēng)險(xiǎn)考慮,最終我們采用了比較保守的優(yōu)化方案:

1)修改新生代大小,從原來(lái)的 2G 修改成 4G
2)將緩存數(shù)據(jù)的格式由 JSON 改成數(shù)組,如下所示:
[["2399","小牛","湖人","123"]]

修改完成之后, 緩存的大小從平均 300k 左右降為 80k 左右,YGC 頻率下降很明顯,同時(shí)頁(yè)面響應(yīng)也變快了很多。

但過(guò)了一會(huì),cpu load 會(huì)在瞬間波動(dòng)得比較高。可見(jiàn),雖然我們減少了緩存大小,但是讀取大對(duì)象依然對(duì)系統(tǒng)資源是極大的損耗,導(dǎo)致 Full GC 的頻率也不低。?

3)為了徹底解決這個(gè)問(wèn)題,我們使用了更精細(xì)化的緩存讀取策略。

我們把緩存拆成兩個(gè)部分,第一部分是全量數(shù)據(jù),第二部分是增量數(shù)據(jù)(數(shù)據(jù)量很?。m?yè)面第一次請(qǐng)求拉取全量數(shù)據(jù),當(dāng)比分有變化的時(shí)候,通過(guò) websocket 推送增量數(shù)據(jù)。

第 3 步完成后,頁(yè)面的訪問(wèn)速度極快,服務(wù)器的資源使用也很少,優(yōu)化的效果非常優(yōu)異。

經(jīng)過(guò)這次優(yōu)化,我理解到:? 緩存雖然可以提升整體速度,但是在高并發(fā)場(chǎng)景下,緩存對(duì)象大小依然是需要關(guān)注的點(diǎn),稍不留神就會(huì)產(chǎn)生事故。另外我們也需要合理地控制讀取策略,最大程度減少 GC 的頻率 , 從而提升整體性能。

2.? 分頁(yè)列表查詢

列表如何緩存是我非常渴望和大家分享的技能點(diǎn)。這個(gè)知識(shí)點(diǎn)也是我 2012 年從開(kāi)源中國(guó)上學(xué)到的,下面我以查詢博客列表的場(chǎng)景為例。
我們先說(shuō)第 1 種方案:對(duì)分頁(yè)內(nèi)容進(jìn)行整體緩存。這種方案會(huì) 按照頁(yè)碼和每頁(yè)大小組合成一個(gè)緩存key,緩存值就是博客信息列表。 假如某一個(gè)博客內(nèi)容發(fā)生修改, 我們要重新加載緩存,或者刪除整頁(yè)的緩存。
這種方案,緩存的顆粒度比較大,如果博客更新較為頻繁,則緩存很容易失效。下面我介紹下第 2 種方案:僅對(duì)博客進(jìn)行緩存。流程大致如下:
1)先從數(shù)據(jù)庫(kù)查詢當(dāng)前頁(yè)的博客id列表,sql類似:
select?id?from?blogs?limit?0,10?
2)批量從緩存中獲取博客id列表對(duì)應(yīng)的緩存數(shù)據(jù) ,并記錄沒(méi)有命中的博客id,若沒(méi)有命中的id列表大于0,再次從數(shù)據(jù)庫(kù)中查詢一次,并放入緩存,sql類似:
select?id?from?blogs?where?id?in?(noHitId1,?noHitId2)
3)將沒(méi)有緩存的博客對(duì)象存入緩存中
4)返回博客對(duì)象列表
理論上,要是緩存都預(yù)熱的情況下,一次簡(jiǎn)單的數(shù)據(jù)庫(kù)查詢,一次緩存批量獲取,即可返回所有的數(shù)據(jù)。另外,關(guān)于 存批量獲取,如何實(shí)現(xiàn)?
  • 本地緩存:性能極高,for 循環(huán)即可
  • memcached:使用 mget 命令
  • Redis:若緩存對(duì)象結(jié)構(gòu)簡(jiǎn)單,使用 mget 、hmget命令;若結(jié)構(gòu)復(fù)雜,可以考慮使用 pipleline,lua腳本模式
第 1 種方案適用于數(shù)據(jù)極少發(fā)生變化的場(chǎng)景,比如排行榜,首頁(yè)新聞資訊等。
第 2 種方案適用于大部分的分頁(yè)場(chǎng)景,而且能和其他資源整合在一起。舉例:在搜索系統(tǒng)里,我們可以通過(guò)篩選條件查詢出博客 id 列表,然后通過(guò)如上的方式,快速獲取博客列表。

03 多級(jí)緩存

首先要明確為什么要使用多級(jí)緩存?
本地緩存速度極快,但是容量有限,而且無(wú)法共享內(nèi)存。 分布式緩存容量可擴(kuò)展,但在高并發(fā)場(chǎng)景下,如果所有數(shù)據(jù)都必須從遠(yuǎn)程緩存種獲取,很容易導(dǎo)致帶寬跑滿,吞吐量下降。
有句話說(shuō)得好, 緩存離用戶越近越高效!
使用多級(jí)緩存的好處在于:高并發(fā)場(chǎng)景下, 能提升整個(gè)系統(tǒng)的吞吐量,減少分布式緩存的壓力。
2018年,我服務(wù)的一家電商公司需要進(jìn)行 app 首頁(yè)接口的性能優(yōu)化。我花了大概兩天的時(shí)間完成了整個(gè)方案,采取的是兩級(jí)緩存模式,同時(shí)利用了 guava 的惰性加載機(jī)制,整體架構(gòu)如下圖所示:

一個(gè)架構(gòu)師的緩存修煉之路

緩存讀取流程如下:

1、業(yè)務(wù)網(wǎng)關(guān)剛啟動(dòng)時(shí),本地緩存沒(méi)有數(shù)據(jù),讀取 Redis 緩存,如果 Redis 緩存也沒(méi)數(shù)據(jù),則通過(guò) RPC 調(diào)用導(dǎo)購(gòu)服務(wù)讀取數(shù)據(jù),然后再將數(shù)據(jù)寫(xiě)入本地緩存和 Redis 中;若 Redis 緩存不為空,則將緩存數(shù)據(jù)寫(xiě)入本地緩存中。

2、由于步驟1已經(jīng)對(duì)本地緩存預(yù)熱,后續(xù)請(qǐng)求直接讀取本地緩存,返回給用戶端。

3、Guava 配置了 refresh 機(jī)制,每隔一段時(shí)間會(huì)調(diào)用自定義 LoadingCache 線程池(5個(gè)最大線程,5個(gè)核心線程)去導(dǎo)購(gòu)服務(wù)同步數(shù)據(jù)到本地緩存和 Redis 中。

優(yōu)化后,性能表現(xiàn)很好,平均耗時(shí)在 5ms 左右。最開(kāi)始我以為出現(xiàn)問(wèn)題的幾率很小,可是有一天晚上,突然發(fā)現(xiàn) app 端首頁(yè)顯示的數(shù)據(jù)時(shí)而相同,時(shí)而不同。

也就是說(shuō):?雖然 LoadingCache 線程一直在調(diào)用接口更新緩存信息,但是各個(gè) 服務(wù)器本地緩存中的數(shù)據(jù)并非完成一致。 說(shuō)明了兩個(gè)很重要的點(diǎn): ?

1、惰性加載仍然可能造成多臺(tái)機(jī)器的數(shù)據(jù)不一致

2、 LoadingCache 線程池?cái)?shù)量配置的不太合理,? 導(dǎo)致了線程堆積

最終,我們的解決方案是:
1、惰性加載結(jié)合消息機(jī)制來(lái)更新緩存數(shù)據(jù),也就是:當(dāng)導(dǎo)購(gòu)服務(wù)的配置發(fā)生變化時(shí),通知業(yè)務(wù)網(wǎng)關(guān)重新拉取數(shù)據(jù),更新緩存。
2、適當(dāng)調(diào)大 LoadigCache 的線程池參數(shù),并在線程池埋點(diǎn),監(jiān)控線程池的使用情況,當(dāng)線程繁忙時(shí)能發(fā)出告警,然后動(dòng)態(tài)修改線程池參數(shù)。

特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒(méi)關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:

一個(gè)架構(gòu)師的緩存修煉之路

一個(gè)架構(gòu)師的緩存修煉之路

一個(gè)架構(gòu)師的緩存修煉之路

長(zhǎng)按訂閱更多精彩▼

一個(gè)架構(gòu)師的緩存修煉之路

如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉