1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        緩存熱點,緩存穿透,終極解決方案看過來

        共 3669字,需瀏覽 8分鐘

         ·

        2021-08-30 09:38

        作者:鉑賽東
        來源:SegmentFault 思否社區(qū)

        背景

        前不久,因為公司業(yè)務需要,需要解決在大促場景下后端業(yè)務的熱點緩存問題,所以研究了下緩存熱點解決方案。
        很多公司的緩存都是基于redis來做的,redis的性能其實已經(jīng)足以能應付大部分的場景,但是對于大促期間或者活動搶購期間的某個爆品,可能會出現(xiàn)在幾秒時間內流入大量的流量,由于某個爆品的數(shù)據(jù)在redis cluster場景下會按照hash規(guī)則被存放在某個redis分片上,那么這幾秒的流量都會壓到這個redis分片,從而在瞬間會導致這個redis分片的癱瘓,也會影響后續(xù)的redis請求的阻塞。
        還有個場景,就是公司并不是所有的服務端邏輯都有緩存。在流量起來的時候,這些熱key還是會壓到數(shù)據(jù)庫層面。導致壓力。

        解決方案

        一般常見的解決方案就是增加二級緩存,對于熱點數(shù)據(jù)寫到jvm里一份。設置過期時間。但是什么時候設置,熱點如何探測,規(guī)則如何設置,過期時間設置多少。甚至于如何快速落地,這都是需要研究的問題。
        我們希望有一個統(tǒng)一的方案來解決這些問題。
        我們發(fā)現(xiàn)了Hotkey這款開源框架。
        Hotkey源于京東,hotkey能自動地對任意突發(fā)性的無法預知的熱點數(shù)據(jù),按照配置的規(guī)則進行毫秒級別的探測,探測到的熱數(shù)據(jù)會推送到所有的服務端JVM中,大幅減輕對后端數(shù)據(jù)層的沖擊。這些熱數(shù)據(jù)在整個微服務集群會保持一致性,當熱點消失的時候,自動從jvm中進行移除。
        Hotkey的特性能很好的實現(xiàn)我們的目標。并且京東內部也用Hotkey實戰(zhàn)了618大促,穩(wěn)定性有所保障。
        Hotkey的架構圖(以下圖引用自Hotkey在Gitee的主頁)


        Hotkey整個架構共分為以下幾個部分:
        worker:負責采集上報信息,根據(jù)規(guī)則計算出熱點信息,規(guī)則來自于etcd。熱點信息推送到client里
        client:每個client連接etcd,獲取每個worker的ip和端口,和worker保持長鏈接,接受worker的熱點信息推送
        etcd:分布式的協(xié)調者,接受每個worker的心跳上報,并把worker的連接信息推送給client。監(jiān)聽規(guī)則的改變,推送給worker
        dashboard:ui界面,查看實例以及worker的狀態(tài),查看以及修改規(guī)則數(shù)據(jù)。規(guī)則存到mysql,同時由etcd推送給worker
        下面給出hotkey的項目地址
        hotkey: 京東App后臺中間件,毫秒級探測熱點數(shù)據(jù),毫秒級推送至服務器集群內存,大幅降低熱key對數(shù)據(jù)層查詢壓力 (gitee.com)
        關于Hotkey的介紹和如何搭建,大家可以看這篇文章來了解,這里就不多贅述。
        京東毫秒級熱key探測框架設計與實踐,已實戰(zhàn)于618大促 (qq.com)

        碰到的問題

        我們在搭建hotkey環(huán)境和落地實施中,碰到2個問題:
        • Hotkey雖然開源,但是相關client jar包并未上傳中央倉庫,dashboard和worker啟動包也并未提供下載。需要下載源碼進行編譯,編譯過程中也碰到一些包依賴的問題。

        • Hotkey的client jar只提供了api級別的方法供程序使用,如果要落地到業(yè)務項目中,需要大規(guī)模的修改代碼才能實施。


        我們更希望提供一種侵入更少的方式,在RPC以及接口的層面進行代理包裝。使用者無論使用什么RPC框架,只是在相關接口上打上標注,而無需動業(yè)務的任何代碼。就可以在這個接口層面進行檢測熱點。如果該接口的某個參數(shù)為熱點的話,就自動進行代理,走jvm的熱點數(shù)據(jù),等熱點消除后,依舊走原來的調用。
        如果你覺得上述的描述過于難以理解的話,那么直白點說就是:
        比如某個活動大促期間有個商品S001進行搶購,有大量的流量進入了商品詳情頁面。這個商品詳情RPC方式調用了商品服務的以下接口方法獲取商品信息:
        public interface ProductService{
          SkuInfo getSkuInfo(String skuCode);
        }

        那么我們希望只在這個接口上打上標注。就可以適配Hotkey框架進行探測熱點,當商品S001被大量請求時,S001這個商品就可以成為熱點,這時getSkuInfo這個接口就會被自動代理,從而只從Jvm中獲取數(shù)據(jù),而不會真正走RPC調用。等熱點消除后,這個接口依舊調用RPC獲取數(shù)據(jù)。
        這樣的方式無疑侵入性更小,更容易使Hotkey框架落地。

        Hotlink客戶端

        為此我們基于Hotkey client研發(fā)了Hotlink客戶端框架,該客戶端框架能讓Hotkey更完美的落地,增強了Hotkey客戶端的能力。
        Hotlink的項目地址:hotlink: Hotlink框架是一個基于Hotkey框架的客戶端增強版實現(xiàn),該客戶端框架能讓Hotkey更完美的落地,增強了Hotkey客戶端的能力。(gitee.com)
        該客戶端框架有以下特點:
        • 業(yè)務接入簡單,只需要一個標注,1分鐘就能使你的RPC接口接入熱點探測框架

        • 啟動時動態(tài)掃描所有Hotlink標注的接口,創(chuàng)建動態(tài)代理

        • 基于動態(tài)代理去對接口做增強,理論上只要有接口,就支持任何RPC框架

        • 本地方法只要有接口,也能使用熱點探測






        結合Hotkey的架構圖,Hotlink在整個架構圖中的位置如下圖:

        Hotlink如何使用

        第一步
        按照Hotkey的部署要求,搭建好worker和dashboard。具體方式請參照:
        hotkey: 京東App后臺中間件,毫秒級探測熱點數(shù)據(jù),毫秒級推送至服務器集群內存,大幅降低熱key對數(shù)據(jù)層查詢壓力 (gitee.com)
        第二步
        本地業(yè)務項目依賴jar包(此jar包并未上傳到中央倉庫,需要大家自己deploy到自己公司的私庫)
        <dependency>
          <groupId>com.thebeastshop</groupId>
          <artifactId>hotlink-spring-boot-starter</artifactId>
          <version>1.0.12</version>
        </dependency>

        hotlink需要的fastjson和groovy版本有點要求,如果你項目中的這2個包版本過低又同時覆蓋了hotlink的傳遞依賴包時,需要額外指定版本:
        <fastjson.version>1.2.70</fastjson.version>
        <guava.version>29.0-jre</guava.version>

        第三步
        本地springboot配置文件里加入?yún)?shù)
        #此app-name不配置的話,會優(yōu)先讀取spring.application.name屬性
        hotlink.app-name=test
        #etcd地址和端口
        hotlink.etcd-url=http://xxx.xxx.xxx.xxx:2379

        第四步
        在你的接口里加入標簽@Hotlink
        在接口上加:接口里所有的方法都會自動探測熱點
        在方法上加:只有這個方法會自動探測熱點
        比如:
        public interface ProductService{
          @Hotlink
          SkuInfo getSkuInfo(String skuCode);
        }

        那么當某一個SKU001成為熱點時,那么傳入?yún)?shù)SKU001會自動代理從JVM里取到數(shù)據(jù),而SKU002則繼續(xù)走RPC調用。
        這樣就完成了所有的配置。啟動皆可。

        使用Hotlink需要注意的事項

        由于Hotlink的實現(xiàn)是用動態(tài)代理來實現(xiàn),只要滿足這兩個條件,即可在啟動時會掃描器掃到:
        • 接口層面上標注@Hotlink

        • 相關實現(xiàn)會被注入Spring上下文中




        在標注接口的時候,盡量標注在一定時間范圍內是冪等的接口。比如會員查詢,sku信息查詢,相關活動信息的查詢,這些信息在一定時間范圍內不會頻繁變動,那么就適合做熱點探測。
        非冪等性的接口,即便是相同參數(shù),每次返回也會不一樣。那就不建議做熱點探測。比如下單,庫存的查詢,余額的查詢。這樣的接口如果一旦被升級成熱點。那會影響業(yè)務界面的正確性和后續(xù)邏輯的判斷錯誤。


        點擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動和交流,掃描下方”二維碼“或在“公眾號后臺回復“ 入群 ”即可加入我們的技術交流群,收獲更多的技術文章~

        - END -


        瀏覽 18
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            疯狂操逼大香蕉 | 中国一级淫片bbb | 欧美日韩18禁 | 日本三a级 | 美女骚穴 | 欧美在线观看视频一区二区 | 啊~用力cao嗯cao烂我闺蜜 | 三级全黄做爰视频 | 成人深夜小视频 | 天天拍天天少妇av |