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

一、引子

1-1. TMC 是什么

TMC 抖仅,即“透明多級緩存( Transparent Multilevel Cache )”损离,是有贊 PaaS 團(tuán)隊給公司內(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é)了下列 多級緩存解決方案 需要解決的需求痛點:

  • 熱點探測:如何快速且準(zhǔn)確的發(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ù)透明御滩;

本篇聚焦在應(yīng)用層客戶端的“熱點探測”、“本地緩存”功能党远。

三削解、 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包的JedisPoolJedis類做了改造,在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ù),進(jìn)行熱點探測豺谈,將熱點 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ù)進(jìn)行“熱點探測”术幔;

2)key值過期

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

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

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

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 訪問事件”進(jìn)行異步化上報芒珠,不會阻塞業(yè)務(wù)桥狡;
  • 通信模塊線程隔離:Hermes-SDK通信模塊 使用獨立線程池+有界隊列,保證事件上報&監(jiān)聽的I/O操作與業(yè)務(wù)執(zhí)行線程隔離皱卓,即使出現(xiàn)非預(yù)期性異常也不會影響基本業(yè)務(wù)功能裹芝;
  • 緩存管控:Hermes-SDK熱點模塊 對本地緩存大小上限進(jìn)行了管控,使其占用內(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 乎串,維護(hù)一個時間輪,記錄基于當(dāng)前時刻滑窗的訪問熱度买置;
  • 熱度匯聚:對 App 的所有 Key 寄悯,以<key,熱度>的形式進(jìn)行 熱度排序匯總
  • 熱點探測:對 App 堕义,從 熱Key排序匯總 結(jié)果中選出 TopN的熱點Key 猜旬,推送給 Hermes-SDK脆栋;

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

Hermes-SDK 通過本地rsyslogkey訪問事件 以協(xié)議格式放入 kafkaHermes服務(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 掸茅,維護(hù)了一個 時間輪

  • 時間輪中共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 進(jìn)行“熱度匯聚”工作:

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

4-5. 熱點探測

  • 在前幾步贡珊,每3秒 一次的 映射任務(wù) 執(zhí)行,對每個 App 都會產(chǎn)生一份當(dāng)前時刻的 熱度匯聚結(jié)果 涉馁;
  • Hermes服務(wù)端集群 中的“熱點探測”節(jié)點门岔,對每個 App ,只需周期性從其最近一份 熱度匯聚結(jié)果 中取出達(dá)到熱度閾值的 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. 準(zhǔn)確性

key 的熱度匯聚結(jié)果由“基于時間輪實現(xiàn)的滑動窗口”匯聚得到,相對準(zhǔ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)用的緩存請求&命中率曲線圖

  • 上圖藍(lán)線為應(yīng)用集群調(diào)用get()方法訪問緩存次數(shù)

  • 上圖綠線為獲取緩存操作命中 TMC 本地緩存的次數(shù)


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

可以看出活動期間緩存請求量及本地緩存命中量均有明顯增長假栓,本地緩存命中率達(dá)到近 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ù)量”骄噪、“熱點黑白名單”維度進(jìn)行自由配置以達(dá)到更好的使用效果尚困。

最后, TMC 的迭代還在持續(xù)進(jìn)行中...


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末链蕊,一起剝皮案震驚了整個濱河市事甜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌滔韵,老刑警劉巖逻谦,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異陪蜻,居然都是意外死亡邦马,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門宴卖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來滋将,“玉大人,你說我怎么就攤上這事症昏∷婷觯” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵肝谭,是天一觀的道長掘宪。 經(jīng)常有香客問我蛾扇,道長,這世上最難降的妖魔是什么添诉? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任屁桑,我火速辦了婚禮,結(jié)果婚禮上栏赴,老公的妹妹穿的比我還像新娘蘑斧。我一直安慰自己,他們只是感情好须眷,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布竖瘾。 她就那樣靜靜地躺著,像睡著了一般花颗。 火紅的嫁衣襯著肌膚如雪捕传。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天扩劝,我揣著相機與錄音庸论,去河邊找鬼。 笑死棒呛,一個胖子當(dāng)著我的面吹牛聂示,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播簇秒,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼鱼喉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了趋观?” 一聲冷哼從身側(cè)響起扛禽,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎皱坛,沒想到半個月后编曼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡剩辟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年掐场,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抹沪。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡刻肄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出融欧,到底是詐尸還是另有隱情敏弃,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布噪馏,位于F島的核電站麦到,受9級特大地震影響绿饵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瓶颠,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一拟赊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粹淋,春花似錦吸祟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至借杰,卻和暖如春过吻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蔗衡。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工纤虽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绞惦。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓逼纸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親翩隧。 傳聞我的和親對象是個殘疾皇子樊展,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • NOSQL類型簡介鍵值對:會使用到一個哈希表呻纹,表中有一個特定的鍵和一個指針指向特定的數(shù)據(jù)堆生,如redis,volde...
    MicoCube閱讀 3,961評論 2 27
  • 緩存是最直接有效提升系統(tǒng)性能的手段之一雷酪。個人認(rèn)為用好用對緩存是優(yōu)秀程序員的必備基本素質(zhì)淑仆。 本文結(jié)合實際開發(fā)經(jīng)驗,從...
    Java小生閱讀 801評論 1 3
  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,905評論 2 89
  • 讓你跟著我哥力,只是受苦蔗怠,對不起。 愛上我就像愛上了一個白手起家而又不知到什么時候能成功的人吩跋。 被人愛著是幸福的寞射,所以...
    Cazaea閱讀 1,057評論 1 2
  • 我們每一個人都在尋找自己的幸福桥温,其實幸福并不難得到,如果我們經(jīng)常懷著無私梁丘、良好的意愿侵浸,那么幸福就近在咫尺旺韭。 ...
    江小然閱讀 827評論 1 5