偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

字節(jié)二面:假設(shè)10W人突訪,系統(tǒng)怎么保證不Crash ?

開(kāi)發(fā) 前端
Redis Cluster中各node流量不均衡造成Redis Cluster的分布式優(yōu)勢(shì)無(wú)法被Client利用,一個(gè)分片負(fù)載很高而其它分片十分空閑從而產(chǎn)生讀/寫(xiě)熱點(diǎn)問(wèn)題。

今年行情不大好,很多小伙伴來(lái)找我改簡(jiǎn)歷聊面試經(jīng)歷,這不,最近知識(shí)星球的同學(xué)經(jīng)過(guò)朋友內(nèi)推才獲得面試機(jī)會(huì),但是在二面的時(shí)候被問(wèn)倒了,這是一道場(chǎng)景題:假設(shè)10W人突防,系統(tǒng)怎么做到不crash(崩潰) ?

心理防線比較差的同學(xué)一聽(tīng)到10W這個(gè)數(shù)字估計(jì)就有點(diǎn)崩潰了,其實(shí)仔細(xì)理解,這個(gè)題,是面試當(dāng)中一道比較高端的場(chǎng)景題。

這個(gè)題目的回答,大有玄機(jī)?;卮鸬糜兴剑軌蛑苯幽玫給ffer??上?,很多小伙伴可能一句話都說(shuō)不上來(lái)。

如果面試遇到這個(gè)問(wèn)題,很多小伙伴的第一反應(yīng):

怎么可能,我們的系統(tǒng),總體的用戶量,不到1萬(wàn), 怎么可能會(huì)有10W人同時(shí)訪問(wèn)。

疑問(wèn)歸疑問(wèn)。

這個(gè)問(wèn)題,如果遇到了,只能會(huì)硬著頭皮作答。

如果直接用這個(gè)疑問(wèn)去反問(wèn)面試官,那么 ,面試官一定會(huì)說(shuō):這小子 沒(méi)有遇到過(guò)事情,沒(méi)有見(jiàn)過(guò)市面。

為啥呢?

因?yàn)槟呐掠脩舨坏?萬(wàn),其實(shí),咱們的系統(tǒng),還是可能會(huì)有10W人同時(shí)訪問(wèn)滴。這10W人從哪里來(lái)的呢? 這些人包括:

  • 爬蟲(chóng)
  • 刷子(羊毛黨)

爬蟲(chóng)對(duì)訪問(wèn)量的貢獻(xiàn)

大家應(yīng)該聽(tīng)過(guò)一句話吧,整個(gè)互聯(lián)網(wǎng)上大概有 50%以上的流量其實(shí)是爬蟲(chóng)。

一個(gè)做反爬蟲(chóng)哥們,發(fā)現(xiàn)了一個(gè)極端案例,

某個(gè)頁(yè)面12000次點(diǎn)擊里邊,98%的點(diǎn)擊率,是爬蟲(chóng)貢獻(xiàn)的。

爬蟲(chóng)和用戶的比例是 19比1.

那么 1W用戶, 可能會(huì)對(duì)應(yīng)到19W 爬蟲(chóng),

那么 1W用戶, 有沒(méi)有  10W的 同時(shí)訪問(wèn)的可能呢?

因?yàn)?大量爬蟲(chóng)的存著, 當(dāng)然有的。

刷子用戶(羊毛黨)對(duì)訪問(wèn)量的貢獻(xiàn)

“羊毛黨”戰(zhàn)術(shù)之一:開(kāi)啟機(jī)器人批量注冊(cè)新賬號(hào),招募“新兵”。

“這是個(gè)‘昏招’,批量注冊(cè)的賬號(hào)很容易識(shí)別。

“羊毛黨”戰(zhàn)術(shù)之二:提前囤積賬號(hào),囤積的老賬號(hào)”。

但通過(guò)注冊(cè)時(shí)間、注冊(cè)地與下單地比對(duì)等方式,很快識(shí)別出來(lái)。

某年的“618”電商節(jié)活動(dòng)期間,某電商公司,平均每天攔截“羊毛黨”賬號(hào)2000萬(wàn)個(gè)。

那么 1W用戶, 可能會(huì)對(duì)應(yīng)到多少羊毛黨用戶呢?

其中,可能會(huì)包含部分 提前囤積賬號(hào)

另外,在 活動(dòng)執(zhí)行的過(guò)程中, 還是有 可能 批量注冊(cè)大量的新賬號(hào)

那么 1W用戶, 有沒(méi)有  10W的 同時(shí)訪問(wèn)的可能呢?

只要有利可圖,就會(huì)有 刷子用戶(羊毛黨),他們會(huì)通過(guò)群體人手,或者 自動(dòng)化工具,制造大量的瞬間流量。

這些自動(dòng)化工具,在 1s之內(nèi), 嘗試10W次。

所以,只要是有利可圖,如 秒殺等, 那么 1W用戶, 有沒(méi)有  10W的 同時(shí)訪問(wèn)的可能呢?

當(dāng)然有的。

那么,假設(shè)10W人突然訪問(wèn),現(xiàn)有架構(gòu)能否扛住?

按照之前和大家分析的架構(gòu)理論

一個(gè)系統(tǒng)10W人同時(shí)訪問(wèn) , 也就是:并發(fā)量為 10w Qps

那么 10w Qps ,對(duì)應(yīng)到多少用戶量呢  ?

是 一個(gè)1億的用戶量。

而 ,我們很多同學(xué)手上的 系統(tǒng), 總體的用戶量 不到1萬(wàn),

不到1萬(wàn)的用戶,對(duì)應(yīng)到多少 的 吞吐量呢?

是 10。

沒(méi)錯(cuò),如果 總體的用戶量 不到1萬(wàn),按照 正常估算, 吞吐量就只有 10。

也就是說(shuō), 如果我們按照 1萬(wàn) 做系統(tǒng)架構(gòu)

圖片

這種架構(gòu),對(duì)于 qps 為10 的小流量來(lái)說(shuō),可以說(shuō)是 小菜一碟。

可以說(shuō),用牛刀 在 殺雞。

那么,如果發(fā)生突發(fā)情況,

假設(shè)10W人突然訪問(wèn),我們的架構(gòu),如何抵抗?

圖片

大家看看,上面的架構(gòu), 能抵抗嗎?

接入層和服務(wù)層如何抵抗?

方式之一:擴(kuò)容

方式之二:限流

首先能用到的策略:擴(kuò)容

大家首先會(huì)想到的策略,就是擴(kuò)容。

圖片

但是,如果流量是突發(fā)的, 又不知道什么時(shí)候擴(kuò), 怎么辦呢?

那么就是自動(dòng)擴(kuò)容。

其次能用到的策略:限流

  • nginx 限流
  • SpringCloud gateway 限流

接入層限流可以進(jìn)行 nginx 限流

圖片

微服務(wù) SpringCloud gateway 里邊,

還 可以使用 redis lua進(jìn)行分布式限流, 或者使用 sentinel 進(jìn)行 限流,

經(jīng)過(guò)擴(kuò)容和限流,關(guān)注公眾號(hào):碼猿技術(shù)專欄,回復(fù)關(guān)鍵詞:1111 獲取阿里內(nèi)部Java性能調(diào)優(yōu)手冊(cè)! 咱們的系統(tǒng),應(yīng)該可以扛住 10Wqps, 因?yàn)榭梢园蚜髁肯拗频?1Wqps,甚至是 1 K qps。

誰(shuí)怪 有那么多刷子流量,或者 爬蟲(chóng)流量呢。

但是,限流是無(wú)奈之舉。

或者說(shuō),如果10Wqps,都是有效流量, 不能使用限流這 簡(jiǎn)單粗暴的方式 , 而是這個(gè) 10Wqps 必須進(jìn)入到服務(wù)層。

分布式Redis集群如何抵抗?

這個(gè) 10Wqps 必須進(jìn)入到服務(wù)層。

怎么辦?

服務(wù)層 倒是好說(shuō),和網(wǎng)關(guān)一樣, 可以通過(guò)擴(kuò)容解決。

所以,后面的 流量就進(jìn)入  redis集群。

圖片

redis 集群一般搭建的是 3主3從:

圖片

一般來(lái)說(shuō),主節(jié)點(diǎn)提供服務(wù), 從節(jié)點(diǎn)是做冗余的, 并不提供數(shù)據(jù)的寫(xiě)入服務(wù)。

redis cluster模式官方默認(rèn)主節(jié)點(diǎn)提供讀寫(xiě),  從節(jié)點(diǎn)提供slot數(shù)據(jù)備份以及故障轉(zhuǎn)移。默認(rèn)情況下,從節(jié)點(diǎn)并不提供數(shù)據(jù)讀寫(xiě)服務(wù)。

單個(gè)redis 的吞吐量,一般就是 2W左右。

那么 10Wqps,訪問(wèn) redis cluster,分布到 3個(gè)節(jié)點(diǎn), 還是不夠。

如果 10Wqps 訪問(wèn)的是同一個(gè)key, 那就問(wèn)題更大了。

因?yàn)?單個(gè)redis 的吞吐量,一般就是 2W左右。怎么可能扛住  5倍的吞吐量。

于是就很容易出現(xiàn) redis cpu 100%, 請(qǐng)求排隊(duì), 沒(méi)有響應(yīng),嚴(yán)重的情況 出現(xiàn) redis 雪崩。

于是乎,改怎么辦?

大概也有兩種方案:

方法一:redis 擴(kuò)容

方法二:本地緩存

方法一 redis 擴(kuò)容 可以解決 key 的訪問(wèn)量比較 均勻的問(wèn)題。比如擴(kuò)容到 10主10從,就可以承擔(dān) 20Wqps的 流量。

但是方法一 要求每個(gè)key的訪問(wèn)量 必須分布得比較均勻。如果20w qps 的流量,全部來(lái)自一個(gè)key, 則方案一 無(wú)效。

方法二 本地緩存 可以解決 單個(gè)key 訪問(wèn)量 巨大的問(wèn)題。這種 占據(jù)大量流量的 單個(gè)key,叫做 hotkey(熱key)。

所以,接下來(lái),還是得調(diào)整系統(tǒng)的架構(gòu), 加入本地緩存的 環(huán)節(jié)。

解決 10WQps 突發(fā)流量的本地緩存架構(gòu)

解決 10WQps 突發(fā)流量的本地緩存架構(gòu),大致有兩種:

  • 二級(jí)緩存架構(gòu)
  • 三級(jí)緩存架構(gòu)

二級(jí)緩存架構(gòu):

java 本地緩存+ redis 分布式緩存,具體如下圖:

圖片

先發(fā)問(wèn)一級(jí)緩存caffeine ,如果 沒(méi)有找到,再訪問(wèn) 二級(jí)緩存 redis 集群

三級(jí)緩存架構(gòu):

nginx本地緩存+ java 本地緩存+ redis 分布式緩存,具體如下圖:

圖片

本地緩存的優(yōu)缺點(diǎn)

1. 快但是量少:訪問(wèn)速度快,但無(wú)法進(jìn)行大數(shù)據(jù)存儲(chǔ)

本地緩存相對(duì)于分布式緩存的好處是,由于數(shù)據(jù)不需要跨網(wǎng)絡(luò)傳輸,故性能更好,

但是由于占用了應(yīng)用進(jìn)程的內(nèi)存空間,如 Java 進(jìn)程的 JVM 內(nèi)存空間,故不能進(jìn)行大數(shù)據(jù)量的數(shù)據(jù)存儲(chǔ)。

2. 需要解決數(shù)據(jù)一致性問(wèn)題:本地緩存、分布式緩存、DB數(shù)據(jù)一致性問(wèn)題

與此同時(shí),本地緩存只支持被該應(yīng)用進(jìn)程訪問(wèn),一般無(wú)法被其他應(yīng)用進(jìn)程訪問(wèn),故在應(yīng)用進(jìn)程的集群部署當(dāng)中,

如果對(duì)應(yīng)的數(shù)據(jù)庫(kù)數(shù)據(jù),存在數(shù)據(jù)更新,則需要同步更新不同部署節(jié)點(diǎn)的緩存數(shù)據(jù)來(lái)包保證數(shù)據(jù)一致性,

復(fù)雜度較高并且容易出錯(cuò),如基于 rocketmq 的發(fā)布訂閱機(jī)制來(lái)同步更新各個(gè)部署節(jié)點(diǎn)。

3.未持久化,容易丟失:數(shù)據(jù)隨應(yīng)用進(jìn)程的重啟而丟失

由于本地緩存的數(shù)據(jù)是存儲(chǔ)在應(yīng)用進(jìn)程的內(nèi)存空間的,所以當(dāng)應(yīng)用進(jìn)程重啟時(shí),本地緩存的數(shù)據(jù)會(huì)丟失。

所以對(duì)于需要更改然后持久化的數(shù)據(jù),需要注意及時(shí)保存,否則可能會(huì)造成數(shù)據(jù)丟失。

4.需要盡量緩存熱點(diǎn)key,而提升緩存的命中率

由于本地緩存太小,從而很容易被淘汰,

如果還沒(méi)有來(lái)得及訪問(wèn),本地緩存中的數(shù)據(jù),就被淘汰了,那就失去了本地緩存的價(jià)值, 當(dāng)然,本地緩存的命中率也會(huì)很低。

如何提升緩存的命中率?

方式1:采用更好的  緩存淘汰策略

比如caffeine中,使用了 w-tinylfu 策略。

這種策略的  緩存的命中率,比較簡(jiǎn)單的 lfu、lru 都 高出很多。

有測(cè)試表明:caffeine 比 guava 的命中率,不同場(chǎng)景,都會(huì)高出10%以上。

方式2:盡量識(shí)別和緩存 熱點(diǎn)數(shù)據(jù)

簡(jiǎn)單的說(shuō),把熱點(diǎn)數(shù)據(jù), 加載到本地緩存。

什么是HotKey?

在某個(gè)Key接收到的訪問(wèn)次數(shù)、顯著高于其它Key時(shí),我們可以將其稱之為HotKey,

從訪問(wèn)量上來(lái)說(shuō),常見(jiàn)的HotKey如:

  • 某Redis實(shí)例的每秒總訪問(wèn)量為10000,而其中一個(gè)Key的每秒訪問(wèn)量達(dá)到了7000(訪問(wèn)次數(shù)顯著高于其它Key)對(duì)一個(gè)擁有上千個(gè)成員且總大小為1MB的HASH Key每秒發(fā)送大量的HGETALL(帶寬占用顯著高于其它Key)
  • 對(duì)一個(gè)擁有數(shù)萬(wàn)個(gè)成員的ZSET Key每秒發(fā)送大量的ZRANGE(CPU時(shí)間占用顯著高于其它Key)

從業(yè)務(wù)上來(lái)說(shuō), 常見(jiàn)的HotKey如:

1 、MySQL等數(shù)據(jù)庫(kù)會(huì)被頻繁訪問(wèn)的熱數(shù)據(jù)

如爆款商品的skuId。

2 、redis的被密集訪問(wèn)的key

如爆款商品的各維度信息,skuId、shopId等。

3 、機(jī)器人、爬蟲(chóng)、刷子用戶

如用戶的userId、uuid、ip等。

4 、某個(gè)接口地址

如/sku/query或者更精細(xì)維度的。

注意,我們的HotKey探測(cè)框架只關(guān)心key,其實(shí)就是一個(gè)字符串,

HotKey對(duì)服務(wù)層和數(shù)據(jù)層的風(fēng)險(xiǎn)

在擁有大量并發(fā)用戶的系統(tǒng)中,HotKey一直以來(lái)都是一個(gè)不可避免的問(wèn)題。

  • 或許是突然某些商品成了爆款,
  • 或許是海量用戶突然涌入某個(gè)店鋪,
  • 或許是秒殺時(shí)瞬間大量開(kāi)啟的爬蟲(chóng)用戶,
  • 突發(fā)大批機(jī)器人以遠(yuǎn)超正常用戶的速度發(fā)起極其密集的請(qǐng)求,這些機(jī)器人只需要很小的代價(jià),就能發(fā)出百倍于普通用戶的請(qǐng)求量,從而大幅擠占正常用戶的資源。

以京東為例的這些頭部互聯(lián)網(wǎng)公司,動(dòng)輒某個(gè)爆品,會(huì)瞬間引入每秒上百萬(wàn)甚至數(shù)百萬(wàn)的請(qǐng)求,當(dāng)然流量多數(shù)會(huì)在幾秒內(nèi)就消失。

但就是這短短的幾秒的HotKey,就會(huì)瞬間造成其所在redis分片集群癱瘓。

原因也很簡(jiǎn)單,redis作為一個(gè)單線程的結(jié)構(gòu),所有的請(qǐng)求到來(lái)后都會(huì)去排隊(duì),當(dāng)請(qǐng)求量遠(yuǎn)大于自身處理能力時(shí),后面的請(qǐng)求會(huì)陷入等待、超時(shí)。

由于該redis分片完全被這個(gè)key的請(qǐng)求給打滿,導(dǎo)致該分片上所有其他數(shù)據(jù)操作都無(wú)法繼續(xù)提供服務(wù),也就是HotKey不僅僅影響自己,還會(huì)影響和它合租的數(shù)據(jù)。

這樣,redis 緩存沒(méi)有響應(yīng)之后,相當(dāng)于 redis 擊穿, 請(qǐng)求直接轉(zhuǎn)向DB

DB的吞吐量,比如會(huì)低很多,DB 就會(huì)雪崩。

總結(jié)一下,HotKey帶來(lái)的常見(jiàn)問(wèn)題

  • HotKey占用大量的Redis CPU時(shí)間,使其性能變差并影響其它請(qǐng)求;
  • Redis Cluster中各node流量不均衡造成Redis Cluster的分布式優(yōu)勢(shì)無(wú)法被Client利用,一個(gè)分片負(fù)載很高而其它分片十分空閑從而產(chǎn)生讀/寫(xiě)熱點(diǎn)問(wèn)題;
  • 在搶購(gòu)、秒殺活動(dòng)中,由于商品對(duì)應(yīng)庫(kù)存Key的請(qǐng)求量過(guò)大,超出Redis處理能力造成超賣;
  • HotKey的請(qǐng)求壓力數(shù)量超出Redis的承受能力造成緩存擊穿,此時(shí)大量強(qiáng)求將直接指向后端存儲(chǔ),將后端存儲(chǔ)打掛并影響到其它業(yè)務(wù);

HotKey問(wèn)題的根本:

HotKey問(wèn)題歸根到底就是如何找到HotKey,并將HotKey放到本地內(nèi)存的問(wèn)題。

只要該key在內(nèi)存里,我們就能極快地來(lái)對(duì)它做邏輯,內(nèi)存訪問(wèn)和redis訪問(wèn)的速度不在一個(gè)量級(jí)。

如果該key是在本地內(nèi)存中,讀取一個(gè)內(nèi)存中的值,每秒多少個(gè)萬(wàn)次都是很正常的,不存在任何數(shù)據(jù)層的瓶頸。

但問(wèn)題是事先不知道HotKey在哪里?

那么,問(wèn)題就來(lái)了,如何進(jìn)行 HotKey的探測(cè)?

HotKey探測(cè)關(guān)鍵指標(biāo)

1、實(shí)時(shí)性

這個(gè)很容易理解,key往往是突發(fā)性瞬間就熱了,根本不給你再慢悠悠手工去配置中心添加HotKey再推送到j(luò)vm的機(jī)會(huì)。

它大部分時(shí)間不可預(yù)知,來(lái)得也非常迅速,可能某個(gè)商家上個(gè)活動(dòng),瞬間HotKey就出現(xiàn)了。如果短時(shí)間內(nèi)沒(méi)能進(jìn)到內(nèi)存,就有redis集群被打爆的風(fēng)險(xiǎn)。

所以HotKey探測(cè)框架最重要的就是實(shí)時(shí)性,最好是某個(gè)key剛有熱的苗頭,在1秒內(nèi)它就已經(jīng)進(jìn)到整個(gè)服務(wù)集群的內(nèi)存里了,1秒后就不會(huì)再去密集訪問(wèn)redis了。

同理,對(duì)于刷子用戶也一樣,剛開(kāi)始刷,1秒內(nèi)我就把它給禁掉了。

2、準(zhǔn)確性

這個(gè)很重要,也容易實(shí)現(xiàn),累加數(shù)量,做到不誤探,精準(zhǔn)探測(cè),保證探測(cè)出的HotKey是完全符合用戶自己設(shè)定的閾值。

3、集群一致性

這個(gè)比較重要,尤其是某些帶刪除key的場(chǎng)景,要能做到刪key時(shí)整個(gè)集群內(nèi)的該key都會(huì)刪掉,以避免數(shù)據(jù)的錯(cuò)誤。

4、高性能

這個(gè)是核心之一,高性能帶來(lái)的就是低成本,做HotKey探測(cè)目的就是為了降低數(shù)據(jù)層的負(fù)載,提升應(yīng)用層的性能,節(jié)省服務(wù)器資源。不然,大家直接去整體擴(kuò)充redis集群規(guī)模就好了。

理論上,在不影響實(shí)時(shí)性的情況下,要完成實(shí)時(shí)HotKey探測(cè),所消耗的機(jī)器資源越少,那么經(jīng)濟(jì)價(jià)值就越大。

如何實(shí)現(xiàn)HotKey探測(cè)?

HotKey探測(cè)方案1: 流計(jì)算集群

通過(guò)  流式計(jì)算集群 storm/ flink 集群,進(jìn)行 topkey

圖片

java 應(yīng)用將訪問(wèn) 記錄發(fā)送到 消息隊(duì)列,如 kafka

storm、flink 集群,進(jìn)行top N 的計(jì)算,把top N 結(jié)果存在 redis

其中的 top N 的key,就是熱點(diǎn) key

HotKey探測(cè)方案2: 流計(jì)算集群

有贊透明多級(jí)緩存解決方案

HotKey探測(cè)方案3: 結(jié)合開(kāi)源hotkey,做熱點(diǎn)探測(cè)

比如:結(jié)合京東開(kāi)源hotkey,做熱點(diǎn)探測(cè)

HotKey探測(cè)方案2:有贊透明多級(jí)緩存解決方案(TMC)

一、TMC簡(jiǎn)介

1-1. TMC 是什么

TMC ,即“透明多級(jí)緩存( Transparent Multilevel Cache )”,是有贊 PaaS 團(tuán)隊(duì)給公司內(nèi)應(yīng)用提供的整體緩存解決方案。

TMC 在通用“分布式緩存解決方案(如 CodisProxy + Redis ,如有贊自研分布式緩存系統(tǒng) zanKV )”基礎(chǔ)上,增加了以下功能:

  • 應(yīng)用層熱點(diǎn)探測(cè)
  • 應(yīng)用層本地緩存
  • 應(yīng)用層緩存命中統(tǒng)計(jì)

以幫助應(yīng)用層解決緩存使用過(guò)程中出現(xiàn)的熱點(diǎn)訪問(wèn)問(wèn)題。

1-2. 為什么要做 TMC

使用有贊服務(wù)的電商商家數(shù)量和類型很多,商家會(huì)不定期做一些“商品秒殺”、“商品推廣”活動(dòng),導(dǎo)致“營(yíng)銷活動(dòng)”、“商品詳情”、“交易下單”等鏈路應(yīng)用出現(xiàn) 緩存熱點(diǎn)訪問(wèn) 的情況:

  • 活動(dòng)時(shí)間、活動(dòng)類型、活動(dòng)商品之類的信息不可預(yù)期,導(dǎo)致 緩存熱點(diǎn)訪問(wèn) 情況不可提前預(yù)知;
  • 緩存熱點(diǎn)訪問(wèn) 出現(xiàn)期間,應(yīng)用層少數(shù) 熱點(diǎn)訪問(wèn) key 產(chǎn)生大量緩存訪問(wèn)請(qǐng)求:沖擊分布式緩存系統(tǒng),大量占據(jù)內(nèi)網(wǎng)帶寬,最終影響應(yīng)用層系統(tǒng)穩(wěn)定性;

為了應(yīng)對(duì)以上問(wèn)題,需要一個(gè)能夠 自動(dòng)發(fā)現(xiàn)熱點(diǎn) 并 將熱點(diǎn)緩存訪問(wèn)請(qǐng)求前置在應(yīng)用層本地緩存 的解決方案,這就是 TMC 產(chǎn)生的原因。

1-3. 多級(jí)緩存解決方案的痛點(diǎn)

基于上述描述,我們總結(jié)了下列 多級(jí)緩存解決方案 需要解決的需求痛點(diǎn):

  • 熱點(diǎn)探測(cè):如何快速且準(zhǔn)確的發(fā)現(xiàn) 熱點(diǎn)訪問(wèn) key ?
  • 數(shù)據(jù)一致性:前置在應(yīng)用層的本地緩存,如何保障與分布式緩存系統(tǒng)的數(shù)據(jù)一致性?
  • 效果驗(yàn)證:如何讓?xiě)?yīng)用層查看本地緩存命中率、熱點(diǎn) key 等數(shù)據(jù),驗(yàn)證多級(jí)緩存效果?
  • 透明接入:整體解決方案如何減少對(duì)應(yīng)用系統(tǒng)的入侵,做到快速平滑接入?

TMC 聚焦上述痛點(diǎn),設(shè)計(jì)并實(shí)現(xiàn)了整體解決方案。

以支持“熱點(diǎn)探測(cè)”和“本地緩存”,減少熱點(diǎn)訪問(wèn)時(shí)對(duì)下游分布式緩存服務(wù)的沖擊,避免影響應(yīng)用服務(wù)的性能及穩(wěn)定性。

二、 TMC 整體架構(gòu)

圖片

TMC 整體架構(gòu)如上圖,共分為三層:

  • 存儲(chǔ)層:提供基礎(chǔ)的kv數(shù)據(jù)存儲(chǔ)能力,針對(duì)不同的業(yè)務(wù)場(chǎng)景選用不同的存儲(chǔ)服務(wù)( codis / zankv / aerospike );
  • 代理層:為應(yīng)用層提供統(tǒng)一的緩存使用入口及通信協(xié)議,承擔(dān)分布式數(shù)據(jù)水平切分后的路由功能轉(zhuǎn)發(fā)工作;
  • 應(yīng)用層:提供統(tǒng)一客戶端給應(yīng)用服務(wù)使用,內(nèi)置“熱點(diǎn)探測(cè)”、“本地緩存”等功能,對(duì)業(yè)務(wù)透明;

三、 TMC 本地緩存

3-1. 如何透明

TMC 是如何減少對(duì)業(yè)務(wù)應(yīng)用系統(tǒng)的入侵,做到透明接入的?

對(duì)于公司 Java 應(yīng)用服務(wù),在緩存客戶端使用方式上分為兩類:

  • 基于spring.data.redis包,使用RedisTemplate編寫(xiě)業(yè)務(wù)代碼;
  • 基于youzan.framework.redis包,使用RedisClient編寫(xiě)業(yè)務(wù)代碼;

不論使用以上那種方式,最終通過(guò)JedisPool?創(chuàng)建的Jedis對(duì)象與緩存服務(wù)端代理層做請(qǐng)求交互。

圖片

TMC 對(duì)原生jedis包的JedisPool和Jedis類做了改造,

在JedisPool初始化過(guò)程中, 集成TMC“熱點(diǎn)發(fā)現(xiàn)”+“本地緩存”功能Hermes-SDK包的初始化邏輯,

使Jedis?客戶端與緩存服務(wù)端代理層交互時(shí),  先與Hermes-SDK交互,從而完成 “熱點(diǎn)探測(cè)”+“本地緩存”功能的透明接入。

對(duì)于 Java 應(yīng)用服務(wù),只需使用特定版本的 jedis-jar 包,無(wú)需修改代碼,即可接入 TMC 使用“熱點(diǎn)發(fā)現(xiàn)”+“本地緩存”功能,做到了對(duì)應(yīng)用系統(tǒng)的最小入侵。

3-2. 整體結(jié)構(gòu)

圖片

3-2-1. 模塊劃分

TMC 本地緩存整體結(jié)構(gòu)分為如下模塊:

  • Jedis-Client:Java 應(yīng)用與緩存服務(wù)端交互的直接入口,接口定義與原生 Jedis-Client 無(wú)異;
  • Hermes-SDK:自研“熱點(diǎn)發(fā)現(xiàn)+本地緩存”功能的SDK封裝, Jedis-Client 通過(guò)與它交互來(lái)集成相應(yīng)能力;
  • Hermes服務(wù)端集群:接收 Hermes-SDK 上報(bào)的緩存訪問(wèn)數(shù)據(jù),進(jìn)行熱點(diǎn)探測(cè),將熱點(diǎn) key 推送給 Hermes-SDK 做本地緩存;
  • 緩存集群:由代理層和存儲(chǔ)層組成,為應(yīng)用客戶端提供統(tǒng)一的分布式緩存服務(wù)入口;
  • 基礎(chǔ)組件:etcd 集群、 Apollo 配置中心,為 TMC 提供“集群推送”和“統(tǒng)一配置”能力;

3-2-2. 基本流程

1) key 值獲取

  • Java 應(yīng)用調(diào)用 Jedis-Client 接口獲取key的緩存值時(shí),Jedis-Client 會(huì)詢問(wèn) Hermes-SDK 該 key 當(dāng)前是否是 熱點(diǎn)key;
  • 對(duì)于 熱點(diǎn)key ,直接從 Hermes-SDK 的 熱點(diǎn)模塊 獲取熱點(diǎn) key 在本地緩存的 value 值,不去訪問(wèn) 緩存集群 ,從而將訪問(wèn)請(qǐng)求前置在應(yīng)用層;
  • 對(duì)于非 熱點(diǎn)key ,Hermes-SDK 會(huì)通過(guò)Callable回調(diào) Jedis-Client 的原生接口,從 緩存集群 拿到 value 值;
  • 對(duì)于 Jedis-Client 的每次 key 值訪問(wèn)請(qǐng)求,Hermes-SDK 都會(huì)通過(guò)其 通信模塊 將 key訪問(wèn)事件 異步上報(bào)給 Hermes服務(wù)端集群 ,以便其根據(jù)上報(bào)數(shù)據(jù)進(jìn)行“熱點(diǎn)探測(cè)”;

2)key值過(guò)期

  • Java 應(yīng)用調(diào)用 Jedis-Client 的set() del() expire()接口時(shí)會(huì)導(dǎo)致對(duì)應(yīng) key 值失效,Jedis-Client 會(huì)同步調(diào)用 Hermes-SDK 的invalid()方法告知其“ key 值失效”事件;
  • 對(duì)于 熱點(diǎn)key ,Hermes-SDK 的 熱點(diǎn)模塊 會(huì)先將 key 在本地緩存的 value 值失效,以達(dá)到本地?cái)?shù)據(jù)強(qiáng)一致。同時(shí) 通信模塊 會(huì)異步將“ key 值失效”事件通過(guò) etcd集群 推送給 Java 應(yīng)用集群中其他 Hermes-SDK 節(jié)點(diǎn);
  • 其他Hermes-SDK節(jié)點(diǎn)的 通信模塊 收到 “ key 值失效”事件后,會(huì)調(diào)用 熱點(diǎn)模塊 將 key 在本地緩存的 value 值失效,以達(dá)到集群數(shù)據(jù)最終一致;

3)熱點(diǎn)發(fā)現(xiàn)

  • Hermes服務(wù)端集群 不斷收集 Hermes-SDK上報(bào)的 key訪問(wèn)事件,對(duì)不同業(yè)務(wù)應(yīng)用集群的緩存訪問(wèn)數(shù)據(jù)進(jìn)行周期性(3s一次)分析計(jì)算,以探測(cè)業(yè)務(wù)應(yīng)用集群中的熱點(diǎn)key列表;
  • 對(duì)于探測(cè)到的熱點(diǎn)key列表,Hermes服務(wù)端集群 將其通過(guò) etcd集群 推送給不同業(yè)務(wù)應(yīng)用集群的 Hermes-SDK 通信模塊,通知其對(duì)熱點(diǎn)key列表進(jìn)行本地緩存;

4)配置讀取

  • Hermes-SDK 在啟動(dòng)及運(yùn)行過(guò)程中,會(huì)從 Apollo配置中心 讀取其關(guān)心的配置信息(如:?jiǎn)?dòng)關(guān)閉配置、黑白名單配置、etcd地址...);
  • Hermes服務(wù)端集群 在啟動(dòng)及運(yùn)行過(guò)程中,會(huì)從 Apollo配置中心 讀取其關(guān)心的配置信息(如:業(yè)務(wù)應(yīng)用列表、熱點(diǎn)閾值配置、 etcd 地址...);

3-2-3. 穩(wěn)定性

TMC本地緩存穩(wěn)定性表現(xiàn)在以下方面:

  • 數(shù)據(jù)上報(bào)異步化:Hermes-SDK 使用rsyslog技術(shù)對(duì)“ key 訪問(wèn)事件”進(jìn)行異步化上報(bào),不會(huì)阻塞業(yè)務(wù);
  • 通信模塊線程隔離:Hermes-SDK 的 通信模塊 使用獨(dú)立線程池+有界隊(duì)列,保證事件上報(bào)&監(jiān)聽(tīng)的I/O操作與業(yè)務(wù)執(zhí)行線程隔離,即使出現(xiàn)非預(yù)期性異常也不會(huì)影響基本業(yè)務(wù)功能;
  • 緩存管控:Hermes-SDK 的 熱點(diǎn)模塊 對(duì)本地緩存大小上限進(jìn)行了管控,使其占用內(nèi)存不超過(guò) 64MB(LRU),杜絕 JVM 堆內(nèi)存溢出的可能;

3-2-4. 一致性

TMC 本地緩存一致性表現(xiàn)在以下方面:

  • Hermes-SDK 的 熱點(diǎn)模塊 僅緩存 熱點(diǎn)key 數(shù)據(jù),絕大多數(shù)非熱點(diǎn) key 數(shù)據(jù)由 緩存集群 存儲(chǔ);
  • 熱點(diǎn)key 變更導(dǎo)致 value 失效時(shí),Hermes-SDK 同步失效本地緩存,保證 本地強(qiáng)一致;
  • 熱點(diǎn)key 變更導(dǎo)致 value 失效時(shí),Hermes-SDK 通過(guò) etcd集群 廣播事件,異步失效業(yè)務(wù)應(yīng)用集群中其他節(jié)點(diǎn)的本地緩存,保證 集群最終一致;

四、TMC熱點(diǎn)發(fā)現(xiàn)

4-1. 整體流程

圖片

TMC 熱點(diǎn)發(fā)現(xiàn)流程分為四步:

  • 數(shù)據(jù)收集:收集 Hermes-SDK 上報(bào)的 key訪問(wèn)事件;
  • 熱度滑窗:對(duì) App 的每個(gè) Key ,維護(hù)一個(gè)時(shí)間輪,記錄基于當(dāng)前時(shí)刻滑窗的訪問(wèn)熱度;
  • 熱度匯聚:對(duì) App 的所有 Key ,以<key,熱度>的形式進(jìn)行 熱度排序匯總;
  • 熱點(diǎn)探測(cè):對(duì) App ,從 熱Key排序匯總 結(jié)果中選出 TopN的熱點(diǎn)Key ,推送給 Hermes-SDK;

4-2. 數(shù)據(jù)收集

Hermes-SDK 通過(guò)本地rsyslog將 key訪問(wèn)事件 以協(xié)議格式放入 kafka ,Hermes服務(wù)端集群 的每個(gè)節(jié)點(diǎn)消費(fèi) kafka 消息,實(shí)時(shí)獲取 key訪問(wèn)事件。

訪問(wèn)事件協(xié)議格式如下:

  • appName:集群節(jié)點(diǎn)所屬業(yè)務(wù)應(yīng)用
  • uniqueKey:業(yè)務(wù)應(yīng)用 key訪問(wèn)事件 的 key
  • sendTime:業(yè)務(wù)應(yīng)用 key訪問(wèn)事件 的發(fā)生時(shí)間
  • weight:業(yè)務(wù)應(yīng)用 key訪問(wèn)事件 的訪問(wèn)權(quán)值

Hermes服務(wù)端集群 節(jié)點(diǎn)將收集到的 key訪問(wèn)事件 存儲(chǔ)在本地內(nèi)存中,

內(nèi)存數(shù)據(jù)結(jié)構(gòu)為Map<String, Map<String, LongAdder>>,

對(duì)應(yīng)業(yè)務(wù)含義映射為Map< appName , Map< uniqueKey , 熱度 >>。

4-3. 熱度滑窗

圖片

4-3-1. 時(shí)間滑窗

Hermes服務(wù)端集群 節(jié)點(diǎn),對(duì)每個(gè)App的每個(gè) key ,維護(hù)了一個(gè) 時(shí)間輪:

  • 時(shí)間輪中共10個(gè) 時(shí)間片,每個(gè)時(shí)間片記錄當(dāng)前 key 對(duì)應(yīng) 3 秒時(shí)間周期的總訪問(wèn)次數(shù);
  • 時(shí)間輪10個(gè)時(shí)間片的記錄累加即表示當(dāng)前 key 從當(dāng)前時(shí)間向前 30 秒時(shí)間窗口內(nèi)的總訪問(wèn)次數(shù);

4-3-2. 映射任務(wù)

Hermes服務(wù)端集群 節(jié)點(diǎn),對(duì)每個(gè) App 每3秒 生成一個(gè) 映射任務(wù) ,交由節(jié)點(diǎn)內(nèi) “緩存映射線程池” 執(zhí)行。

映射任務(wù) 內(nèi)容如下:

  • 對(duì)當(dāng)前 App ,從Map< appName , Map< uniqueKey , 熱度 >>中取出 appName 對(duì)應(yīng)的Map Map< uniqueKey , 熱度 >>;
  • 遍歷Map< uniqueKey , 熱度 >>中的 key ,對(duì)每個(gè) key 取出其熱度存入其 時(shí)間輪 對(duì)應(yīng)的時(shí)間片中;

4-4. 熱度匯聚

圖片

完成第二步“熱度滑窗”后,映射任務(wù) 繼續(xù)對(duì)當(dāng)前 App 進(jìn)行“熱度匯聚”工作:

  • 遍歷 App 的 key ,將每個(gè) key 的 時(shí)間輪 熱度進(jìn)行匯總(即30秒時(shí)間窗口內(nèi)總熱度)得到探測(cè)時(shí)刻 滑窗總熱度;
  • 將 < key , 滑窗總熱度 > 以排序集合的方式存入 Redis存儲(chǔ)服務(wù) 中,即 熱度匯聚結(jié)果;

4-5. 熱點(diǎn)探測(cè)

  • 在前幾步,每3秒 一次的 映射任務(wù) 執(zhí)行,對(duì)每個(gè) App 都會(huì)產(chǎn)生一份當(dāng)前時(shí)刻的 熱度匯聚結(jié)果 ;
  • Hermes服務(wù)端集群 中的“熱點(diǎn)探測(cè)”節(jié)點(diǎn),對(duì)每個(gè) App ,只需周期性從其最近一份 熱度匯聚結(jié)果 中取出達(dá)到熱度閾值的 TopN 的 key 列表,即可得到本次探測(cè)的 熱點(diǎn)key列表;

TMC 熱點(diǎn)發(fā)現(xiàn)整體流程如下圖:

圖片

4-6. 特性總結(jié)

4-6-1. 實(shí)時(shí)性

Hermes-SDK基于rsyslog + kafka 實(shí)時(shí)上報(bào) key訪問(wèn)事件。映射任務(wù) 3秒一個(gè)周期完成“熱度滑窗” + “熱度匯聚”工作,當(dāng)有 熱點(diǎn)訪問(wèn)場(chǎng)景 出現(xiàn)時(shí)最長(zhǎng)3秒即可探測(cè)出對(duì)應(yīng) 熱點(diǎn)key。

4-6-2. 準(zhǔn)確性

key 的熱度匯聚結(jié)果由“基于時(shí)間輪實(shí)現(xiàn)的滑動(dòng)窗口”匯聚得到,相對(duì)準(zhǔn)確地反應(yīng)當(dāng)前及最近正在發(fā)生訪問(wèn)分布。

4-6-3.擴(kuò)展性

Hermes服務(wù)端集群 節(jié)點(diǎn)無(wú)狀態(tài),節(jié)點(diǎn)數(shù)可基于 kafka 的 partition 數(shù)量橫向擴(kuò)展。

“熱度滑窗” + “熱度匯聚” 過(guò)程基于 App 數(shù)量,在單節(jié)點(diǎn)內(nèi)多線程擴(kuò)展。

五、TMC實(shí)戰(zhàn)效果

5-1. 快手商家某次商品營(yíng)銷活動(dòng)

有贊商家通過(guò)快手直播平臺(tái)為某商品搞活動(dòng),造成該商品短時(shí)間內(nèi)被集中訪問(wèn)產(chǎn)生訪問(wèn)熱點(diǎn),活動(dòng)期間 TMC 記錄的實(shí)際熱點(diǎn)訪問(wèn)效果數(shù)據(jù)如下:

5-1-1. 某核心應(yīng)用的緩存請(qǐng)求&命中率曲線圖

圖片

  • 上圖藍(lán)線為應(yīng)用集群調(diào)用get()方法訪問(wèn)緩存次數(shù)
  • 上圖綠線為獲取緩存操作命中 TMC 本地緩存的次數(shù)

圖片

  • 上圖為本地緩存命中率曲線圖

可以看出活動(dòng)期間緩存請(qǐng)求量及本地緩存命中量均有明顯增長(zhǎng),本地緩存命中率達(dá)到近 80% (即應(yīng)用集群中 80% 的緩存查詢請(qǐng)求被 TMC 本地緩存攔截)。

5-1-2. 熱點(diǎn)緩存對(duì)應(yīng)用訪問(wèn)的加速效果

圖片

  • 上圖為應(yīng)用接口QPS曲線

圖片

  • 上圖為應(yīng)用接口RT曲線

可以看出活動(dòng)期間應(yīng)用接口的請(qǐng)求量有明顯增長(zhǎng),由于 TMC 本地緩存的效果應(yīng)用接口的 RT 反而出現(xiàn)下降。

5-2. 雙十一期間部分應(yīng)用 TMC 效果展示

5-2-1. 商品域核心應(yīng)用效果

圖片

5-2-2. 活動(dòng)域核心應(yīng)用效果

圖片

圖片

六、TMC功能展望

在有贊, TMC 目前已為商品中心、物流中心、庫(kù)存中心、營(yíng)銷活動(dòng)、用戶中心、網(wǎng)關(guān)&消息等多個(gè)核心應(yīng)用模塊提供服務(wù),后續(xù)應(yīng)用也在陸續(xù)接入中。

TMC 在提供“熱點(diǎn)探測(cè)” + “本地緩存”的核心能力同時(shí),也為應(yīng)用服務(wù)提供了靈活的配置選擇,應(yīng)用服務(wù)可以結(jié)合實(shí)際業(yè)務(wù)情況在“熱點(diǎn)閾值”、“熱點(diǎn)key探測(cè)數(shù)量”、“熱點(diǎn)黑白名單”維度進(jìn)行自由配置以達(dá)到更好的使用效果。

配合三級(jí)緩存的使用,需要進(jìn)行 熱key的 探測(cè),有贊平臺(tái)通過(guò) 熱key的探測(cè)和 支持,

其中:活動(dòng)期間,本地緩存命中率達(dá)到近 80%的命中率, 并且, 響應(yīng)時(shí)間,和平峰時(shí)段,沒(méi)有變化。

HotKey探測(cè)方案3: 結(jié)合開(kāi)源hotkey,做熱點(diǎn)探測(cè)

基于開(kāi)源hotkey進(jìn)行 熱點(diǎn)探測(cè),有很多小伙伴,在生產(chǎn)系統(tǒng)進(jìn)行了 緩存系統(tǒng)的重構(gòu)

下面將重構(gòu)前與重構(gòu)后做下對(duì)照,來(lái)說(shuō)明這套機(jī)制的優(yōu)缺點(diǎn)。

特性

重構(gòu)系統(tǒng)前

使用京東hotkey重構(gòu)系統(tǒng)后

機(jī)器資源

高配物理機(jī)/虛擬機(jī)

普通物理機(jī)/虛擬機(jī)/容器

管控復(fù)雜

無(wú)法控制熱點(diǎn),不易監(jiān)控

熱點(diǎn)數(shù)據(jù)可以監(jiān)控統(tǒng)計(jì),可以手動(dòng)刷新

資源利用率

資源利用率低,無(wú)論是否是熱點(diǎn)數(shù)據(jù)都占用資源

資源利用率高,大部分熱點(diǎn)數(shù)據(jù)持有資源

突發(fā)流量

無(wú)法彈性應(yīng)對(duì)突發(fā)流量

彈性應(yīng)對(duì)突發(fā)流量

預(yù)發(fā)流量

預(yù)設(shè)所有數(shù)據(jù)

只提前預(yù)設(shè)熱點(diǎn)數(shù)據(jù)

數(shù)據(jù)一致性

集群內(nèi)數(shù)據(jù)不一致情況時(shí)常發(fā)生,出現(xiàn)“橫跳”現(xiàn)象

集群內(nèi)數(shù)據(jù)一致性高,極少或不發(fā)生不一致性情況

假設(shè)10W人同時(shí)訪問(wèn),如何保證不 雪崩?

  • 擴(kuò)容
  • 限流
  • 三級(jí)緩存

三級(jí)緩存  強(qiáng)烈推薦進(jìn)行 熱點(diǎn)探測(cè) 相結(jié)合, 主要的優(yōu)勢(shì)是:

  • 通過(guò)熱點(diǎn)探測(cè),既能提升 本地緩存命中率,
  • 除此之外,還能識(shí)別 刷子用戶, 把刷子用戶加入  黑名單, 并且利用 bloom 過(guò)濾器進(jìn)行緩存。 從而提升系統(tǒng)的安全性。
責(zé)任編輯:武曉燕 來(lái)源: 碼猿技術(shù)專欄
相關(guān)推薦

2023-11-27 13:18:00

Redis數(shù)據(jù)不丟失

2023-06-01 08:54:08

RabbitMQ確認(rèn)機(jī)制生產(chǎn)端

2017-03-13 09:12:00

TCP數(shù)據(jù)結(jié)構(gòu)請(qǐng)求包

2024-08-06 08:13:26

2024-01-16 08:24:59

消息隊(duì)列KafkaRocketMQ

2021-01-13 14:42:36

GitHub代碼Java

2019-11-12 14:15:07

Redis內(nèi)存持久化

2021-09-08 07:58:58

字節(jié)系統(tǒng)雙寫(xiě)

2022-11-10 16:39:59

架構(gòu)系統(tǒng)技術(shù)架構(gòu)

2020-03-09 08:00:43

娛樂(lè)圈肖戰(zhàn)評(píng)論

2025-04-22 08:55:31

2020-05-13 09:42:49

大數(shù)據(jù)平臺(tái)方法論

2022-07-05 09:56:42

搜索搜索引擎

2021-06-30 17:38:03

Trie 樹(shù)字符Java

2025-03-28 10:47:05

開(kāi)發(fā)注解Java

2024-08-30 08:59:15

2021-03-01 11:53:15

面試偽共享CPU

2025-04-08 09:20:00

Sentinel限流微服務(wù)

2024-11-01 08:31:56

2025-04-02 12:20:00

開(kāi)發(fā)代碼函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)