有赞多级缓存解决方案怎么做的,你知道吗?
一、引子
1-1. TMC 是什么
TMC,即“透明多級緩存(Transparent Multilevel Cache)”,是有贊 PaaS 團隊給公司內應用提供的整體緩存解決方案。
TMC 在通用“分布式緩存解決方案(如 CodisProxy + Redis,如有贊自研分布式緩存系統 zanKV)”基礎上,增加了以下功能:
-
應用層熱點探測
-
應用層本地緩存
-
應用層緩存命中統計
以幫助應用層解決緩存使用過程中出現的熱點訪問問題。
1-2. 為什么要做 TMC
使用有贊服務的電商商家數量和類型很多,商家會不定期做一些“商品秒殺”、“商品推廣”活動,導致“營銷活動”、“商品詳情”、“交易下單”等鏈路應用出現 緩存熱點訪問 的情況:
-
活動時間、活動類型、活動商品之類的信息不可預期,導致?緩存熱點訪問?情況不可提前預知;
-
緩存熱點訪問?出現期間,應用層少數?熱點訪問 key?產生大量緩存訪問請求:沖擊分布式緩存系統,大量占據內網帶寬,最終影響應用層系統穩定性;
為了應對以上問題,需要一個能夠 自動發現熱點 并 將熱點緩存訪問請求前置在應用層本地緩存 的解決方案,這就是 TMC 產生的原因。
1-3. 多級緩存解決方案的痛點
基于上述描述,我們總結了下列 多級緩存解決方案 需要解決的需求痛點:
-
熱點探測:如何快速且準確的發現?熱點訪問 key??
-
數據一致性:前置在應用層的本地緩存,如何保障與分布式緩存系統的數據一致性?
-
效果驗證:如何讓應用層查看本地緩存命中率、熱點 key 等數據,驗證多級緩存效果?
-
透明接入:整體解決方案如何減少對應用系統的入侵,做到快速平滑接入?
TMC 聚焦上述痛點,設計并實現了整體解決方案。以支持“熱點探測”和“本地緩存”,減少熱點訪問時對下游分布式緩存服務的沖擊,避免影響應用服務的性能及穩定性。
?
二、TMC 整體架構
TMC 整體架構如上圖,共分為三層:
-
存儲層:提供基礎的 kv 數據存儲能力,針對不同的業務場景選用不同的存儲服務(codis/zankv/aerospike);
-
代理層:為應用層提供統一的緩存使用入口及通信協議,承擔分布式數據水平切分后的路由功能轉發工作;
-
應用層:提供統一客戶端給應用服務使用,內置“熱點探測”、“本地緩存”等功能,對業務透明;
本篇聚焦在應用層客戶端的“熱點探測”、“本地緩存”功能。
?
三、TMC 本地緩存
3-1. 如何透明
TMC 是如何減少對業務應用系統的入侵,做到透明接入的? 對于公司 Java 應用服務,在緩存客戶端使用方式上分為兩類:
-
基于?spring.data.redis包,使用?RedisTemplate編寫業務代碼;
-
基于?youzan.framework.redis包,使用?RedisClient編寫業務代碼;
不論使用以上那種方式,最終通過 JedisPool創建的 Jedis對象與緩存服務端代理層做請求交互。
TMC 對原生 jedis 包的 JedisPool和 Jedis類做了改造,在 JedisPool 初始化過程中集成 TMC“熱點發現”+“本地緩存”功能 Hermes-SDK包的初始化邏輯,使 Jedis客戶端與緩存服務端代理層交互時先與 Hermes-SDK交互,從而完成 “熱點探測”+“本地緩存”功能的透明接入。
對于 Java 應用服務,只需使用特定版本的 jedis-jar 包,無需修改代碼,即可接入 TMC 使用“熱點發現”+“本地緩存”功能,做到了對應用系統的最小入侵。
3-2. 整體結構
3-2-1. 模塊劃分
TMC 本地緩存整體結構分為如下模塊:
-
Jedis-Client:Java 應用與緩存服務端交互的直接入口,接口定義與原生 Jedis-Client 無異;
-
Hermes-SDK:自研“熱點發現+本地緩存”功能的 SDK 封裝,Jedis-Client 通過與它交互來集成相應能力;
-
Hermes 服務端集群:接收 Hermes-SDK 上報的緩存訪問數據,進行熱點探測,將熱點 key 推送給 Hermes-SDK 做本地緩存;
-
緩存集群:由代理層和存儲層組成,為應用客戶端提供統一的分布式緩存服務入口;
-
基礎組件:etcd 集群、Apollo 配置中心,為 TMC 提供“集群推送”和“統一配置”能力;
3-2-2. 基本流程
1)key 值獲取
-
Java 應用調用?Jedis-Client?接口獲取 key 的緩存值時,Jedis-Client?會詢問?Hermes-SDK?該 key 當前是否是?熱點key;
-
對于?熱點key?,直接從?Hermes-SDK?的?熱點模塊?獲取熱點 key 在本地緩存的 value 值,不去訪問?緩存集群?,從而將訪問請求前置在應用層;
-
對于非?熱點key?,Hermes-SDK?會通過?Callable回調?Jedis-Client?的原生接口,從?緩存集群?拿到 value 值;
-
對于?Jedis-Client?的每次 key 值訪問請求,Hermes-SDK?都會通過其?通信模塊?將?key 訪問事件?異步上報給?Hermes 服務端集群?,以便其根據上報數據進行“熱點探測”;
2)key 值過期
-
Java 應用調用?Jedis-Client?的?set()?del()?expire()接口時會導致對應 key 值失效,Jedis-Client?會同步調用?Hermes-SDK?的?invalid()方法告知其“key 值失效”事件;
-
對于?熱點 key?,Hermes-SDK?的?熱點模塊?會先將 key 在本地緩存的 value 值失效,以達到本地數據強一致。同時?通信模塊?會異步將“key 值失效”事件通過?etcd 集群?推送給 Java 應用集群中其他?Hermes-SDK?節點;
-
其他?Hermes-SDK?節點的?通信模塊?收到 “key 值失效”事件后,會調用?熱點模塊?將 key 在本地緩存的 value 值失效,以達到集群數據最終一致;
3)熱點發現
-
Hermes 服務端集群?不斷收集?Hermes-SDK上報的?key 訪問事件,對不同業務應用集群的緩存訪問數據進行周期性(3s 一次)分析計算,以探測業務應用集群中的熱點 key列表;
-
對于探測到的熱點 key列表,Hermes 服務端集群?將其通過?etcd 集群?推送給不同業務應用集群的?Hermes-SDK?通信模塊,通知其對熱點 key列表進行本地緩存;
4)配置讀取
-
Hermes-SDK?在啟動及運行過程中,會從?Apollo 配置中心?讀取其關心的配置信息(如:啟動關閉配置、黑白名單配置、etcd 地址...);
-
Hermes 服務端集群?在啟動及運行過程中,會從?Apollo 配置中心?讀取其關心的配置信息(如:業務應用列表、熱點閾值配置、etcd 地址...);
3-2-3. 穩定性
TMC 本地緩存穩定性表現在以下方面:
-
數據上報異步化:Hermes-SDK?使用?rsyslog技術對“key 訪問事件”進行異步化上報,不會阻塞業務;
-
通信模塊線程隔離:Hermes-SDK?的?通信模塊?使用獨立線程池+有界隊列,保證事件上報&監聽的 I/O 操作與業務執行線程隔離,即使出現非預期性異常也不會影響基本業務功能;
-
緩存管控:Hermes-SDK?的?熱點模塊?對本地緩存大小上限進行了管控,使其占用內存不超過 64MB(LRU),杜絕 JVM 堆內存溢出的可能;
3-2-4. 一致性
TMC 本地緩存一致性表現在以下方面:
-
Hermes-SDK?的?熱點模塊?僅緩存?熱點 key?數據,絕大多數非熱點 key數據由?緩存集群?存儲;
-
熱點 key?變更導致 value 失效時,Hermes-SDK?同步失效本地緩存,保證?本地強一致;
-
熱點 key?變更導致 value 失效時,Hermes-SDK?通過?etcd 集群?廣播事件,異步失效業務應用集群中其他節點的本地緩存,保證?集群最終一致;
-
?
四、TMC 熱點發現
4-1. 整體流程
TMC 熱點發現流程分為四步:
-
數據收集:收集?Hermes-SDK?上報的?key 訪問事件;
-
熱度滑窗:對 App 的每個 Key,維護一個時間輪,記錄基于當前時刻滑窗的訪問熱度;
-
熱度匯聚:對 App 的所有 Key,以?<key,熱度>的形式進行?熱度排序匯總;
-
熱點探測:對 App,從?熱 Key 排序匯總?結果中選出?TopN 的熱點 Key?,推送給?Hermes-SDK;
4-2. 數據收集
Hermes-SDK 通過本地 rsyslog將 key 訪問事件 以協議格式放入 kafka ,Hermes 服務端集群 的每個節點消費 kafka 消息,實時獲取 key 訪問事件。
訪問事件協議格式如下:
-
appName:集群節點所屬業務應用
-
uniqueKey:業務應用?key 訪問事件?的 key
-
sendTime:業務應用?key 訪問事件?的發生時間
-
weight:業務應用?key 訪問事件?的訪問權值
Hermes 服務端集群 節點將收集到的 key 訪問事件 存儲在本地內存中,內存數據結構為 Map<String,Map<String,LongAdder>>,對應業務含義映射為 Map<appName,Map<uniqueKey,熱度>>。
4-3. 熱度滑窗
4-3-1. 時間滑窗
Hermes 服務端集群 節點,對每個 App 的每個 key,維護了一個 時間輪:
-
時間輪中共 10 個?時間片,每個時間片記錄當前 key 對應 3 秒時間周期的總訪問次數;
-
時間輪 10 個時間片的記錄累加即表示當前 key 從當前時間向前 30 秒時間窗口內的總訪問次數;
4-3-2. 映射任務
Hermes 服務端集群 節點,對每個 App 每 3 秒 生成一個 映射任務 ,交由節點內 “緩存映射線程池” 執行。映射任務 內容如下:
-
對當前 App,從?Map<appName,Map<uniqueKey,熱度>>中取出?appName?對應的 Map?Map<uniqueKey,熱度>>;
-
遍歷?Map<uniqueKey,熱度>>中的 key,對每個 key 取出其熱度存入其?時間輪?對應的時間片中;
4-4. 熱度匯聚
完成第二步“熱度滑窗”后,映射任務 繼續對當前 App 進行“熱度匯聚”工作:
-
遍歷 App 的 key,將每個 key 的?時間輪?熱度進行匯總(即 30 秒時間窗口內總熱度)得到探測時刻?滑窗總熱度;
-
將?< key , 滑窗總熱度 >?以排序集合的方式存入?Redis 存儲服務?中,即?熱度匯聚結果;
4-5. 熱點探測
-
在前幾步,每 3 秒?一次的?映射任務?執行,對每個 App 都會產生一份當前時刻的?熱度匯聚結果?;
-
Hermes 服務端集群?中的“熱點探測”節點,對每個 App,只需周期性從其最近一份?熱度匯聚結果?中取出達到熱度閾值的 TopN 的 key 列表,即可得到本次探測的?熱點 key 列表;
TMC 熱點發現整體流程如下圖:
4-6. 特性總結
4-6-1. 實時性
Hermes-SDK?基于rsyslog + kafka 實時上報 key 訪問事件。映射任務 3 秒一個周期完成“熱度滑窗” + “熱度匯聚”工作,當有 熱點訪問場景 出現時最長 3 秒即可探測出對應 熱點 key。
4-6-2. 準確性
key 的熱度匯聚結果由“基于時間輪實現的滑動窗口”匯聚得到,相對準確地反應當前及最近正在發生訪問分布。
4-6-3. 擴展性
Hermes 服務端集群節點無狀態,節點數可基于 kafka 的 partition 數量橫向擴展。
“熱度滑窗” + “熱度匯聚” 過程基于 App 數量,在單節點內多線程擴展。
?
五、TMC 實戰效果
5-1. 快手商家某次商品營銷活動
有贊商家通過快手直播平臺為某商品搞活動,造成該商品短時間內被集中訪問產生訪問熱點,活動期間 TMC 記錄的實際熱點訪問效果數據如下:
5-1-1. 某核心應用的緩存請求&命中率曲線圖
-
上圖藍線為應用集群調用get()方法訪問緩存次數
-
上圖綠線為獲取緩存操作命中TMC本地緩存的次數
-
上圖為本地緩存命中率曲線圖
可以看出活動期間緩存請求量及本地緩存命中量均有明顯增長,本地緩存命中率達到近 80%(即應用集群中 80% 的緩存查詢請求被 TMC 本地緩存攔截)。
5-1-2. 熱點緩存對應用訪問的加速效果
-
上圖為應用接口 QPS 曲線
-
上圖為應用接口 RT 曲線
可以看出活動期間應用接口的請求量有明顯增長,由于 TMC 本地緩存的效果應用接口的 RT 反而出現下降。
5-2. 雙十一期間部分應用 TMC 效果展示
5-2-1. 商品域核心應用效果
5-2-2. 活動域核心應用效果
?
六、TMC 功能展望
在有贊,TMC 目前已為商品中心、物流中心、庫存中心、營銷活動、用戶中心、網關&消息等多個核心應用模塊提供服務,后續應用也在陸續接入中。
TMC 在提供“熱點探測” + “本地緩存”的核心能力同時,也為應用服務提供了靈活的配置選擇,應用服務可以結合實際業務情況在“熱點閾值”、“熱點 key 探測數量”、“熱點黑白名單”維度進行自由配置以達到更好的使用效果。
總結
以上是生活随笔為你收集整理的有赞多级缓存解决方案怎么做的,你知道吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Cloud生态的配置服务器
- 下一篇: Spring Cloud Alibaba