java缓存——(一)服务器本地缓存ehcache、guava cache和Caffeine
在多线程高并发场景中往往是离不开cache的,需要根据不同的应用场景来需要选择不同的cache,比如分布式缓存如redis、memcached,还有本地(进程内)缓存如ehcache、GuavaCache、Caffeine、LocalCache等。
一、ehcache
在Java项目广泛的使用。它是一个开源的、设计于提高在数据从RDBMS中取出来的高花费、高延迟采取的一种缓存方案。正因为Ehcache具有健壮性(基于java开发)、被认证(具有apache 2.0 license)、充满特色(稍后会详细介绍),所以被用于大型复杂分布式web application的各个节点中。
什么特色?
1. 够快
Ehcache的发行有一段时长了,经过几年的努力和不计其数的性能测试,Ehcache终被设计于large, high concurrency systems.
2. 够简单
开发者提供的接口非常简单明了,从Ehcache的搭建到运用运行仅仅需要的是你宝贵的几分钟。其实很多开发者都不知道自己用在用Ehcache,Ehcache被广泛的运用于其他的开源项目
比如:hibernate
3.够袖珍
关于这点的特性,官方给了一个很可爱的名字small foot print ,一般Ehcache的发布版本不会到2M,V 2.2.3 才 668KB。
4. 够轻量
核心程序仅仅依赖slf4j这一个包,没有之一!
5.好扩展
Ehcache提供了对大数据的内存和硬盘的存储,最近版本允许多实例、保存对象高灵活性、提供LRU、LFU、FIFO淘汰算法,基础属性支持热配置、支持的插件多
6.监听器
缓存管理器监听器 (CacheManagerListener)和 缓存监听器(CacheEvenListener),做一些统计或数据一致性广播挺好用的
二、guava cache
先说说一般的cache都会实现的基础功能包括:
提供一个存储缓存的容器,该容器实现了存放(Put)和读取(Get)缓存的接口供外部调用。 缓存通常以<key,value>的形式存在,通过key来从缓存中获取value。当然容器的大小往往是有限的(受限于内存大小),需要为它设置清除缓存的策略。
在GuavaCache中缓存的容器被定义为接口Cache<K, V>的实现类,这些实现类都是线程安全的,因此通常定义为一个单例。并且接口Cache是泛型,很好的支持了不同类型的key和value。作为示例,我们构建一个key为Integer、value为String的Cache实例:
final static Cache<Integer, String> cache = CacheBuilder.newBuilder() //设置cache的初始大小为10,要合理设置该值 .initialCapacity(10) //设置并发数为5,即同一时间最多只能有5个线程往cache执行写入操作 .concurrencyLevel(5) //设置cache中的数据在写入之后的存活时间为10秒 .expireAfterWrite(10, TimeUnit.SECONDS) //构建cache实例 .build();
据说GuavaCache的实现是基于ConcurrentHashMap的,因此上面的构造过程所调用的方法,通过查看其官方文档也能看到一些类似的原理。比如通过initialCapacity(5)定义初始值大小,要是定义太大就好浪费内存空间,要是太小,需要扩容的时候就会像map一样需要resize,这个过程会产生大量需要gc的对象,还有比如通过concurrencyLevel(5)来限制写入操作的并发数,这和ConcurrentHashMap的锁机制也是类似的(ConcurrentHashMap读不需要加锁,写入需要加锁,每个segment都有一个锁)。
三、Caffeine
Caffeine是使用Java8对Guava缓存的重写版本,在Spring 5.0或者Spring Boot 2.0中将取代,基于LRU算法实现,支持多种缓存过期策略。
那么为什么这么好的东西需要被淘汰呢,如果对于本地Cache有过深入研究的人应该知道LRU算法基本可以满足大部分的场景,但是很多人为了精益求精,基于LRU的算法,又在此基础上提出了一系列更好的,更有效果的淘汰策略。比如有ARC,LIRS和W-TinyLFU等都提供了接近最理想的命中率,他们这些算法进一步提高了本地缓存的效率。
Cache的目的就是缓存,如果在功能一样的情况下,最重要的突破就是性能了。从功能上来看GuavaCache已经比较完善了,基本满足了绝大部分本地缓存的需求。那么Spring5使用Caffeine来代替GuavaCache就是因为性能的问题了。
Caffeine的API的操作功能和Guava是基本保持一致的,并且Caffeine为了兼容之前是Guava的用户,做了一个Guava的Adapter给大家使用也是十分的贴心。
当然Caffeine的调整不只有算法上面的调整,还有内存方面的优化以及一些实用的方法没有覆盖到。不过相信仅仅是上面提到的新特点就会让人们有心动的想法去尝试。