有赞多级缓存解决方案怎么做的,你知道吗?
一、引子
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)用層解決緩存使用過程中出現(xiàn)的熱點(diǎn)訪問問題。
1-2. 為什么要做 TMC
使用有贊服務(wù)的電商商家數(shù)量和類型很多,商家會(huì)不定期做一些“商品秒殺”、“商品推廣”活動(dòng),導(dǎo)致“營銷活動(dòng)”、“商品詳情”、“交易下單”等鏈路應(yīng)用出現(xiàn) 緩存熱點(diǎn)訪問 的情況:
-
活動(dòng)時(shí)間、活動(dòng)類型、活動(dòng)商品之類的信息不可預(yù)期,導(dǎo)致?緩存熱點(diǎn)訪問?情況不可提前預(yù)知;
-
緩存熱點(diǎn)訪問?出現(xiàn)期間,應(yīng)用層少數(shù)?熱點(diǎn)訪問 key?產(chǎn)生大量緩存訪問請(qǐng)求:沖擊分布式緩存系統(tǒng),大量占據(jù)內(nèi)網(wǎng)帶寬,最終影響應(yīng)用層系統(tǒng)穩(wěn)定性;
為了應(yīng)對(duì)以上問題,需要一個(gè)能夠 自動(dòng)發(fā)現(xiàn)熱點(diǎn) 并 將熱點(diǎ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)訪問 key??
-
數(shù)據(jù)一致性:前置在應(yīng)用層的本地緩存,如何保障與分布式緩存系統(tǒng)的數(shù)據(jù)一致性?
-
效果驗(yàn)證:如何讓應(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)訪問時(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ù)透明;
本篇聚焦在應(yīng)用層客戶端的“熱點(diǎn)探測(cè)”、“本地緩存”功能。
?
三、TMC 本地緩存
3-1. 如何透明
TMC 是如何減少對(duì)業(yè)務(wù)應(yīng)用系統(tǒng)的入侵,做到透明接入的? 對(duì)于公司 Java 應(yīng)用服務(wù),在緩存客戶端使用方式上分為兩類:
-
基于?spring.data.redis包,使用?RedisTemplate編寫業(yè)務(wù)代碼;
-
基于?youzan.framework.redis包,使用?RedisClient編寫業(yè)務(wù)代碼;
不論使用以上那種方式,最終通過 JedisPool創(chuàng)建的 Jedis對(duì)象與緩存服務(wù)端代理層做請(qǐng)求交互。
TMC 對(duì)原生 jedis 包的 JedisPool和 Jedis類做了改造,在 JedisPool 初始化過程中集成 TMC“熱點(diǎn)發(fā)現(xiàn)”+“本地緩存”功能 Hermes-SDK包的初始化邏輯,使 Jedis客戶端與緩存服務(wù)端代理層交互時(shí)先與 Hermes-SDK交互,從而完成 “熱點(diǎn)探測(cè)”+“本地緩存”功能的透明接入。
對(duì)于 Java 應(yīng)用服務(wù),只需使用特定版本的 jedis-jar 包,無需修改代碼,即可接入 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 無異;
-
Hermes-SDK:自研“熱點(diǎn)發(fā)現(xiàn)+本地緩存”功能的 SDK 封裝,Jedis-Client 通過與它交互來集成相應(yīng)能力;
-
Hermes 服務(wù)端集群:接收 Hermes-SDK 上報(bào)的緩存訪問數(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ì)詢問?Hermes-SDK?該 key 當(dāng)前是否是?熱點(diǎn)key;
-
對(duì)于?熱點(diǎn)key?,直接從?Hermes-SDK?的?熱點(diǎn)模塊?獲取熱點(diǎn) key 在本地緩存的 value 值,不去訪問?緩存集群?,從而將訪問請(qǐng)求前置在應(yīng)用層;
-
對(duì)于非?熱點(diǎn)key?,Hermes-SDK?會(huì)通過?Callable回調(diào)?Jedis-Client?的原生接口,從?緩存集群?拿到 value 值;
-
對(duì)于?Jedis-Client?的每次 key 值訪問請(qǐng)求,Hermes-SDK?都會(huì)通過其?通信模塊?將?key 訪問事件?異步上報(bào)給?Hermes 服務(wù)端集群?,以便其根據(jù)上報(bào)數(shù)據(jù)進(jìn)行“熱點(diǎn)探測(cè)”;
2)key 值過期
-
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 值失效”事件通過?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 訪問事件,對(duì)不同業(yè)務(wù)應(yīng)用集群的緩存訪問數(shù)據(jù)進(jìn)行周期性(3s 一次)分析計(jì)算,以探測(cè)業(yè)務(wù)應(yīng)用集群中的熱點(diǎn) key列表;
-
對(duì)于探測(cè)到的熱點(diǎn) key列表,Hermes 服務(wù)端集群?將其通過?etcd 集群?推送給不同業(yè)務(wù)應(yīng)用集群的?Hermes-SDK?通信模塊,通知其對(duì)熱點(diǎn) key列表進(jìn)行本地緩存;
4)配置讀取
-
Hermes-SDK?在啟動(dòng)及運(yùn)行過程中,會(huì)從?Apollo 配置中心?讀取其關(guān)心的配置信息(如:啟動(dòng)關(guān)閉配置、黑白名單配置、etcd 地址...);
-
Hermes 服務(wù)端集群?在啟動(dòng)及運(yùn)行過程中,會(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 訪問事件”進(jìn)行異步化上報(bào),不會(huì)阻塞業(yè)務(wù);
-
通信模塊線程隔離:Hermes-SDK?的?通信模塊?使用獨(dú)立線程池+有界隊(duì)列,保證事件上報(bào)&監(jiān)聽的 I/O 操作與業(yè)務(wù)執(zhí)行線程隔離,即使出現(xiàn)非預(yù)期性異常也不會(huì)影響基本業(yè)務(wù)功能;
-
緩存管控:Hermes-SDK?的?熱點(diǎn)模塊?對(duì)本地緩存大小上限進(jìn)行了管控,使其占用內(nèi)存不超過 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?通過?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 訪問事件;
-
熱度滑窗:對(duì) App 的每個(gè) Key,維護(hù)一個(gè)時(shí)間輪,記錄基于當(dāng)前時(shí)刻滑窗的訪問熱度;
-
熱度匯聚:對(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 通過本地 rsyslog將 key 訪問事件 以協(xié)議格式放入 kafka ,Hermes 服務(wù)端集群 的每個(gè)節(jié)點(diǎn)消費(fèi) kafka 消息,實(shí)時(shí)獲取 key 訪問事件。
訪問事件協(xié)議格式如下:
-
appName:集群節(jié)點(diǎn)所屬業(yè)務(wù)應(yīng)用
-
uniqueKey:業(yè)務(wù)應(yīng)用?key 訪問事件?的 key
-
sendTime:業(yè)務(wù)應(yīng)用?key 訪問事件?的發(fā)生時(shí)間
-
weight:業(yè)務(wù)應(yīng)用?key 訪問事件?的訪問權(quán)值
Hermes 服務(wù)端集群 節(jié)點(diǎn)將收集到的 key 訪問事件 存儲(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í)間周期的總訪問次數(shù);
-
時(shí)間輪 10 個(gè)時(shí)間片的記錄累加即表示當(dāng)前 key 從當(dāng)前時(shí)間向前 30 秒時(shí)間窗口內(nèi)的總訪問次數(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ù) 3 秒一個(gè)周期完成“熱度滑窗” + “熱度匯聚”工作,當(dāng)有 熱點(diǎn)訪問場(chǎng)景 出現(xiàn)時(shí)最長 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ā)生訪問分布。
4-6-3. 擴(kuò)展性
Hermes 服務(wù)端集群節(jié)點(diǎn)無狀態(tài),節(jié)點(diǎn)數(shù)可基于 kafka 的 partition 數(shù)量橫向擴(kuò)展。
“熱度滑窗” + “熱度匯聚” 過程基于 App 數(shù)量,在單節(jié)點(diǎn)內(nèi)多線程擴(kuò)展。
?
五、TMC 實(shí)戰(zhàn)效果
5-1. 快手商家某次商品營銷活動(dòng)
有贊商家通過快手直播平臺(tái)為某商品搞活動(dòng),造成該商品短時(shí)間內(nèi)被集中訪問產(chǎn)生訪問熱點(diǎn),活動(dòng)期間 TMC 記錄的實(shí)際熱點(diǎn)訪問效果數(shù)據(jù)如下:
5-1-1. 某核心應(yīng)用的緩存請(qǐng)求&命中率曲線圖
-
上圖藍(lán)線為應(yīng)用集群調(diào)用get()方法訪問緩存次數(shù)
-
上圖綠線為獲取緩存操作命中TMC本地緩存的次數(shù)
-
上圖為本地緩存命中率曲線圖
可以看出活動(dòng)期間緩存請(qǐng)求量及本地緩存命中量均有明顯增長,本地緩存命中率達(dá)到近 80%(即應(yīng)用集群中 80% 的緩存查詢請(qǐng)求被 TMC 本地緩存攔截)。
5-1-2. 熱點(diǎn)緩存對(duì)應(yīng)用訪問的加速效果
-
上圖為應(yīng)用接口 QPS 曲線
-
上圖為應(yīng)用接口 RT 曲線
可以看出活動(dòng)期間應(yīng)用接口的請(qǐ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 目前已為商品中心、物流中心、庫存中心、營銷活動(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á)到更好的使用效果。
總結(jié)
以上是生活随笔為你收集整理的有赞多级缓存解决方案怎么做的,你知道吗?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Cloud生态的配置服务器
- 下一篇: Spring Cloud Alibaba