Skip to content

Central Starter Cache

概述

  Central Starter Cache 主要用于为项目提供缓存管理功能。在后端开发过程中,经常通过缓存来提升接口响应速度,减少数据库的压力。由于 Spring Cache 的缓存管理功能不支持级联删除功能,因此可能会出现缓存清除困难、缓存清除不干净等问题,很多应用程序不得不提供手动「清除缓存」的功能给用户,用户体验不佳。

级联删除定义

  级联删除是指:定义 A 缓存依赖 B 缓存,定义 B 缓存依赖 C 缓存;当 C 缓存被删除时,缓存框架应根据依赖关系找到 B 和 A 缓存,然后依次删除。

  缓存级联删除功能可以解决缓存管理复杂等问题。

Maven 座标

xml
<dependency>
    <groupId>com.central-x</groupId>
    <artifactId>central-starter-cache</artifactId>
    <version>${centralx.version}</version>
 </dependency>

使用类库

启用缓存功能

  开发者需要在程序启动类或配置类上添加 @EnableCaching 注解,用于启用本类库提供的缓存功能。

java
@EnableCaching
@SpringBootApplication
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

注解管理缓存

  在日常开发过程中,最经常使用缓存的方式,就是通过在方法上面添加相关的注解,以达到自动管理缓存的过程。

执行顺序

@Cachable

  本注解主要用于在没有缓存时生成缓存,有缓存时直接返回结果。

java
    /**
     * 本缓存会在调用方法前,检查是否存在指定键的缓存
     * 如果存在缓存,则直接返回缓存,本方法将不会被调用
     * 如果不存在缓存,则调用本方法,并将本方法返回的数据保存到缓存,供下次使用
     *
     * 通过 key 指定缓存的键名,使用模板语法计算键
     * 通过 expires 指定缓存失效时间
     */
    @Cacheable(key = "account:id:${args[0]}", expires = 30 * 60 * 1000L)
    public Account findById(String id) {
        // 根据主键查询帐户信息
        ...
    }


    /**
     * 通过 sign(args) 计算参数的签名,不同的参数签名不一样,因此对应的缓存也不一样。
     * 通过 dependencies 指定当前缓存的依赖。当依赖的缓存被清除时,当前缓存也会被一起清除。
     */
    @Cacheable(key = "account:findBy:${sign(args)}", dependencies = "account:id:any")
    public List<Account> findBy(Long first, Long offset, Conditions<Account> conditions, Orders<Account> orders) {
        // 通过条件查询帐户信息
        ...
    }

@CacheEvict

  本注解用于清除指定的缓存。在清除缓存时,会同时清除依赖本缓存的其它缓存。

java
    /**
     * 清除指定的缓存
     * 同时清除键为 account:id:any 的缓存,由于 account:findBy:* 依赖了这个缓存,因此也会被同时清除
     */
    @CacheEvict(key = "account:id:${args[0]}")
    @CacheEvict(key = "account:id:any")
    public boolean deleteById(String id) {
        // 根据主键删除数据
        ...
    }

手动管理缓存

java
    @Autowired
    private CacheStorage storage;

    
    public List<Account> findBy(Long first, Long offset, Conditions<Account> conditions, Orders<Account> orders) {
        // 根据参数计算缓存键
        var key = ...;

        // 判断缓存是否存在
        if (this.storage.exists(key)) {
            // 如果缓存存在,则返回缓存
            return this.storage.get(key);
        }

        // 根据主键查询帐户信息
        var accounts = ...;

        // 保存结果到缓存系统,缓存有效期为 30 分钟,并依赖键为 account:id:any 的缓存
        this.storage.put(key, accounts, 30 * 60 * 1000L, "account:id:any");

        return accounts;
    }


    public boolean deleteById(String id) {
        // 根据主键删除数据
        var result = ...

        // 同时清除 account:id:${id} 和 account:id:any 这两个缓存
        // 在清除这两个缓存的时候,缓存系统会同时清除依赖本缓存的其它缓存
        this.storage.evict("account:id:" + id, "account:id:any");
        return result;
    }

Released under the MIT license.