SpringBoot:第五篇 集成Guava(本地缓存+分布式缓存)

简介: SpringBoot:第五篇 集成Guava(本地缓存+分布式缓存)

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

https://tech.youzan.com/tmc/


相关文章
|
7天前
|
消息中间件 Java Apache
SpringBoot集成RocketMq
RocketMQ 是一款开源的分布式消息中间件,采用纯 Java 编写,支持事务消息、顺序消息、批量消息、定时消息及消息回溯等功能。其优势包括去除对 ZooKeeper 的依赖、支持异步和同步刷盘、高吞吐量及消息过滤等特性。RocketMQ 具备高可用性和高可靠性,适用于大规模分布式系统,能有效保障消息传输的一致性和顺序性。
401 2
|
13天前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
7天前
|
缓存 NoSQL 关系型数据库
Redis缓存和分布式锁
Redis 是一种高性能的键值存储系统,广泛用于缓存、消息队列和内存数据库。其典型应用包括缓解关系型数据库压力,通过缓存热点数据提高查询效率,支持高并发访问。此外,Redis 还可用于实现分布式锁,解决分布式系统中的资源竞争问题。文章还探讨了缓存的更新策略、缓存穿透与雪崩的解决方案,以及 Redlock 算法等关键技术。
|
3月前
|
前端开发
SpringBoot2.3.1集成Knife4j接口文档
SpringBoot2.3.1集成Knife4j接口文档
449 44
|
2月前
|
缓存 JSON 前端开发
第07课:Spring Boot集成Thymeleaf模板引擎
第07课:Spring Boot集成Thymeleaf模板引擎
383 0
第07课:Spring Boot集成Thymeleaf模板引擎
|
2月前
|
Java 关系型数据库 MySQL
springboot项目集成dolphinscheduler调度器 实现datax数据同步任务
springboot项目集成dolphinscheduler调度器 实现datax数据同步任务
336 2
|
2月前
|
分布式计算 Java 大数据
springboot项目集成dolphinscheduler调度器 可拖拽spark任务管理
springboot项目集成dolphinscheduler调度器 可拖拽spark任务管理
151 2
|
2月前
|
存储 人工智能 Java
Springboot集成AI Springboot3 集成阿里云百炼大模型CosyVoice2 实现Ai克隆语音(未持久化存储)
本项目基于Spring Boot 3.5.3与Java 17,集成阿里云百炼大模型CosyVoice2实现音色克隆与语音合成。内容涵盖项目搭建、音色创建、音频合成、音色管理等功能,适用于希望快速掌握Spring Boot集成语音AI技术的开发者。需提前注册阿里云并获取API Key。
|
4月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
7天前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
64 1
Redis专题-实战篇二-商户查询缓存