各缓存的特性对比

本文仅针对在 Java 开发中,常用的缓存方案进行对比,并整理阅读到的、较有帮助的博文。
本文不对缓存的基本作用、各缓存的使用、部署方式进行说明。

文章后部分给出了 Spring 中,多级缓存的一种实现思路,欢迎参考!

存储方式分布式部署方式特点/适用场景
内存JVM 内存×JDK自带这里指 ConcurrentHashMap。需要手动管理缓存。缓存使用场景较简单的场景。
CaffeineJVM 内存×jar 包采用比 Guava 更优的算法,显著提升读写性能、命中率。据说是新时代的本地缓存,对 Guava API 有良好的支持
GuavaJVM 内存×jar 包由 Google 提供。类似 ConcurrentHashMap 的实现,但提供了更多 API,更灵活的失效、回收策略。
EhcacheJVM 内存+磁盘支持jar 包使用分布式时,支持同步、共享比较麻烦,通常用于单机,单机时性能很好
memcached内存客户端实现独立部署无持久化,值只支持 String,适合频繁读、较少修改的场景,对大 Value 支持友好
redis内存+磁盘支持独立部署对集群方案、分布式部署有完善的支持;对持久化、容灾有完善的方案;性能很优秀,并支持复杂的 KV 类型存储
levelDB存储引擎(内存+磁盘)作为存储引擎提供支持jar 包由 Google 提供。轻量存储引擎,提供缓存操作 API,可以理解为简化的 RocksDB (TiDB 的底层实现),但是仅引入 levelDB 时,不支持分布式

上述缓存均开源,且社区都很活跃

主要参考(重点)

本地缓存的进化

部分缓存的比较

在 Springboot 中,建立并使用多级缓存

这里给出一种设计方案,仅供参考。

也可用作 Spring 自动配置与缓存实现参考

实现效果

通过配置文件调整缓存各层的关系,仅需编写缓存实现部分代码,编写统一的注入方法即可完成自动装配,由 Spring 容器管理多级缓存。

配置文件:

cache:
  layers:
    # 越靠上的越接近 DB,编号越小
    - redis
    - guava

业务(单测)代码:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = XxxApplication.class)
public class MultiStringCacheTest {

    // 这个是最终实现的多级缓存对外接口的 Bean
    // 配置正确后,注入后,直接使用对应接口即可
    @Autowired
    private MultiStringCache multiStringCache;

    @Test
    public void setTest() {
        // 基本的设置、读取接口测试
        String key1 = "key1";
        String val1 = "val1";
        multiStringCache.set(key1, val1);
        Assert.assertEquals(multiStringCache.getCache(key1), val1);
    }
}

设计、原理

image.png

  • 缓存层级设计

    • 由 MultiStringCache 统一管理各级缓存,为方便管理,这里要求每一层缓存都必须是 AbstractStringCacheLayer 的子类
    • CacheLayer 规定了缓存层的基本接口
    • AbstractStringCacheLayer 对 CacheLayer 部分方法进行了简单实现,并提供了针对对象与 Json 互转的方法,拓展了非 String 值类型的支持。
    • RedisCacheLayer, GuavaCacheLayer 是缓存层的具体实现。
  • 配置方式设计

    • 由 MultiCacheProperties 读取配置文件中缓存相关的配置信息
    • 由 MultiCacheConfiguration 对配置进行解释,通过内部类,使用反射调用工厂方法将各层缓存的 Bean 注册到 Spring 容器,最后将 MultiStringCache 的 Bean 注册到容器。
    • CacheLayerBuilder 提供各层缓存构造的工厂方法,根据对应前缀构造指定的缓存层。
  • 使用方法

    1. 复用图中除 RedisCacheLayer, GuavaCacheLayer 的全部类。
    2. 按照业务需要,编写自己的缓存层;缓存层必须继承 AbstractStringCacheLayer 方法。
    3. 按照上文配置文件中描述的方式进行配置。
    4. 在业务代码中直接使用(自动注入),提供的接口可以参考代码,有必要的注释,可以自行拓展。

完整代码样例

注意,该样例中提供的实现属于 demo,仅在单元测试的若干个测试用例中实现了二级缓存的全部特性,仅供参考学习。

样例代码:file-case: 多级缓存实现部分

该项目近期可能会继续更新,如果链接失效,可以留言提醒更新。