www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]前言 隨著互聯(lián)網(wǎng)的高速發(fā)展,市面上也出現(xiàn)了越來越多的網(wǎng)站和app。我們判斷一個(gè)軟件是否好用,用戶體驗(yàn)就是一個(gè)重要的衡量標(biāo)準(zhǔn)。比如說我們經(jīng)常用的微信,打開一個(gè)頁(yè)面要十幾秒,發(fā)個(gè)語(yǔ)音要幾分鐘對(duì)方才能收到。相信這樣的軟件大家肯定是都不愿意用的。軟件要

前言

隨著互聯(lián)網(wǎng)的高速發(fā)展,市面上也出現(xiàn)了越來越多的網(wǎng)站和app。我們判斷一個(gè)軟件是否好用,用戶體驗(yàn)就是一個(gè)重要的衡量標(biāo)準(zhǔn)。比如說我們經(jīng)常用的微信,打開一個(gè)頁(yè)面要十幾秒,發(fā)個(gè)語(yǔ)音要幾分鐘對(duì)方才能收到。相信這樣的軟件大家肯定是都不愿意用的。軟件要做到用戶體驗(yàn)好,響應(yīng)速度快,緩存就是必不可少的一個(gè)神器。緩存又分進(jìn)程內(nèi)緩存和分布式緩存兩種:分布式緩存如redis、memcached等,還有本地(進(jìn)程內(nèi))緩存如ehcache、GuavaCache、Caffeine等。說起Guava Cache,很多人都不會(huì)陌生,它是Google Guava工具包中的一個(gè)非常方便易用的本地化緩存實(shí)現(xiàn),基于LRU算法實(shí)現(xiàn),支持多種緩存過期策略。由于Guava的大量使用,Guava Cache也得到了大量的應(yīng)用。但是,Guava Cache的性能一定是最好的嗎?也許,曾經(jīng)它的性能是非常不錯(cuò)的。正所謂長(zhǎng)江后浪推前浪,前浪被拍在沙灘上。我們就來介紹一個(gè)比Guava Cache性能更高的緩存框架:Caffeine。

Tips: Spring5(SpringBoot2)開始用Caffeine取代guava.詳見官方信息SPR-13797
https://jira.spring.io/browse/SPR-13797

官方性能比較

以下測(cè)試都是基于jmh測(cè)試的,官網(wǎng)地址
測(cè)試為什么要基于jmh測(cè)試,可以參考知乎上R回答

在HotSpot VM上跑microbenchmark切記不要在main()里跑循環(huán)計(jì)時(shí)就完事。這是典型錯(cuò)誤。重要的事情重復(fù)三遍:請(qǐng)用JMH,請(qǐng)用JMH,請(qǐng)用JMH。除非非常了解HotSpot的實(shí)現(xiàn)細(xì)節(jié),在main里這樣跑循環(huán)計(jì)時(shí)得到的結(jié)果其實(shí)對(duì)一般程序員來說根本沒有任何意義,因?yàn)闊o(wú)法解釋。

  • 8個(gè)線程讀,100%的讀操作

    本地緩存性能之王Caffeine
  • 6個(gè)線程讀,2個(gè)線程寫,也就是75%的讀操作,25%的寫操作。

    本地緩存性能之王Caffeine
  • 8個(gè)線程寫,100%的寫操作

    本地緩存性能之王Caffeine
對(duì)比結(jié)論

可以從數(shù)據(jù)看出來Caffeine的性能都比Guava要好。然后Caffeine的API的操作功能和Guava是基本保持一致的,并且  Caffeine為了兼容之前是Guava的用戶,做了一個(gè)Guava的Adapter給大家使用也是十分的貼心。

如何使用

  • 在 pom.xml 中添加 caffeine 依賴

1<!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine -->
2<dependency>
3    <groupId>com.github.ben-manes.caffeine</groupId>
4    <artifactId>caffeine</artifactId>
5    <version>2.8.2</version>
6</dependency>

創(chuàng)建對(duì)象

1 Cache<String, Object> cache = Caffeine.newBuilder()
2                .initialCapacity(100)//初始大小
3                .maximumSize(200)//最大數(shù)量
4                .expireAfterWrite(3, TimeUnit.SECONDS)//過期時(shí)間
5                .build();
創(chuàng)建參數(shù)介紹
  • initialCapacity: 初始的緩存空間大小

  • maximumSize: 緩存的最大數(shù)量

  • maximumWeight: 緩存的最大權(quán)重

  • expireAfterAccess: 最后一次讀或?qū)懖僮骱蠼?jīng)過指定時(shí)間過期

  • expireAfterWrite: 最后一次寫操作后經(jīng)過指定時(shí)間過期

  • refreshAfterWrite: 創(chuàng)建緩存或者最近一次更新緩存后經(jīng)過指定時(shí)間間隔,刷新緩存

  • weakKeys: 打開key的弱引用

  • weakValues:打開value的弱引用

  • softValues:打開value的軟引用

  • recordStats:開發(fā)統(tǒng)計(jì)功能

注意:
expireAfterWrite和expireAfterAccess同時(shí)存在時(shí),以expireAfterWrite為準(zhǔn)。
maximumSize和maximumWeight不可以同時(shí)使用。

添加數(shù)據(jù)

Caffeine 為我們提供了手動(dòng)、同步和異步這幾種填充策略。
下面我們來演示下手動(dòng)填充策略吧,其他幾種如果大家感興趣的可以去官網(wǎng)了解下

1  Cache<String, String> cache = Caffeine.newBuilder()
2                .build();
3        cache.put("java金融""java金融");
4        System.out.println(cache.getIfPresent("java金融"));

自動(dòng)添加(自定義添加函數(shù))

 1  public static void main(String[] args) {
2        Cache<String, String> cache = Caffeine.newBuilder()
3                .build();
4        // 1.如果緩存中能查到,則直接返回
5        // 2.如果查不到,則從我們自定義的getValue方法獲取數(shù)據(jù),并加入到緩存中
6        String val = cache.get("java金融", k -> getValue(k));
7        System.out.println(val);
8    }
9    /**
10     * 緩存中找不到,則會(huì)進(jìn)入這個(gè)方法。一般是從數(shù)據(jù)庫(kù)獲取內(nèi)容
11     * @param k
12     * @return
13     */

14    private static String getValue(String k) {
15        return k + ":value";
16    }

過期策略

Caffeine 為我們提供了三種過期策略
,分別是基于大?。╯ize-based)、基于時(shí)間(time-based)、基于引用(reference-based)

基于大?。╯ize-based)
 1      LoadingCache<String, String> cache = Caffeine.newBuilder()
2                // 最大容量為1
3                .maximumSize(1)
4                .build(k->getValue(k));
5        cache.put("java金融1","java金融1");
6        cache.put("java金融2","java金融2");
7        cache.put("java金融3","java金融3");
8        cache.cleanUp();
9        System.out.println(cache.getIfPresent("java金融1"));
10        System.out.println(cache.getIfPresent("java金融2"));
11        System.out.println(cache.getIfPresent("java金融3"));

運(yùn)行結(jié)果如下:淘汰了兩個(gè)只剩下一個(gè)。

1null
2null
3java金融3
基于時(shí)間(time-based)

Caffeine提供了三種定時(shí)驅(qū)逐策略:

expireAfterWrite(long, TimeUnit)
  • 在最后一次寫入緩存后開始計(jì)時(shí),在指定的時(shí)間后過期。

 1  LoadingCache<String, String> cache =  Caffeine.newBuilder()
2                // 最大容量為1
3                .maximumSize(1)
4                .expireAfterWrite(3, TimeUnit.SECONDS)
5                .build(k->getValue(k));
6        cache.put("java金融","java金融");
7        Thread.sleep(1*1000);
8        System.out.println(cache.getIfPresent("java金融"));
9        Thread.sleep(1*1000);
10        System.out.println(cache.getIfPresent("java金融"));
11        Thread.sleep(1*1000);
12        System.out.println(cache.getIfPresent("java金融"));

運(yùn)行結(jié)果第三秒的時(shí)候取值為空。

1java金融
2java金融
3null
expireAfterAccess
  • 在最后一次讀或者寫入后開始計(jì)時(shí),在指定的時(shí)間后過期。假如一直有請(qǐng)求訪問該key,那么這個(gè)緩存將一直不會(huì)過期。

 1LoadingCache<String, String> cache =  Caffeine.newBuilder()
2                // 最大容量為1
3                .maximumSize(1)
4                .expireAfterAccess(3, TimeUnit.SECONDS)
5                .build(k->getValue(k));
6        cache.put("java金融","java金融");
7        Thread.sleep(1*1000);
8        System.out.println(cache.getIfPresent("java金融"));
9        Thread.sleep(1*1000);
10        System.out.println(cache.getIfPresent("java金融"));
11        Thread.sleep(1*1000);
12        System.out.println(cache.getIfPresent("java金融"));
13        Thread.sleep(3001);
14        System.out.println(cache.getIfPresent("java金融"));

運(yùn)行結(jié)果:讀和寫都沒有的情況下,3秒后才過期,然后就輸出了null。

1java金融
2java金融
3java金融
4null
expireAfter(Expiry)
  • 在expireAfter中需要自己實(shí)現(xiàn)Expiry接口,這個(gè)接口支持expireAfterCreate,expireAfterUpdate,以及expireAfterRead了之后多久過期。注意這個(gè)是和expireAfterAccess、expireAfterAccess是互斥的。這里和expireAfterAccess、expireAfterAccess不同的是,需要你告訴緩存框架,他應(yīng)該在具體的某個(gè)時(shí)間過期,獲取具體的過期時(shí)間。

 1 LoadingCache<String, String> cache = Caffeine.newBuilder()
2                // 最大容量為1
3                .maximumSize(1)
4                .removalListener((key, value, cause) ->
5                        System.out.println("key:" + key + ",value:" + value + ",刪除原因:" + cause))
6                .expireAfter(new Expiry<String, String>() {
7                    @Override
8                    public long expireAfterCreate(@NonNull String key, @NonNull String value, long currentTime) {
9                        return currentTime;
10                    }
11                    @Override
12                    public long expireAfterUpdate(@NonNull String key, @NonNull String value, long currentTime, @NonNegative long currentDuration) {
13                        return currentTime;
14                    }
15
16                    @Override
17                    public long expireAfterRead(@NonNull String key, @NonNull String value, long currentTime, @NonNegative long currentDuration) {
18                        return currentTime;
19                    }
20                })
21                .build(k -> getValue(k));

刪除

  • 單個(gè)刪除:Cache.invalidate(key)

  • 批量刪除:Cache.invalidateAll(keys)

  • 刪除所有緩存項(xiàng):Cache.invalidateAll

總結(jié)

本文只是對(duì)Caffeine的一個(gè)簡(jiǎn)單使用的介紹,它還有很多不錯(cuò)的東西,比如緩存監(jiān)控、事件監(jiān)聽、W-TinyLFU算法(高命中率、低內(nèi)存占用)感興趣的同學(xué)可以去官網(wǎng)查看。

參考

https://www.itcodemonkey.com/article/9498.html
https://juejin.im/post/5dede1f2518825121f699339
https://www.cnblogs.com/CrankZ/p/10889859.html
https://blog.csdn.net/hy245120020/article/details/78080686

https://www.zhihu.com/question/58735131/answer/307771944


特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:

本地緩存性能之王Caffeine

長(zhǎng)按訂閱更多精彩▼

本地緩存性能之王Caffeine

如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉