天天看點

閑魚如何一招保證推薦流穩如泰山背景業界主流溜一遍我的叢集Cache元件典型栗子展望

作者:閑魚技術——習武

背景

近幾年網際網路的快速發展中,網際網路業務發展越來越複雜,業務也被拆分得越來越細,阿裡内部業務也發生着翻天覆地的變化,從最初的單體應用,到後面的分布式叢集,再到最近幾年大中台小前台的業務形态,作為後端開發,依賴的服務方越來越多,同時依賴服務方的故障因素也會越來越多的會影響到閑魚的上層業務的穩定。例如在閑魚主推商品流的業務場景中,商品中台資料庫的抖動會造成主推商品流的卡頓或者頁面顯示空窗現象,個性化算法中台向量叢集的擴容也會造成推薦内容延時被拖到非常長,後面還有可能依賴其他的業務中台,作為上層業務如何保證依賴的中台越來越多的情況下,還能保證服務的穩定性運作呢?

業界主流溜一遍

根據日常解決問題的經驗,不能直接解決業務問題本身,可以折中解決業務問題也是一個不錯的辦法。上述業務問題中,當業務出現問題的時候,可以折中提前置備好所需的業務資料傳回給業務,也是一個不錯的辦法。在閑魚主推商品流的業務場景中,對可靠性要求非常高,因為推薦商品失敗,使用者看到推薦頁出現空窗,業務所需的資料量大概是5頁的推薦商品資料流,大概為3M左右。在實際解決問題中,筆者從業務所需的資料量級、可靠性要求級别等角度調研了業界一些通用解決辦法。

閑魚如何一招保證推薦流穩如泰山背景業界主流溜一遍我的叢集Cache元件典型栗子展望

為了給使用者良好的業務體驗,筆者主要使用服務端資料備援、用戶端資料備援、熔斷機制等方法,來確定使用者對閑魚App流暢的業務體驗。筆者主要服務端資料備援聊聊本地緩存,根據筆者在阿裡斷網演練的經驗,斷網演練時,某個區域的所有服務不可用,是以筆者在技術選型的時候沒有考慮分布式緩存Redis,Memcache之類等。目前就業界本地緩存庫有Guava、Caffeine、Ehcache、Cache2K、ConcurrentHashMap、Varnish、JackRabbit等,筆者選取了幾個性能比較優越的緩存庫比較,下面筆者從功能上、性能上、易用性、叢集能力、可視化報表上等分别比較。

閑魚如何一招保證推薦流穩如泰山背景業界主流溜一遍我的叢集Cache元件典型栗子展望

筆者對照目前業務需求對比了上述四個元件,在定時失效政策能力上,除了ConcurrentHashMap都是使用定時失效能力,并且三個元件時間複雜度都是O(n)。在叢集能力上,Ehcache依賴自身網絡協定保證叢集資料一緻性,不能使用現有集團内部元件保證資料一緻性。在本地緩存能力上,Caffeine的寫能力[1]優與Guava。在元件通用性上,Guava元件更加通用。最終筆者選用了Guava元件作為本地緩存元件,因為Guava 元件更加通用,并且很友善與阿裡内部中間件內建配合使用。在叢集資料同步能力,通過配置中心中間件實作資料同步,在可視化報表能力,通過定時任務列印日志,日志采集系統采集展示資料報表。接下來筆者介紹如何添加上述三種能力和優化Guava本地緩存能力。

我的叢集Cache元件

Guava Caching提供了定時失效、最後通路失效、最後寫入失效政策等能力,筆者主要使用了定時失效能力,在首次寫入Key後,指定時間過後,該Key會失效,業務擷取該Key時,會調用reload方法重新同步加載該Key。如果使用invalid方法使該Key無效,業務并發再次擷取該Key,多線程加載該Key時,隻有一個業務線程調用load方法加載該Key,其他線程等待該Key,加載完成後重新進入指定時間後流程。筆者在原來Guava Cache本地緩存能力上結合Spring自動注入能力,進行工程化,添加了業務所需的如下三種能力

  • 當key失效,本地緩存reload異步加載
  • 失效本地緩存key,整個叢集機器上key失效能力
  • 定時上報本機Cache内各個Key在本地緩存大小

根據上述業務能力,整體流程圖如下所示

閑魚如何一招保證推薦流穩如泰山背景業界主流溜一遍我的叢集Cache元件典型栗子展望

叢集本機Cache元件的整體結構類圖如下:

閑魚如何一招保證推薦流穩如泰山背景業界主流溜一遍我的叢集Cache元件典型栗子展望
  • AbstractCacheLoader重寫父類CacheLoader的reload方法,添加異步加載能力
  • LocalCacheManager管理所有實作AbstractCacheConfig的子類,并上報各自本地緩存大小。
  • 實作AbstractCacheConfig的業務配置子類,例如CurrentCacheConfig等,調用invalidate方法時,會通知叢集本機Cache中Key消息。

業務同學在使用叢集本機Cache元件時,隻需要繼承AbstractCacheConfig抽象類,聲明為Bean,即用叢集本機Cache元件,業務同學無需關心叢集環境問題等。相比Guava cache元件,提供了叢集本機Cache Key失效能力,以及對Key集中管理和監控,減少了單獨使用Guava cache帶來記憶體無法管理的問題。

接下來筆者介紹使用叢集本機Cache元件能力的典型案例: 自動置備兜底元件。

典型栗子

自動置備兜底元件

兜底是在服務遇到外部依賴異常(逾時、不可用、資料異常等),可能導緻服務無可以傳回的正常資料時,服務通過使用兜底資料提供服務的一種降級行為。自動置備兜底元件使用叢集本機cache的本機緩存能力和叢集失效能力,很友善完成兜底資料置備。在閑魚的業務場景中使用兜底置備元件的場景非常多,例如閑魚主推商品流等。

兜底自動置備元件原理如下:

閑魚如何一招保證推薦流穩如泰山背景業界主流溜一遍我的叢集Cache元件典型栗子展望
  • 使用定時任務scheduleX2定時觸發服務叢集中的一台伺服器,執行兜底置備,更新tair緩存内容,失效本地緩存,即失效叢集server的本地緩存。
  • 當業務請求擷取key時,會擷取tair中最新内容,并緩存到本地,再次請求,直接本地擷取。

詳細業務請求流程圖如下所示

閑魚如何一招保證推薦流穩如泰山背景業界主流溜一遍我的叢集Cache元件典型栗子展望

自動兜底元件已經在閑魚的多個業務場景得到使用,在斷網演練情況下,服務端RT延時和成功率有了明顯的提升,閑魚主要業務場景的提升效果如下:

閑魚如何一招保證推薦流穩如泰山背景業界主流溜一遍我的叢集Cache元件典型栗子展望

展望

在叢集本機cache元件使用過程中也發現一些問題,例如有時候叢集本機cache緩存錯誤的配置,需要重新開機叢集或者等待key失效,是以需要叢集本機cache元件web管理功能。在叢集本機cache元件推廣中,發現有些業務場景的緩存key對應的緩存對象比較大,或者緩存key的數量比較多,後期按照key使用頻率等級,考慮對于長期不使用的key存儲到本機磁盤上,讓業務方不關心緩存Key過大可能造成的問題。

參考:

[1]:

Halodoc Caching Analysis