自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

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

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

這個題目的回答,大有玄機。回答得有水平,能夠直接拿到offer??上?,很多小伙伴可能一句話都說不上來。

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

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

疑問歸疑問。

這個問題,如果遇到了,只能會硬著頭皮作答。

如果直接用這個疑問去反問面試官,那么 ,面試官一定會說:這小子 沒有遇到過事情,沒有見過市面。

為啥呢?

因為哪怕用戶不到1萬,其實,咱們的系統(tǒng),還是可能會有10W人同時訪問滴。這10W人從哪里來的呢? 這些人包括:

  • 爬蟲
  • 刷子(羊毛黨)

爬蟲對訪問量的貢獻

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

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

某個頁面12000次點擊里邊,98%的點擊率,是爬蟲貢獻的。

爬蟲和用戶的比例是 19比1.

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

那么 1W用戶, 有沒有  10W的 同時訪問的可能呢?

因為 大量爬蟲的存著, 當(dāng)然有的。

刷子用戶(羊毛黨)對訪問量的貢獻

“羊毛黨”戰(zhàn)術(shù)之一:開啟機器人批量注冊新賬號,招募“新兵”。

“這是個‘昏招’,批量注冊的賬號很容易識別。

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

但通過注冊時間、注冊地與下單地比對等方式,很快識別出來。

某年的“618”電商節(jié)活動期間,某電商公司,平均每天攔截“羊毛黨”賬號2000萬個。

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

其中,可能會包含部分 提前囤積賬號

另外,在 活動執(zhí)行的過程中, 還是有 可能 批量注冊大量的新賬號

那么 1W用戶, 有沒有  10W的 同時訪問的可能呢?

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

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

所以,只要是有利可圖,如 秒殺等, 那么 1W用戶, 有沒有  10W的 同時訪問的可能呢?

當(dāng)然有的。

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

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

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

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

是 一個1億的用戶量。

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

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

是 10。

沒錯,如果 總體的用戶量 不到1萬,按照 正常估算, 吞吐量就只有 10。

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

圖片

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

可以說,用牛刀 在 殺雞。

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

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

圖片

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

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

方式之一:擴容

方式之二:限流

首先能用到的策略:擴容

大家首先會想到的策略,就是擴容。

圖片

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

那么就是自動擴容。

其次能用到的策略:限流

  • nginx 限流
  • SpringCloud gateway 限流

接入層限流可以進行 nginx 限流

圖片

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

還 可以使用 redis lua進行分布式限流, 或者使用 sentinel 進行 限流,

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

誰怪 有那么多刷子流量,或者 爬蟲流量呢。

但是,限流是無奈之舉。

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

分布式Redis集群如何抵抗?

這個 10Wqps 必須進入到服務(wù)層。

怎么辦?

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

所以,后面的 流量就進入  redis集群。

圖片

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

圖片

一般來說,主節(jié)點提供服務(wù), 從節(jié)點是做冗余的, 并不提供數(shù)據(jù)的寫入服務(wù)。

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

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

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

如果 10Wqps 訪問的是同一個key, 那就問題更大了。

因為 單個redis 的吞吐量,一般就是 2W左右。怎么可能扛住  5倍的吞吐量。

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

于是乎,改怎么辦?

大概也有兩種方案:

方法一:redis 擴容

方法二:本地緩存

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

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

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

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

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

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

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

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

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

圖片

先發(fā)問一級緩存caffeine ,如果 沒有找到,再訪問 二級緩存 redis 集群

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

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

圖片

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

1. 快但是量少:訪問速度快,但無法進行大數(shù)據(jù)存儲

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

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

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

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

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

復(fù)雜度較高并且容易出錯,如基于 rocketmq 的發(fā)布訂閱機制來同步更新各個部署節(jié)點。

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

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

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

4.需要盡量緩存熱點key,而提升緩存的命中率

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

如果還沒有來得及訪問,本地緩存中的數(shù)據(jù),就被淘汰了,那就失去了本地緩存的價值, 當(dāng)然,本地緩存的命中率也會很低。

如何提升緩存的命中率?

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

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

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

有測試表明:caffeine 比 guava 的命中率,不同場景,都會高出10%以上。

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

簡單的說,把熱點數(shù)據(jù), 加載到本地緩存。

什么是HotKey?

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

從訪問量上來說,常見的HotKey如:

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

從業(yè)務(wù)上來說, 常見的HotKey如:

1 、MySQL等數(shù)據(jù)庫會被頻繁訪問的熱數(shù)據(jù)

如爆款商品的skuId。

2 、redis的被密集訪問的key

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

3 、機器人、爬蟲、刷子用戶

如用戶的userId、uuid、ip等。

4 、某個接口地址

如/sku/query或者更精細維度的。

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

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

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

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

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

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

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

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

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

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

總結(jié)一下,HotKey帶來的常見問題

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

HotKey問題的根本:

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

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

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

但問題是事先不知道HotKey在哪里?

那么,問題就來了,如何進行 HotKey的探測?

HotKey探測關(guān)鍵指標

1、實時性

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

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

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

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

2、準確性

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

3、集群一致性

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

4、高性能

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

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

如何實現(xiàn)HotKey探測?

HotKey探測方案1: 流計算集群

通過  流式計算集群 storm/ flink 集群,進行 topkey

圖片

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

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

其中的 top N 的key,就是熱點 key

HotKey探測方案2: 流計算集群

有贊透明多級緩存解決方案

HotKey探測方案3: 結(jié)合開源hotkey,做熱點探測

比如:結(jié)合京東開源hotkey,做熱點探測

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

一、TMC簡介

1-1. TMC 是什么

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

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

  • 應(yīng)用層熱點探測
  • 應(yīng)用層本地緩存
  • 應(yīng)用層緩存命中統(tǒng)計

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

1-2. 為什么要做 TMC

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

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

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

1-3. 多級緩存解決方案的痛點

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

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

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

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

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

圖片

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

  • 存儲層:提供基礎(chǔ)的kv數(shù)據(jù)存儲能力,針對不同的業(yè)務(wù)場景選用不同的存儲服務(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)置“熱點探測”、“本地緩存”等功能,對業(yè)務(wù)透明;

三、 TMC 本地緩存

3-1. 如何透明

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

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

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

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

圖片

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

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

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

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

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

圖片

3-2-1. 模塊劃分

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

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

3-2-2. 基本流程

1) key 值獲取

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

2)key值過期

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

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

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

4)配置讀取

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

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

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

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

3-2-4. 一致性

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

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

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

4-1. 整體流程

圖片

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

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

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

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

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

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

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

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

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

4-3. 熱度滑窗

圖片

4-3-1. 時間滑窗

Hermes服務(wù)端集群 節(jié)點,對每個App的每個 key ,維護了一個 時間輪:

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

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

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

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

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

4-4. 熱度匯聚

圖片

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

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

4-5. 熱點探測

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

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

圖片

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

4-6-1. 實時性

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

4-6-2. 準確性

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

4-6-3.擴展性

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

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

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

5-1. 快手商家某次商品營銷活動

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

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

圖片

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

圖片

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

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

5-1-2. 熱點緩存對應(yīng)用訪問的加速效果

圖片

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

圖片

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

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

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

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

圖片

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

圖片

圖片

六、TMC功能展望

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

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

配合三級緩存的使用,需要進行 熱key的 探測,有贊平臺通過 熱key的探測和 支持,

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

HotKey探測方案3: 結(jié)合開源hotkey,做熱點探測

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

下面將重構(gòu)前與重構(gòu)后做下對照,來說明這套機制的優(yōu)缺點。

特性

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

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

機器資源

高配物理機/虛擬機

普通物理機/虛擬機/容器

管控復(fù)雜

無法控制熱點,不易監(jiān)控

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

資源利用率

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

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

突發(fā)流量

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

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

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

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

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

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

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

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

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

  • 擴容
  • 限流
  • 三級緩存

三級緩存  強烈推薦進行 熱點探測 相結(jié)合, 主要的優(yōu)勢是:

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

2023-11-27 13:18:00

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

2023-06-01 08:54:08

RabbitMQ確認機制生產(chǎn)端

2017-03-13 09:12:00

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

2024-08-06 08:13:26

2024-01-16 08:24:59

消息隊列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)雙寫

2022-11-10 16:39:59

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

2020-03-09 08:00:43

娛樂圈肖戰(zhàn)評論

2025-04-22 08:55:31

2022-07-05 09:56:42

搜索搜索引擎

2020-05-13 09:42:49

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

2021-06-30 17:38:03

Trie 樹字符Java

2025-03-28 10:47:05

開發(fā)注解Java

2021-03-01 11:53:15

面試偽共享CPU

2024-08-30 08:59:15

2025-04-08 09:20:00

Sentinel限流微服務(wù)

2025-04-02 12:20:00

開發(fā)代碼函數(shù)

2024-11-01 08:31:56

點贊
收藏

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