程序员子龙(Java面试 + Java学习) 程序员子龙(Java面试 + Java学习)
首页
学习指南
工具
开源项目
技术书籍

程序员子龙

Java 开发从业者
首页
学习指南
工具
开源项目
技术书籍
  • 基础

  • JVM

  • Spring

  • 并发编程

  • Mybatis

  • 网络编程

  • 数据库

  • 缓存

    • Redis

    • 本地缓存

      • Java 的高性能缓存库-caffeine!
      • 阿里开源的缓存框架JetCache
      • Java本地缓存技术选型(Guava Cache、Caffeine、EhCache)
    • 设计模式

    • 分布式

    • 高并发

    • SpringBoot

    • SpringCloudAlibaba

    • Nginx

    • 面试

    • 生产问题

    • 系统设计

    • 消息中间件

    • Java
    • 缓存
    • 本地缓存
    程序员子龙
    2024-04-22
    目录

    Java本地缓存技术选型(Guava Cache、Caffeine、EhCache)

    # 前言

    对一个java开发者而言,提到缓存,第一反应就是Redis。利用这类缓存足以解决大多数的性能问题了,我们也要知道,这种属于remote cache(分布式缓存),应用的进程和缓存的进程通常分布在不同的服务器上,不同进程之间通过RPC或HTTP的方式通信。这种缓存的优点是缓存和应用服务解耦,支持大数据量的存储,缺点是数据要经过网络传输,性能上会有一定损耗。

    与分布式缓存对应的是本地缓存,缓存的进程和应用进程是同一个,数据的读写都在一个进程内完成,这种方式的优点是没有网络开销,访问速度很快。缺点是受JVM内存的限制,不适合存放大数据。

    # 本地缓存常用技术

    本地缓存和应用同属于一个进程,使用不当会影响服务稳定性,所以通常需要考虑更多的因素,例如容量限制、过期策略、淘汰策略、自动刷新等。常用的本地缓存方案有:

    • Guava Cache
    • Caffeine
    • EhCache

    # 基于Guava Cache实现本地缓存

    Guava是Google团队开源的一款 Java 核心增强库,包含集合、并发原语、缓存、IO、反射等工具箱,性能和稳定性上都有保障,应用十分广泛。Guava Cache支持很多特性:

    • 支持最大容量限制
    • 支持两种过期删除策略(插入时间和访问时间)
    • 支持简单的统计功能
    • 基于LRU算法实现

    引入依赖

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>18.0</version>
    </dependency>
    
    
    1
    2
    3
    4
    5
    6

    简单的示例:

    public class GuavaCacheTest {
    
        public static void main(String[] args) throws Exception {
            //创建guava cache
            Cache<String, String> loadingCache = CacheBuilder.newBuilder()
                    //cache的初始容量
                    .initialCapacity(5)
                    //cache最大缓存数
                    .maximumSize(10)
                    //设置写缓存后n秒钟过期
                    .expireAfterWrite(17, TimeUnit.SECONDS)
                    //设置读写缓存后n秒钟过期,实际很少用到,类似于expireAfterWrite
                    //.expireAfterAccess(17, TimeUnit.SECONDS)
                    .build();
            String key = "key";
            // 往缓存写数据
            loadingCache.put(key, "v");
    
            // 获取value的值,如果key不存在,调用collable方法获取value值加载到key中再返回
            String value = loadingCache.get(key, new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return getValueFromDB(key);
                }
            });
    
            // 删除key
            loadingCache.invalidate(key);
        }
    
        private static String getValueFromDB(String key) {
            return "v";
        }
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35

    # Caffeine

    Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 Spring5 (Springboot 2.x) 后,Spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件。

    <dependency>
        <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
        <version>2.5.5</version>
    </dependency>
    
    
    1
    2
    3
    4
    5
    6

    使用Caffeine:

    public class CaffeineCacheTest {
    
        public static void main(String[] args) throws Exception {
            //创建guava cache
            Cache<String, String> loadingCache = Caffeine.newBuilder()
                    //cache的初始容量
                    .initialCapacity(5)
                    //cache最大缓存数
                    .maximumSize(10)
                    //设置写缓存后n秒钟过期
                    .expireAfterWrite(17, TimeUnit.SECONDS)
                    //设置读写缓存后n秒钟过期,实际很少用到,类似于expireAfterWrite
                    //.expireAfterAccess(17, TimeUnit.SECONDS)
                    .build();
            String key = "key";
            // 往缓存写数据
            loadingCache.put(key, "v");
    
            // 获取value的值,如果key不存在,获取value后再返回
            String value = loadingCache.get(key, CaffeineCacheTest::getValueFromDB);
    
            // 删除key
            loadingCache.invalidate(key);
        }
    
        private static String getValueFromDB(String key) {
            return "v";
        }
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

    相比Guava Cache来说,Caffeine无论从功能上和性能上都有明显优势。同时两者的API类似,使用Guava Cache的代码很容易可以切换到Caffeine,节省迁移成本。

    # EhCache

    EhCache是一个纯Java的进程内缓存框架,具有快速、精干的特点。注意的这里的关键字进程,基于进程的缓存直觉告诉我们效率肯定要高一些,因为它直接在进程之内进行操作,但不同应用之间缓存的共享可能就会有问题。

    EhCache是Hibernate中默认的CacheProvider,Spring Boot也对其进行了支持,Spring中提供的缓存抽象也支持对EhCache缓存框架的绑定,而且支持基于注解的方式来使用。因此,EhCache是一款被广泛使用的基于Java的高速缓存框架,使用起来也非常方便。

    EhCache提供了多种缓存策略,主要分为内存和磁盘两级,是一款面向通用缓存、Java EE和轻量级容器的缓存框架。

    <dependency>
        <groupId>org.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>3.8.0</version>
    </dependency>
    
    
    1
    2
    3
    4
    5
    6

    使用EhCache

    public class EncacheTest {
    
        public static void main(String[] args) throws Exception {
            // 声明一个cacheBuilder
            CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                    .withCache("encacheInstance", CacheConfigurationBuilder
                            //声明一个容量为20的堆内缓存
                            .newCacheConfigurationBuilder(String.class,String.class, ResourcePoolsBuilder.heap(20)))
                    .build(true);
            // 获取Cache实例
            Cache<String,String> myCache =  cacheManager.getCache("encacheInstance", String.class, String.class);
            // 写缓存
            myCache.put("key","v");
            // 读缓存
            String value = myCache.get("key");
            // 移除换粗
            cacheManager.removeCache("myCache");
            cacheManager.close();
        }
    }
    
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    # 总结

    • 从易用性角度,Guava Cache、Caffeine和EhCache都有十分成熟的接入方案,使用简单。
    • 从功能性角度,Guava Cache和Caffeine功能类似,都是只支持堆内缓存,Encache相比功能更为丰富
    • 从性能上进行比较,Caffeine最优、GuavaCache次之,EhCache最差(下图是三者的性能对比结果)

    总体来说,对于本地缓存的方案中,个人比较推荐Caffeine,性能上遥遥领先。真实的业务工程中,建议使用Caffeine作为本地缓存,另外使用Redis或者memcache作为分布式缓存,构造多级缓存体系,保证性能和可靠性。

    上次更新: 2024/04/28, 07:59:12
    阿里开源的缓存框架JetCache
    单例模式

    ← 阿里开源的缓存框架JetCache 单例模式→

    最近更新
    01
    一个注解,优雅的实现接口幂等性
    11-17
    02
    MySQL事务(超详细!!!)
    10-14
    03
    阿里二面:Kafka中如何保证消息的顺序性?这周被问到两次了
    10-09
    更多文章>
    Theme by Vdoing | Copyright © 2024-2024

        辽ICP备2023001503号-2

    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式