SpringBoot:第四篇 集成Guava(本地缓存+分布式缓存)
本地缓存+分布式缓存(redis) 构建二级缓存
(1)解决redis 热key
(2)redis缓存io读写,毫秒级响应,本地缓存响应时间更短,亚秒级;对于响应要求更高的服务
数据读取
数据修改、删除(先删除本地,然后广播其他节点执行删除)
1.引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.3.17.RELEASE</version> </dependency>
2.Guava相关类配置
(1)GuavaCacheConfig
package com.example.demo.config; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.guava.GuavaCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.TimeUnit; /** * @author duanxiaoqiu * @Date 2019-06-15 14:25 **/ @EnableConfigurationProperties(GuavaProperties.class) @Configuration @EnableCaching public class GuavaCacheConfig { @Autowired private GuavaProperties guavaProperties; @Bean public CacheBuilder<Object,Object> cacheBuilder(){ long maximumSize = guavaProperties.getMaximumSize(); long expireAfterWrite = guavaProperties.getExpireAfterWriteDuration(); long expireAfterAccess = guavaProperties.getExpireAfterAccessDuration(); long refreshDuration = guavaProperties.getRefreshDuration(); if(maximumSize <= 0){ maximumSize = 1024; } if(expireAfterAccess <= 0){ expireAfterAccess = 3600; } if(expireAfterWrite <= 0){ expireAfterWrite = 3600; } if(refreshDuration <= 0){ refreshDuration = 1800; } return CacheBuilder.newBuilder().maximumSize(maximumSize) .expireAfterWrite(expireAfterWrite,TimeUnit.SECONDS) .refreshAfterWrite(refreshDuration,TimeUnit.SECONDS); } @Bean(name = "guavaCacheLoader") public CacheLoader cacheLoader(){ return new GuavaCacheLoader(); } @Bean public CacheManager cacheManager(@Qualifier("cacheBuilder")CacheBuilder cacheBuilder, @Qualifier("guavaCacheLoader")CacheLoader cacheLoader){ GuavaCacheManager cacheManager = new GuavaCacheManager(); cacheManager.setCacheBuilder(cacheBuilder); cacheManager.setCacheLoader(cacheLoader); return cacheManager; } }
(2)GuavaCacheLoader
package com.example.demo.config; import com.google.common.cache.CacheLoader; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFutureTask; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author duanxiaoqiu * @Date 2019-06-15 14:34 **/ public class GuavaCacheLoader extends CacheLoader<String,String> { private final ExecutorService executorService = Executors.newFixedThreadPool(4); @Override public String load(String s) throws Exception { if (s.equals("hello")) { Thread.sleep(3000); return "world"; } else if (s.equals("world")) { Thread.sleep(5000); return "hello"; } return "no value"; } @Override public ListenableFuture<String> reload(String key, String oldValue) throws Exception { ListenableFutureTask<String> task = ListenableFutureTask.create(new Callable<String>() { @Override public String call() throws Exception { if (key.equals("hello")) { return "nihao"; } else if (key.equals("world")) { return "shijie"; } return "no value"; } }); executorService.submit(task); return task; } }
(3)GuavaProperties
package com.example.demo.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; /** * @author duanxiaoqiu * @Date 2019-06-15 14:24 **/ @Configuration @PropertySource("classpath:guava.properties") @ConfigurationProperties(prefix = "guava.cache.config") public class GuavaProperties { private long maximumSize; private long maximumWeight; private long expireAfterWriteDuration; private long expireAfterAccessDuration; private long refreshDuration; private int initialCapacity; private int concurrencyLevel; public long getMaximumSize() { return maximumSize; } public void setMaximumSize(long maximumSize) { this.maximumSize = maximumSize; } public long getMaximumWeight() { return maximumWeight; } public void setMaximumWeight(long maximumWeight) { this.maximumWeight = maximumWeight; } public long getExpireAfterWriteDuration() { return expireAfterWriteDuration; } public void setExpireAfterWriteDuration(long expireAfterWriteDuration) { this.expireAfterWriteDuration = expireAfterWriteDuration; } public long getExpireAfterAccessDuration() { return expireAfterAccessDuration; } public void setExpireAfterAccessDuration(long expireAfterAccessDuration) { this.expireAfterAccessDuration = expireAfterAccessDuration; } public long getRefreshDuration() { return refreshDuration; } public void setRefreshDuration(long refreshDuration) { this.refreshDuration = refreshDuration; } public int getInitialCapacity() { return initialCapacity; } public void setInitialCapacity(int initialCapacity) { this.initialCapacity = initialCapacity; } public int getConcurrencyLevel() { return concurrencyLevel; } public void setConcurrencyLevel(int concurrencyLevel) { this.concurrencyLevel = concurrencyLevel; } }
3.配置文件-- guava.properties
guava.cache.config.expire-after-write-duration=20 #更新间隔时长 guava.cache.config.refresh-duration=10 guava.cache.config.maximumSize=1024
4.使用
package com.example.demo.controller; /** * @author duanxiaoqiu * @Date 2019-06-14 15:05 **/ import com.example.demo.dao.StudentDao; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Slf4j @Controller @RequestMapping("/") public class TestController { @Autowired private StudentDao studentDao; @Autowired private CacheManager cacheManager; @RequestMapping("/") @ResponseBody public String index() { log.info(cacheManager.getCache("hello").getName()); log.info("++++"); return studentDao.getStuById(1).getName() + "hello world"; } }
注:提示idea Spring Boot configuration not found in classpath
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
参考文章:
https://toutiao.io/posts/56yqwd/preview