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:

  1. 违心耗费一些内存空间来晋升速度。
  2. 预料到某些键会被屡次查问。
  3. 缓存中寄存的数据总量不会超出内存容量。

所以,能够将程序频繁用到的大量数据存储到Guava Cache中,以改善程序性能。

2.3 Guava Cache的refresh和expire刷新机制

看一下三种基于工夫的清理或刷新缓存数据的形式:

  expireAfterAccess: 当缓存项在指定的时间段内没有被读或写就会被回收。

  expireAfterWrite:当缓存项在指定的时间段内没有更新就会被回收。

  refreshAfterWrite:当缓存项上一次更新操作之后的多久会被刷新。

这三种之间的比照能够参考:Guava Cache的刷新机制