使用开源项目xxl-cache构建多级缓存

xxl-cache简介

官网地址:https://www.xuxueli.com/xxl-cache/

概述

XXL-CACHE 是一个 多级缓存框架,高效组合本地缓存和分布式缓存(Redis+Caffeine),支持"多级缓存、一致性保障、TTL、Category隔离、防穿透"等能力;拥有"高性能、高扩展、灵活易用"等特性,提供高性能多级缓存解决方案;

特性

1、灵活易用: 接入灵活方便,一分钟上手;

2、多级缓存:高效组合本地缓存和分布式缓存(Redis+Caffeine),支持L1、L2级别缓存,支持多场景缓存诉求;

3、高扩展:框架进行模块化抽象设计,本地缓存、分布式缓存以及序列化方案均支持自定义扩展;

4、高性能:底层设计L1(Local)+L2(Remote)多级缓存模型,除分布式缓存之外前置在应用层设置本地缓存,高热查询前置本地处理避免远程通讯,最大化提升性能;

5、一致性保障:支持多层级、集群多节点之间缓存数据一致性保障,借助广播消息(Redis Pub/Sub)以及客户端主动过期,实现L1及L2之间以及L1各集群节点间缓存数据一致性同步;

6、TTL:支持TTL,支持缓存数据主动过期及清理;

7、Category隔离:支持自定义缓存Category分类,缓存数据存储隔离;

8、缓存风险治理:针对典型缓存风险,如缓存穿透,底层进行针对性设计进行风险防护;

9、透明接入:支持业务透明接入,屏蔽底层实现细节,降低业务开发成本,以及学习认知成本;

10、多序列化协议支持:组件化抽象Serializer,可灵活扩展更多序列化协议;如 JDK、HESSIAN2、JSON、PROTOSTUFF、KRYO 等;

架构图

实际应用

下面通过一个小demo来初步了解xxl-cache的使用方法

环境

jdk:17

springboot:3.4.2

redis:7.4.1

依赖

xml 复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-cache-core</artifactId>
            <version>1.2.0</version>
        </dependency>
    </dependencies>

整体结构

创建配置文件

application.properties

xml 复制代码
# xxl-cache
## L1缓存(本地)提供者,默认 caffeine
xxl.cache.l1.provider=caffeine
## L1缓存最大容量,默认10000;
xxl.cache.l1.maxSize=-1
## L1缓存过期时间,单位秒,默认10min;
xxl.cache.l1.expireAfterWrite=-1
## L2缓存(分布式)提供者,默认 redis
xxl.cache.l2.provider=redis
## L2缓存序列化方式,默认 java
xxl.cache.l2.serializer=java
## L2缓存节点配置,多个节点用逗号分隔;示例 "127.0.0.1:6379,127.0.0.1:6380"
xxl.cache.l2.nodes=127.0.0.1:6379
## L2缓存用户名配置
xxl.cache.l2.user=
## L2缓存密码配置
xxl.cache.l2.password=

XxlCacheConf.java

java 复制代码
@Configuration
public class XxlCacheConf {

    @Value("${xxl.cache.l1.provider}")
    private String l1Provider;
    @Value("${xxl.cache.l1.maxSize}")
    private int maxSize;
    @Value("${xxl.cache.l1.expireAfterWrite}")
    private long expireAfterWrite;
    @Value("${xxl.cache.l2.provider}")
    private String l2Provider;
    @Value("${xxl.cache.l2.serializer}")
    private String serializer;
    @Value("${xxl.cache.l2.nodes}")
    private String nodes;
    @Value("${xxl.cache.l2.user}")
    private String user;
    @Value("${xxl.cache.l2.password}")
    private String password;

    @Bean(initMethod = "start", destroyMethod = "stop")
    public XxlCacheFactory xxlCacheFactory() {
        XxlCacheFactory xxlCacheFactory = new XxlCacheFactory();
        xxlCacheFactory.setL1Provider(l1Provider);
        xxlCacheFactory.setMaxSize(maxSize);
        xxlCacheFactory.setExpireAfterWrite(expireAfterWrite);
        xxlCacheFactory.setL2Provider(l2Provider);
        xxlCacheFactory.setSerializer(serializer);
        xxlCacheFactory.setNodes(nodes);
        xxlCacheFactory.setUser(user);
        xxlCacheFactory.setPassword(password);
        return xxlCacheFactory;
    }
}

测试

创建IndexController

java 复制代码
@Controller()
@Slf4j
public class IndexController {

    /**
     * 1、定义缓存对象,并指定 "缓存category + 过期时间"
     */
    private XxlCacheHelper.XxlCache userCache = XxlCacheHelper.getCache("user", 60 * 1000);

    @RequestMapping("/get")
    @ResponseBody
    public String index() {
        String key = "user03";

        /**
         * 2、缓存读:按照 L1 -> L2 顺序依次读取缓存,如果L1存在缓存则返回,否则读取L2缓存并同步L1;
         */
        String value = userCache.get(key);
        return "key: " + key + "<br> value: " + value;
    }

    @RequestMapping("/set")
    @ResponseBody
    public String set(@RequestParam String value) {
        String key = "user03";

        /**
         * 3、缓存写:按照 L1 -> L2 顺序依次写缓存,同时借助内部广播机制更新全局L1节点缓存;
         */
        userCache.set(key, value);
        return "Set successfully";
    }

    @RequestMapping("/delete")
    @ResponseBody
    public String delete() {
        String key = "user03";

        /**
         * 4、缓存删:按照 L1 -> L2 顺序依次删缓存,同时借助内部广播机制更新全局L1节点缓存;
         */
        userCache.del(key);
        return "Deleted successfully";
    }
}

由于是测试用,这里就将缓存的key写死为user03

使用idea的将应用复制一份,指定运行端口为8081,同时运行两个应用实例来测试数据一致性

首先向8080的get接口发送请求,此时value没有任何值

然后向set接口发送请求,将user03的值设置为123

设置成功,通过日志可以发现:xxl-cache同时设置了l1(caffeine)、l2(redis)缓存中key的值,并且进行了广播,8081收到了广播:

此时我们可以向8081的get接口发送请求,看是否能取到user03的值:

测试成功!

相关推荐
小咕聊编程16 小时前
【含文档+PPT+源码】基于spring boot的固定资产管理系统
java·spring boot·后端
马尚道16 小时前
SpringBoot开发双11商品服务系统 | 已完结
spring boot
韩立学长16 小时前
【开题答辩实录分享】以《自然灾害隐患点管理信息系统》为例进行答辩实录分享
数据库·spring boot
我命由我1234517 小时前
Spring Cloud - Spring Cloud 注册中心与服务提供者(Spring Cloud Eureka 概述、微服务快速入门、微服务应用实例)
java·spring boot·spring·spring cloud·微服务·eureka·java-ee
christine-rr17 小时前
linux常用命令——其他
linux·服务器·网络·数据库·redis·ubuntu
一线大码18 小时前
SpringBoot 优雅实现接口的多实现类方式
java·spring boot·后端
Q_Q196328847518 小时前
python+uniapp基于微信小程序的助眠小程序
spring boot·python·小程序·django·flask·uni-app·node.js
摇滚侠18 小时前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 属性优先级 行内写法 变量选择 笔记42
java·spring boot·笔记
摇滚侠18 小时前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 总结 热部署 常用配置 笔记44
java·spring boot·笔记
十年小站18 小时前
一、新建一个SpringBoot3项目
java·spring boot