java使用guava cache实现本地缓存

原创 2021-02-04 15:39 阅读(4695)次

在高并发的场景中我们不希望所有请求都打到数据库中,以免压垮数据库,这时我们就可能会使用本地缓存来实现解决并发性能问题,当然我们也可以选择redis来实现,但redis有时并发也并没有那么快。于是本地缓存就是我们的唯一救命手段了。

Guava的cache是线程安全的,是本地缓存的不二之选,默认情况下缓存过期是依赖于访问判断时间过期和数量限制过期。
我们再也不用自己手写一个基于ConcurrentHashMap的本地缓存了

maven引入guava包

  1. <!-- 本地缓存-->
  2. <dependency>
  3. <groupId>com.google.guava</groupId>
  4. <artifactId>guava</artifactId>
  5. <version>18.0</version>
  6. </dependency>

两种缓存方式

guava的缓存提供两种方式:

1. 一种是在创建缓存时就提供加载缓存的方法load,在调用缓存时不用关注缓存数据从哪来,cache过期时会自动调用load去数据库或其他组件刷新缓存并返回给调用者。
2. 还有一种就是缓存失效后数据需要调用者手动更新缓存。

这两种方式大家可以根据场景去选择。

下面我提供一下我的代码示例,我的需求是要取缓存中的车牌,判断车辆是否存在缓存中,存在就不入库了。

自动加载缓存方式

代码示例:

  1. import com.google.common.cache.CacheBuilder;
  2. import com.google.common.cache.CacheLoader;
  3. import com.google.common.cache.LoadingCache;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import org.springframework.stereotype.Component;
  7. import java.util.concurrent.TimeUnit;
  8. @Component
  9. public class VehicleNumCacheOnLoad {
  10. private static Logger logger = LoggerFactory.getLogger(VehicleNumCacheOnLoad.class);
  11. private final Integer existFlag = new Integer(1);
  12. private LoadingCache<String,Integer> cache = CacheBuilder.newBuilder()
  13. .recordStats()
  14. .maximumSize(5000000)
  15. .expireAfterWrite(1, TimeUnit.MINUTES)
  16. .build(
  17. new CacheLoader<String, Integer>() {
  18. @Override
  19. public Integer load(String key) throws Exception {
  20. //伪代码:
  21. //查询数据库并返回existFlag
  22. //return existFlag;
  23. //数据库中查询不到,返回null
  24. return null;
  25. }
  26. }
  27. );
  28. }

手动加载缓存方式

代码示例:

  1. import com.google.common.cache.Cache;
  2. import com.google.common.cache.CacheBuilder;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.stereotype.Component;
  6. import java.util.concurrent.TimeUnit;
  7. @Component
  8. public class VehicleNumCache {
  9. private static Logger logger = LoggerFactory.getLogger(VehicleNumCache.class);
  10. private final Integer existFlag = new Integer(1);
  11. private Cache<String,Integer> cache = CacheBuilder.newBuilder()
  12. .recordStats()
  13. .maximumSize(5000000)
  14. .expireAfterWrite(1, TimeUnit.MINUTES)
  15. .build();
  16. /**
  17. * 返回是否存在车辆,非null为存在
  18. * @param vehicleNum
  19. * @return
  20. */
  21. public Integer get(String vehicleNum){
  22. logger.info(cache.stats().toString());
  23. return cache.getIfPresent(vehicleNum);
  24. }
  25. /**
  26. * 返回是否存在车辆,非null为存在
  27. * @param vehicleNum
  28. * @return
  29. */
  30. public void put(String vehicleNum){
  31. cache.put(vehicleNum,existFlag);
  32. }
  33. }

如何调用

代码示例:

  1. Integer flag = vehicleNumCache.get(vehicleNum);
  2. //缓存不存在
  3. if(flag == null){
  4. filterVehicleList.add(v);
  5. }

调用前记得注入缓存类vehicleNumCache