在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何使用緩存

科技綠洲 ? 來源:Java技術指北 ? 作者:Java技術指北 ? 2023-10-08 14:07 ? 次閱讀

緩存技術被認為是減輕服務器負載、降低網絡擁塞、增強Web可擴展性的有效途徑之一,其基本思想是利用客戶訪問的時間局部性(Temproral Locality)原理, 將客戶訪問過的內容在Cache中存放一個副本,當該內容下次被訪問時,不必連接到駐留網站,而是由Cache中保留的副本提供。

在企業Web應用中,通過緩存技術能夠提高請求的響應速度;減少系統IO開銷;降低系統數據讀寫壓力...

緩存的意義

首先我們要知道,在我們開發過程中,為什么要使用緩存,緩存能夠為我們帶來哪些好處!

優點

  • 通過緩存承載系統壓力,減少對系統或網絡資源訪問而引起的性能消耗,在流量較大時能夠很好地減少系統擁塞
  • 緩存一般都是使用存取非常快的組件實現,通過緩存能夠快速響應客戶端請求,從而降低客戶訪問延遲,提審系統響應速度
  • 在配備負載均衡的應用架構中,通過緩存靜態資源能夠有效減少服務器負載壓力
  • 當下游應用故障時,通過返回緩存數據能夠在一定程度上增強應用容錯性

缺點

  • 緩存數據與實際數據不一致問題問題
  • 高并發場景時存在緩存擊穿、緩存穿透、緩存雪崩等問題

總的來說,緩存主要是針對高頻訪問但低頻更新的數據,從而加快服務器響應與原資源訪問壓力

Guava Cache是一個相對比較簡單并且容易理解的本地緩存框架,今天主要以此為開端來認識并學習如何使用緩存

Guava Cache特色

本地緩存我們可以簡單的理解為Map,將數據保存到Map(內存)中,下次使用該數據時,通過key直接從Map中取即可。但是使用Map會有一些幾個問題需要考慮:

  1. 緩存的容量。不可能無限制的對數據進行緩存,當數據較大時占用系統資源會導致主業務受影響
  2. 緩存的清理。有些緩存使用頻率很低,如果一直占用資源也是一種浪費
  3. 并發訪問時的效率問題。緩存更新時瞬時對系統、網絡資源的訪問導致故障
  4. 緩存使用情況評估

當然以上問題我們通過我們對Map包裝下即可實現,當然Guava Cache也就是基于這種思想,底層原理則是基于Map實現,我們看下其有哪些特色:

  • 緩存過期和淘汰機制

通過設置Key的過期時間,包括訪問過期和創建過期;設置緩存容量大小,采用LRU的方式,選擇最近最久的緩存進行刪除。

  • 并發處理能力

Cache主要基于CurrentHashMap實現線程安全;通過對key的計算,基于分段鎖,提高緩存讀寫效率,降低鎖的粒度,提升并發能力

  • 更新鎖定

在緩存中查詢某個key,如果不存在,則查源數據,并回填緩存。在高并發下會出現,多次查詢元數據并重復回填緩存,可能會造成系統故障,最明顯的DB服務器宕機,性能下降等。GuavaCache通過在CacheLoader調用load方法時,對同一個key同一時刻只會有一個請求去讀源數據并回填緩存,后面的請求則直接繼續從緩存讀取,有效阻斷并發請求對資源服務的影響。

  • 集成數據源

一般我們在業務中操作緩存,都會操作緩存和數據源兩部分GuavaCache的get可以集成數據源,在從緩存中讀取不到時可以從數據源中讀取數據并回填緩存

  • 監控統計

監控緩存加載次數、命中率、失誤率以及數據加載時長等

API介紹

  • 緩存構建
    • ManualCache
      此時Cache相當于一個Map,對數據進行CRUD操作時,需要同步操作緩存Map; 高并發情況時,可以使用get(k,loader)讀緩存,通過Cache鎖機制,防止對系統資源(DB)的并發訪問 通過put方法實現緩存的存入與更新;
    • LoadingCache
      此時構建的是一個實現了Cache接口的LoadingCache,相比ManualCache,提供了緩存回填機制,即當緩存不存在時,會基于CacheLoader查詢數據并將結果回填到緩存, 在高并發時,可以有效地基于緩存鎖減少對系統資源的調用。此時僅需要關注緩存的使用,緩存的更新與存入都是基于CacheLoader實現;
  • 緩存獲取
    • get(k)
      根據key查詢,沒有則觸發load;如果load為空則拋出異常
    • getUnchecked(k)
      緩存不存在或返回為null會拋出檢查異常
    • get(k,loader)
      根據key查詢,沒有則調用loader方法,且對結果緩存;如果loader返回null則拋出異常,此時不會調用默認的load方法
    • getIfPresent(k)
      有緩存則返回,否則返回null,不會觸發load
  • 緩存更新
    • put(k,v)
      如果緩存已經存在,則會先進行一次刪除
  • 緩存刪除
    • invalidate(k)
      根據key使緩存失效
    • 過期
      通過配置的過期參數,比如expireAfterAccess、expireAfterWrite、refreshAfterWrite
    • 過載
      當緩存數據量超過設置的最大值時,根據LRU算法進行刪除
    • 引用
      構建緩存時將鍵值設置為弱引用、軟引用,基于GC機制來清理緩存
  • 統計
    • hitRate()
      緩存命中率;
    • hitMiss()
      緩存失誤率;
    • loadCount() 加載次數;
    • averageLoadPenalty()
      加載新值的平均時間,單位為納秒;
    • evictionCount() 緩存項被回收的總數,不包括顯式清除。

Builder配置

配置描述
expireAfterAccess多久沒有讀寫則過期
expireAfterWrite寫入后多久沒更新自動過期,先刪除,后load
refreshAfterWrite上一次更新后多久自動刷新,先reload后刪除,并發時會取到老的數據
removalListener設置緩存刪除監聽
initialCapacity緩存初始化大小
concurrencyLevel最大的并發數,可以理解為并發線程數量
maximumSize最大緩存數量,超過時會根據策略清除
maximumWeight最大權重容量數,僅用于確定緩存是否超過容量
recordStats緩存命中統計

簡單示例

  • ManualCache模式
    下面以用戶服務為例,我們看下如何在增刪改查方法中使用緩存:
private Cache< String, User > cache = CacheBuilder.newBuilder()
            .expireAfterWrite(3, TimeUnit.SECONDS)//寫入多久沒更新自動過期,先刪除,后load
            .removalListener(new RemovalListener< Object, Object >() {
                @Override
                public void onRemoval(RemovalNotification< Object, Object > notification) {
                    LOGGER.info("{} remove {}",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),notification.getKey());
                }
            })
            .initialCapacity(20) //初始化容量
            .concurrencyLevel(10) // 并發
            .maximumSize(100) //最多緩存數量
            .recordStats() // 開啟統計
            .build();

@Override
    public User getUser(String id){
//        緩存不存在時,通過LocalCache鎖機制,防止對數據庫的高頻訪問
       User user;
       try {
           user = cache.get(id,()- > {
               LOGGER.info("緩存不存在,從loader加載數據");
               return userDao.get(id);
           });
       } catch (ExecutionException e) {
           throw new RuntimeException(e);
       }
        return user;
    }

    @Override
    public User saveOrUpdateUser(User user){
        userDao.saveOrUpdate(user);
        cache.put(user.getId(),user);
        return user;
    }

    @Override
    public void removeUser(String id){
        userDao.remove(id);
        cache.invalidate(id);
    }
  • LoadingCache模式
private LoadingCache< String, User > cache = CacheBuilder.newBuilder()
            // 省略
            .build(new CacheLoader< String, User >() {
                @Override
                public User load(String key) throws Exception {
                    LOGGER.info("{} load {}",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),key);
                    return userDao.get(key);
                }

                @Override
                public ListenableFuture< User > reload(String key, User oldUser) throws Exception {
                    LOGGER.info("{} reload {}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),key);
                    ListenableFutureTask< User > listenableFutureTask = ListenableFutureTask.create(() - > userDao.get(key));
                    CompletableFuture.runAsync(listenableFutureTask);
                    return listenableFutureTask;
                }
            });

    @SneakyThrows
    @Override
    public User getUser(String id){
        // 緩存不存在或返回為null會拋出異常
        try {
            return cache.getUnchecked(id);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public User saveOrUpdateUser(User user){
        cache.invalidate(user.getId());
        return userDao.saveOrUpdate(user);
    }

    @Override
    public void removeUser(String id){
        cache.invalidate(id);
        userDao.remove(id);
    }

總結:第一種寫法更像是前面說到的Map,在對數據進行CRUD操作時,需要用戶手動對緩存進行同步的更新或刪除操作,所以叫ManualCache(手動),當然Guava Cache對Map的加強依然有效,比如過期清除,緩存容量限制。第二種方式寫法差不多,主要是引入了CacheLoader接口,在讀數據時緩存數據不存在時,通過CacheLoader的load方法先寫緩存后返回數據

注意

  • expireAfterWrite、refreshAfterWrite的區別

在refreshAfterWrite導致緩存失效時,并不會因為更新緩存而阻塞緩存數據的返回,只不過是返回老的數據

  • 不能緩存null

有時候為了將值為null的數據統一緩存,這樣就不會因為沒有緩存數據而訪問數據庫造成壓力

  • 讀寫時才進行刪除

Guava Cache的緩存數據刪除是在更新或寫入時才會觸發,沒有單獨的調度服務完成這一工作

本地緩存

類似的本地緩存還有,有興趣的可以自己嘗試,其實實現思想應該也差不多

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7030

    瀏覽量

    89034
  • 服務器
    +關注

    關注

    12

    文章

    9160

    瀏覽量

    85421
  • 網絡
    +關注

    關注

    14

    文章

    7565

    瀏覽量

    88788
  • 緩存
    +關注

    關注

    1

    文章

    240

    瀏覽量

    26678
  • key
    key
    +關注

    關注

    0

    文章

    49

    瀏覽量

    12826
收藏 人收藏

    評論

    相關推薦

    硬盤緩存

    硬盤緩存              緩存(Cache)是SCSI硬盤與外部總線交換數據的場所,硬盤先將數據傳送到緩存,再由
    發表于 12-17 14:43 ?1221次閱讀

    硬盤緩存是什么?

    硬盤緩存是什么? 緩存是硬盤內部的高速存儲器,硬盤需要通過它來完成與外部數據總線交換數據的過程。硬盤本身的高速緩存(Cache)
    發表于 01-22 10:40 ?718次閱讀

    Mybatis緩存之一級緩存

    本文主要講mybatis的一級緩存,一級緩存是SqlSession級別的緩存。mybatis提供查詢緩存,用于減輕數據壓力,提高數據庫性能。mybaits提供一級
    發表于 11-27 20:44 ?1227次閱讀
    Mybatis<b class='flag-5'>緩存</b>之一級<b class='flag-5'>緩存</b>

    渲染中的幀緩存和深度緩存

    渲染涉及大量的緩存,這里緩存只是一個簡單的存有像素數據的矩形內存塊,最重要緩存是幀緩存和深度緩存
    的頭像 發表于 05-14 11:44 ?6344次閱讀
    渲染中的幀<b class='flag-5'>緩存</b>和深度<b class='flag-5'>緩存</b>

    什么是Web緩存,HTTP緩存和瀏覽器緩存的區別

    前端緩存主要是分為HTTP緩存和瀏覽器緩存。其中HTTP緩存是在HTTP請求傳輸時用到的緩存,主要在服務器代碼上設置;而瀏覽器
    發表于 09-13 04:17 ?9454次閱讀
    什么是Web<b class='flag-5'>緩存</b>,HTTP<b class='flag-5'>緩存</b>和瀏覽器<b class='flag-5'>緩存</b>的區別

    緩存是什么 為什么需要緩存

    緩存是軟件開發中一個非常有用的概念,數據庫緩存更是在項目中必然會遇到的場景。
    的頭像 發表于 09-28 02:48 ?1.1w次閱讀
    <b class='flag-5'>緩存</b>是什么 為什么需要<b class='flag-5'>緩存</b>

    緩存的基本原理 緩存的分類

    緩存的主要手段有:瀏覽器緩存、CDN、反向代理、本地緩存、分布式緩存、數據庫緩存
    發表于 06-13 12:04 ?4745次閱讀

    緩存如何工作,如何設計CPU緩存

    20世紀80年代,CPU性能有了顯著提升,但這受到板載內存訪問速度緩慢增長的阻礙。隨著這種差異的惡化,工程師們發現了一種通過新的設計技術緩存來解決問題的方法。本文將幫助你進一步了解什么是緩存,它如何工作以及如何設計CPU緩存
    的頭像 發表于 11-19 17:23 ?2748次閱讀

    到底是更新緩存還是刪緩存

    如何保證緩存和數據庫一致性,這是一個老生常談的話題了。 但很多人對這個問題,依舊有很多疑惑: 到底是更新緩存還是刪緩存? 到底選擇先更新數據庫,再刪除緩存,還是先刪除
    的頭像 發表于 10-22 17:05 ?5057次閱讀
    到底是更新<b class='flag-5'>緩存</b>還是刪<b class='flag-5'>緩存</b>

    弄懂HTTP緩存機制及原理

    兩類緩存規則可以同時存在,強制緩存優先級高于對比緩存,也就是說,當執行強制緩存的規則時,如果緩存生效,直接使用
    的頭像 發表于 01-29 09:38 ?704次閱讀

    聊聊本地緩存和分布式緩存

    本地緩存 :應用中的緩存組件,緩存組件和應用在同一進程中,緩存的讀寫非常快,沒有網絡開銷。但各應用或集群的各節點都需要維護自己的單獨緩存,無
    發表于 06-11 15:12 ?833次閱讀
    聊聊本地<b class='flag-5'>緩存</b>和分布式<b class='flag-5'>緩存</b>

    mybatis一級緩存和二級緩存的原理

    MyBatis是一種輕量級的持久化框架,它提供了一級緩存和二級緩存的機制來優化數據庫操作性能。一級緩存是默認開啟的,而二級緩存需要手動配置啟用。 一、一級
    的頭像 發表于 12-03 11:55 ?1177次閱讀

    Redis緩存預熱+緩存雪崩+緩存擊穿+緩存穿透要點簡析

    緩存預熱就是系統上線后,提前將相關的緩存數據直接加載到緩存系統。
    的頭像 發表于 12-25 09:41 ?906次閱讀
    Redis<b class='flag-5'>緩存</b>預熱+<b class='flag-5'>緩存</b>雪崩+<b class='flag-5'>緩存</b>擊穿+<b class='flag-5'>緩存</b>穿透要點簡析

    緩存之美——如何選擇合適的本地緩存

    Guava cache是Google開發的Guava工具包中一套完善的JVM本地緩存框架,底層實現的數據結構類似于ConcurrentHashMap,但是進行了更多的能力拓展,包括緩存過期時間設置、緩存容量設置、多種淘汰策略、
    的頭像 發表于 11-17 14:24 ?296次閱讀
    <b class='flag-5'>緩存</b>之美——如何選擇合適的本地<b class='flag-5'>緩存</b>?

    HTTP緩存頭的使用 本地緩存與遠程緩存的區別

    HTTP緩存頭是一組HTTP響應頭,它們控制瀏覽器和中間代理服務器如何緩存網頁內容。合理使用HTTP緩存頭可以顯著提高網站的加載速度和性能,減少服務器的負載。 1. HTTP緩存頭概述
    的頭像 發表于 12-18 09:41 ?107次閱讀
    主站蜘蛛池模板: 77久久| 午夜视频免费| 久久久久大香线焦| 视频一区二区免费| 三级视频在线播放线观看| 免费看18污黄| 欧美整片第一页| 天天视频天天爽| 亚洲国产精品丝袜在线观看| 日韩a无吗一区二区三区| 亚洲色四在线视频观看| 中文字幕一区二区三区四区| 色综合天天综久久久噜噜噜久久〔 | 91成人免费在线视频| 欧美涩色| 日本视频www色| 天天操网站| 在线亚洲成人| 国产精品9999久久久久仙踪林| 欧美日穴| 人与禽性视频77777| 日本色视| 亚洲男人精品| 真实的国产乱xxxx在线| 亚洲区| 久久成人综合| 午夜影视在线观看| 深夜福利一区| 激情综合五月网| 影院在线观看免费| 日韩伦| 毛片污| 四虎在线永久免费视频网站| 午夜视频在线观看完整高清在线| 一区二区不卡视频在线观看| 麦克斯奥特曼免费观看| 天天做天天爱天天影视综合| 第四色亚洲| se94se亚洲欧美在线| 欧洲精品不卡1卡2卡三卡| 国产视频一二|