1.背景
缓存的次要作用是临时在内存中保留业务零碎的数据处理后果,并且期待下次访问应用。在日长开发有很多场合,有一些数据量不是很大,不会常常改变,并且拜访十分频繁。然而因为受限于硬盘IO的性能或者近程网络等起因获取可能十分的费时。会导致咱们的程序十分迟缓,这在某些业务上是不能忍的!而缓存正是解决这类问题的神器!
缓存在很多零碎和架构中都用宽泛的利用,例如:
- CPU缓存
- 操作系统缓存
- HTTP缓存
- 数据库缓存
- 动态文件缓存
- 本地缓存
- 分布式缓存
能够说在计算机和网络畛域,缓存是无处不在的。能够这么说,只有有硬件性能不对等,波及到网络传输的中央都会有缓存的身影。
缓存总体可分为两种 集中式缓存 和 分布式缓存
“集中式缓存"与"分布式缓存"的区别其实就在于“集中”与"非集中"的概念,其对象可能是服务器、内存条、硬盘等。
2.Guava Cache
Google的guava是个很好的我的项目,提供了诸如汇合、缓存、并发、String工具类等等,实乃Java开发利器。这里说一下LoadingCache应用的应用。
2.1简略应用
应用Cache时,咱们优先读取缓存,当缓存不存在时,则从理论的数据存储获取,如DB、磁盘、网络等,即get-if-absent-compute。guava提供了CacheLoader机制,容许咱们通过设置Loader来主动实现这一过程。如:
Cache<String, User> cache = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES);user = cache.get(name, () -> { User value = query(key);//from databse, disk, etc. return value;});
或者应用LoadingCache:
LoadingCache<String, User> cache = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build( new CacheLoader<String, User>() { @Override public User load(String name) throws Exception { User value = query(key);//from databse, disk, etc. return value; } });
这可比本人写一个Map来缓存数据不便多了,而且还能够设置超时工夫主动帮咱们清理过期的数据。
不过须要留神一点的是,CacheLoader不容许返回的数据为NULL,否则会抛出异样:CacheLoader returned null for key
。所以咱们须要保障查找的数据必须存在,或者抛出异样内部解决。在某些状况下,咱们的数据可能的确不在,比方用户治理模块,咱们在新增数据前,要查问原来是否曾经存在该用户,那么这时候抛出异样也不适合,此时能够应用Optional来优化CacheLoader:
LoadingCache<String, Optional<User>> cache = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build( new CacheLoader<String, Optional<User>>() { @Override public Optional<User> load(String name) throws Exception { User value = query(key);//from databse, disk, etc. return Optional.ofNullable(value); } });
这样咱们保障了CacheLoader返回值不为NULL,而业务数据是否存在,只须要判断Optional.ifPresent()就行了,同时Optional的其余函数在业务逻辑中也是十分有用的。
2.2 和Map比拟
Guava Cache与ConcurrentMap很类似,但也不齐全一样。最根本的区别是ConcurrentMap会始终保留所有增加的元素,直到显式地移除。绝对地,Guava Cache为了限度内存占用,通常都设定为主动回收元素。在某些场景下,只管LoadingCache 不回收元素,它也是很有用的,因为它会主动加载缓存。
Guava Cache是在内存中缓存数据,相比拟于数据库或redis存储,拜访内存中的数据会更加高效。Guava官网介绍,上面的这几种状况能够思考应用Guava Cache:
- 违心耗费一些内存空间来晋升速度。
- 预料到某些键会被屡次查问。
- 缓存中寄存的数据总量不会超出内存容量。
所以,能够将程序频繁用到的大量数据存储到Guava Cache中,以改善程序性能。
2.3 Guava Cache的refresh和expire刷新机制
看一下三种基于工夫的清理或刷新缓存数据的形式:
expireAfterAccess: 当缓存项在指定的时间段内没有被读或写就会被回收。
expireAfterWrite:当缓存项在指定的时间段内没有更新就会被回收。
refreshAfterWrite:当缓存项上一次更新操作之后的多久会被刷新。
这三种之间的比照能够参考:Guava Cache的刷新机制