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

1、引子

1-1. TMC 是什麼

TMC ,即「透明多級緩存( Transparent Multilevel Cache )」,是有贊 PaaS 團隊給公司內應用提供的總體緩存解決方案。redis

TMC 在通用「分佈式緩存解決方案(如 CodisProxy + Redis ,若有贊自研分佈式緩存系統 zanKV )」基礎上,增長了如下功能:spring

  • 應用層熱點探測
  • 應用層本地緩存
  • 應用層緩存命中統計

以幫助應用層解決緩存使用過程當中出現的熱點訪問問題。緩存

1-2. 爲何要作 TMC

使用有贊服務的電商商家數量和類型不少,商家會不按期作一些「商品秒殺」、「商品推廣」活動,致使「營銷活動」、「商品詳情」、「交易下單」等鏈路應用出現 緩存熱點訪問 的狀況:數據結構

  • 活動時間、活動類型、活動商品之類的信息不可預期,致使 緩存熱點訪問 狀況不可提早預知;
  • 緩存熱點訪問 出現期間,應用層少數 熱點訪問 key 產生大量緩存訪問請求:衝擊分佈式緩存系統,大量佔據內網帶寬,最終影響應用層系統穩定性;

爲了應對以上問題,須要一個可以 自動發現熱點將熱點緩存訪問請求前置在應用層本地緩存 的解決方案,這就是 TMC 產生的緣由。多線程

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

基於上述描述,咱們總結了下列 多級緩存解決方案 須要解決的需求痛點:架構

  • 熱點探測:如何快速且準確的發現 熱點訪問 key
  • 數據一致性:前置在應用層的本地緩存,如何保障與分佈式緩存系統的數據一致性?
  • 效果驗證:如何讓應用層查看本地緩存命中率、熱點 key 等數據,驗證多級緩存效果?
  • 透明接入:總體解決方案如何減小對應用系統的入侵,作到快速平滑接入?

TMC 聚焦上述痛點,設計並實現了總體解決方案。以支持「熱點探測」和「本地緩存」,減小熱點訪問時對下游分佈式緩存服務的衝擊,避免影響應用服務的性能及穩定性。app

2、 TMC 總體架構

圖片描述

TMC 總體架構如上圖,共分爲三層:異步

  • 存儲層:提供基礎的kv數據存儲能力,針對不一樣的業務場景選用不一樣的存儲服務( codis / zankv / aerospike );
  • 代理層:爲應用層提供統一的緩存使用入口及通訊協議,承擔分佈式數據水平切分後的路由功能轉發工做;
  • 應用層:提供統一客戶端給應用服務使用,內置「熱點探測」、「本地緩存」等功能,對業務透明;

本篇聚焦在應用層客戶端的「熱點探測」、「本地緩存」功能。分佈式

3、 TMC 本地緩存

3-1. 如何透明

TMC 是如何減小對業務應用系統的入侵,作到透明接入的?性能

對於公司 Java 應用服務,在緩存客戶端使用方式上分爲兩類:

  • 基於spring.data.redis包,使用RedisTemplate編寫業務代碼;
  • 基於youzan.framework.redis包,使用RedisClient編寫業務代碼;

不論使用以上那種方式,最終經過JedisPool建立的Jedis對象與緩存服務端代理層作請求交互。

圖片描述

TMC 對原生jedis包的JedisPoolJedis類作了改造,在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 值,不去訪問 緩存集羣 ,從而將訪問請求前置在應用層;
  • 對於非 熱點keyHermes-SDK 會經過Callable回調 Jedis-Client 的原生接口,從 緩存集羣 拿到 value 值;
  • 對於 Jedis-Client 的每次 key 值訪問請求,Hermes-SDK 都會經過其 通訊模塊key訪問事件 異步上報給 Hermes服務端集羣 ,以便其根據上報數據進行「熱點探測」;

2)key值過時

  • Java 應用調用 Jedis-Clientset() del() expire()接口時會致使對應 key 值失效,Jedis-Client 會同步調用 Hermes-SDKinvalid()方法告知其「 key 值失效」事件;
  • 對於 熱點keyHermes-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集羣 廣播事件,異步失效業務應用集羣中其餘節點的本地緩存,保證 集羣最終一致

4、TMC熱點發現

4-1. 總體流程

圖片描述

TMC 熱點發現流程分爲四步:

  • 數據收集:收集 Hermes-SDK 上報的 key訪問事件
  • 熱度滑窗:對 App 的每一個 Key ,維護一個時間輪,記錄基於當前時刻滑窗的訪問熱度;
  • 熱度匯聚:對 App 的全部 Key ,以<key,熱度>的形式進行 熱度排序彙總
  • 熱點探測:對 App ,從 熱Key排序彙總 結果中選出 TopN的熱點Key ,推送給 Hermes-SDK

4-2. 數據收集

Hermes-SDK 經過本地rsyslogkey訪問事件 以協議格式放入 kafkaHermes服務端集羣 的每一個節點消費 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 數量,在單節點內多線程擴展。

5、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. 活動域核心應用效果

圖片描述
圖片描述

6、TMC功能展望

在有贊, TMC 目前已爲商品中心、物流中心、庫存中心、營銷活動、用戶中心、網關&消息等多個核心應用模塊提供服務,後續應用也在陸續接入中。

TMC 在提供「熱點探測」 + 「本地緩存」的核心能力同時,也爲應用服務提供了靈活的配置選擇,應用服務能夠結合實際業務狀況在「熱點閾值」、「熱點key探測數量」、「熱點黑白名單」維度進行自由配置以達到更好的使用效果。

最後, TMC 的迭代還在持續進行中...

圖片描述

相關文章
相關標籤/搜索