各缓存的特性对比
本文仅针对在 Java 开发中,常用的缓存方案进行对比,并整理阅读到的、较有帮助的博文。
本文不对缓存的基本作用、各缓存的使用、部署方式进行说明。
文章后部分给出了 Spring 中,多级缓存的一种实现思路,欢迎参考!
| 存储方式 | 分布式 | 部署方式 | 特点/适用场景 | |
|---|---|---|---|---|
| 内存 | JVM 内存 | × | JDK自带 | 这里指 ConcurrentHashMap。需要手动管理缓存。缓存使用场景较简单的场景。 | 
| Caffeine | JVM 内存 | × | jar 包 | 采用比 Guava 更优的算法,显著提升读写性能、命中率。据说是新时代的本地缓存,对 Guava API 有良好的支持 | 
| Guava | JVM 内存 | × | jar 包 | 由 Google 提供。类似 ConcurrentHashMap 的实现,但提供了更多 API,更灵活的失效、回收策略。 | 
| Ehcache | JVM 内存+磁盘 | 支持 | jar 包 | 使用分布式时,支持同步、共享比较麻烦,通常用于单机,单机时性能很好 | 
| memcached | 内存 | 客户端实现 | 独立部署 | 无持久化,值只支持 String,适合频繁读、较少修改的场景,对大 Value 支持友好 | 
| redis | 内存+磁盘 | 支持 | 独立部署 | 对集群方案、分布式部署有完善的支持;对持久化、容灾有完善的方案;性能很优秀,并支持复杂的 KV 类型存储 | 
| levelDB | 存储引擎(内存+磁盘) | 作为存储引擎提供支持 | jar 包 | 由 Google 提供。轻量存储引擎,提供缓存操作 API,可以理解为简化的 RocksDB (TiDB 的底层实现),但是仅引入 levelDB 时,不支持分布式 | 
上述缓存均开源,且社区都很活跃
主要参考(重点)
本地缓存的进化
部分缓存的比较
- Caffeine高性能设计剖析
 - 缓存那些事:介绍了几种常见缓存的使用场景。
 - memcached 的分布式缓存介绍了 memcached 如何实现分布式缓存,一致性算法。
 - 既生 Redis 何生 LevelDB ?主要讲解了 Redis 的痛点,LevelDB 提出的解决,以及 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);
    }
}
设计、原理

- 
缓存层级设计
- 由 MultiStringCache 统一管理各级缓存,为方便管理,这里要求每一层缓存都必须是 AbstractStringCacheLayer 的子类
 - CacheLayer 规定了缓存层的基本接口
 - AbstractStringCacheLayer 对 CacheLayer 部分方法进行了简单实现,并提供了针对对象与 Json 互转的方法,拓展了非 String 值类型的支持。
 - RedisCacheLayer, GuavaCacheLayer 是缓存层的具体实现。
 
 - 
配置方式设计
- 由 MultiCacheProperties 读取配置文件中缓存相关的配置信息
 - 由 MultiCacheConfiguration 对配置进行解释,通过内部类,使用反射调用工厂方法将各层缓存的 Bean 注册到 Spring 容器,最后将 MultiStringCache 的 Bean 注册到容器。
 - CacheLayerBuilder 提供各层缓存构造的工厂方法,根据对应前缀构造指定的缓存层。
 
 - 
使用方法
- 复用图中除 RedisCacheLayer, GuavaCacheLayer 的全部类。
 - 按照业务需要,编写自己的缓存层;缓存层必须继承 AbstractStringCacheLayer 方法。
 - 按照上文配置文件中描述的方式进行配置。
 - 在业务代码中直接使用(自动注入),提供的接口可以参考代码,有必要的注释,可以自行拓展。
 
 
完整代码样例
注意,该样例中提供的实现属于 demo,仅在单元测试的若干个测试用例中实现了二级缓存的全部特性,仅供参考学习。
样例代码:file-case: 多级缓存实现部分
该项目近期可能会继续更新,如果链接失效,可以留言提醒更新。