Caffeine Cache 简介 和 Google Guava EhCache 性能比较

释放双眼,带上耳机,听听看~!

1. 前言

互联网软件神速发展,用户的体验度是判断一个软件好坏的重要原因,所以缓存就是必不可少的一个神器。在多线程高并发场景中往往是离不开cache的,需要根据不同的应用场景来需要选择不同的cache,比如分布式缓存如redis、memcached,还有本地(进程内)缓存如ehcache、GuavaCache、Caffeine。

说起Guava Cache,很多人都不会陌生,它是Google Guava工具包中的一个非常方便易用的本地化缓存实现,基于LRU算法实现,支持多种缓存过期策略。由于Guava的大量使用,Guava Cache也得到了大量的应用。但是,Guava Cache的性能一定是最好的吗?也许,曾经,它的性能是非常不错的。但所谓长江后浪推前浪,总会有更加优秀的技术出现。今天,我就来介绍一个比Guava Cache性能更高的缓存框架:Caffeine。

2. 比较

Google Guava工具包中的一个非常方便易用的本地化缓存实现,基于LRU算法实现,支持多种缓存过期策略。

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。

Caffeine是使用Java8对Guava缓存的重写版本,在Spring Boot 2.0中将取代,基于LRU算法实现,支持多种缓存过期策略。

2.1 官方性能比较

场景1:8个线程读,100%的读操作

Caffeine Cache  简介 和  Google Guava  EhCache 性能比较

场景二:6个线程读,2个线程写,也就是75%的读操作,25%的写操作

Caffeine Cache  简介 和  Google Guava  EhCache 性能比较

 

场景三:8个线程写,100%的写操作

Caffeine Cache  简介 和  Google Guava  EhCache 性能比较

可以清楚的看到Caffeine效率明显的高于其他缓存。

3. 如何使用

3.1手动加载(Manual)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1public static void main(String[] args) {
2        Cache<String, String> manualCache = Caffeine.newBuilder()
3                .expireAfterWrite(10, TimeUnit.MILLISECONDS)   //设置过期时间
4                .maximumSize(100)    //设置最大缓存个数
5                .build();
6        String key = "name";
7        // 根据key查询一个缓存,如果没有返回NULL
8        String value = manualCache.getIfPresent(key);
9        System.out.println("key "+ value);    //key null
10        // 将一个值放入缓存,如果以前有值就覆盖以前的值
11        manualCache.put(key,"reed");
12        String value1 = manualCache.getIfPresent(key);
13        System.out.println("key1 "+value1);   //key1 reed
14        // 删除一个缓存
15        manualCache.invalidate(key);
16        String value2 = manualCache.getIfPresent(key);
17        System.out.println("key2 "+value2);    //key2 null
18        // 根据Key查询一个缓存,如果没有调用createExpensiveGraph方法,并将返回值保存到缓存。
19        String value3 =manualCache.get(key,k->"fan");
20        System.out.println("key3 "+value3);    //key3 fan
21        String value4 = manualCache.get(key,k->"reed");
22        System.out.println("key4 "+value4);    //key4 fan
23    }
24

3.2同步加载(Loading)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1@Test
2    public void test(){
3        LoadingCache<String, String> loadingCache = Caffeine.newBuilder()
4                .maximumSize(10_000)
5                .expireAfterWrite(10, TimeUnit.MINUTES)
6                .build(key -> getName(key));
7
8        List<String> keys = new ArrayList<>();
9        keys.add("reed");
10        keys.add("fan");
11
12        Map<String,String> map = loadingCache.getAll(keys);
13
14        for(Map.Entry<String,String> m:map.entrySet()){
15            System.out.println("key:" + m.getKey() + " value:" + m.getValue());
16            /*key:reed value:reed
17            key:fan value:fan*/
18        }
19    }
20    private String getName(String str){
21        return str;
22    }
23

3.3异步加载(Asynchronously Loading)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1@Test
2    public void test() throws Exception {
3        AsyncLoadingCache<String, String> asyncLoadingCache = Caffeine.newBuilder()
4                .maximumSize(10_000)
5                .expireAfterWrite(10, TimeUnit.MINUTES)
6                .buildAsync(key -> getName(key));
7
8        List<String> keys = new ArrayList<>();
9        keys.add("reed");
10        keys.add("fan");
11        CompletableFuture<Map<String, String>> names = asyncLoadingCache.getAll(keys);
12        Map<String, String> map = names.get();
13
14        for (Map.Entry<String, String> m : map.entrySet()) {
15            System.out.println("key:" + m.getKey() + " value:" + m.getValue());
16            /*key:reed value:reed
17            key:fan value:fan*/
18        }
19    }
20
21    private String getName(String str) {
22        return str;
23    }
24

 

给TA打赏
共{{data.count}}人
人已打赏
安全技术

Bootstrap 4 Flex(弹性)布局

2021-12-21 16:36:11

安全技术

从零搭建自己的SpringBoot后台框架(二十三)

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索