苍穹外卖-缓存套餐 Spring Cache day07

Spring Cache 是 Spring 框架提供的一个缓存抽象层,它通过注解的方式简化了缓存的使用,支持多种缓存实现(如 Caffeine、Redis、EhCache 等),并统一了缓存访问的 API。以下是关于 Spring Cache 的详细介绍:

核心注解

  • @EnableCaching:用于开启 Spring Cache 功能,通常放在配置类上。

  • @Cacheable:标记方法具有缓存功能,方法的返回值会被缓存。若缓存中有数据则直接返回,否则执行方法并将结果缓存。

  • @CachePut:每次执行都会将方法的返回值放入缓存,无论缓存中是否已存在数据,常用于更新操作。

  • @CacheEvict:用于清除指定缓存,常用于删除操作。

  • @Caching:组合注解,可同时指定多个缓存规则,如同时使用 @Cacheable、@CachePut 和 @CacheEvict。

  • @CacheConfig:类级别注解,用于简化缓存配置,可在类级别定义公共的缓存配置属性。

基本使用步骤

  1. 添加依赖 :如果是 Spring Boot 项目,可使用 spring-boot-starter-cache Starter。

  2. 启用缓存 :在配置类上添加 @EnableCaching 注解。

  3. 配置 CacheManager :需注册一个 CacheManager,如 ConcurrentMapCacheManager

  4. 使用注解:在方法上使用上述注解来声明缓存规则

缓存穿透

定义:查询的Key在缓存和数据库中都不存在,导致每次请求都直接访问数据库,若大量此类请求到来,会使数据库压力骤增。

成因

  • 业务误操作,导致缓存和数据库中的数据都被误删除。

  • 黑客恶意攻击,故意大量访问不存在的数据。

解决方案

  • 缓存空对象:当查询不到数据时,将空对象或标识存储到缓存中,但需注意设置较短的过期时间,避免过多无用数据占用缓存空间。

  • 布隆过滤器:预先将所有可能存在的数据通过哈希函数映射到一个足够大的Bitmap中,查询时先通过布隆过滤器判断数据是否存在,若布隆过滤器返回不存在,则直接返回,避免查询数据库。

  • 参数校验:在接口层增加严格的参数校验,如用户鉴权校验,拦截非法请求。

  • 限流和熔断:对访问频率进行限制,当请求量超过阈值时,直接拒绝请求或返回默认值,防止数据库被过多请求冲击。

缓存击穿

定义:缓存中的某个热点数据失效,大量请求同时访问该数据,导致请求直接穿透到数据库,给数据库带来巨大压力。

成因

  • 缓存中没有热点数据的缓存,或缓存穿透导致热点数据未被缓存。

解决方案

  • 热点数据永不过期:对热点数据设置永不过期,避免其在缓存中失效,但需定期更新数据,以确保缓存数据的时效性。

  • 互斥锁机制:在缓存失效时,使用互斥锁或分布式锁,确保只有一个请求去查询数据库并更新缓存,其他请求等待锁释放后再从缓存中读取数据。

缓存雪崩

定义:大量缓存数据在同一时间过期,导致大量请求同时到达数据库,给数据库带来巨大压力,甚至可能导致数据库崩溃。

成因

  • 缓存过期策略不当,导致大量缓存同时过期。

  • 缓存服务器宕机。

解决方案

  • 设置不同的过期时间:为不同缓存设置不同的过期时间,避免大量缓存同时失效。

  • 过期时间加随机数:在设置的过期时间基础上,再加一个随机数,使缓存的过期时间分散。

  • 缓存预热:在系统启动时,预先将热点数据加载到缓存中。

  • 限流和熔断:对访问频率进行限制,当请求量超过阈值时,直接拒绝请求或返回默认值,防止数据库被过多请求冲击。

  • 本地缓存:在分布式缓存的基础上,增加本地缓存,提高缓存的可用性。

  • 双缓存:使用两层缓存,第一层缓存使用本地缓存,第二层缓存使用分布式缓存,当第一层缓存失效时,可以由第二层缓存提供数据。

  • 利用Redis集群:提高缓存服务的可用性,即使部分节点失效,也不会影响整个缓存系统的可用性

入门案例:

java 复制代码
package com.itheima.controller;

import com.itheima.entity.User;
import com.itheima.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @PostMapping
//    @CachePut(cacheNames = "userCache",key = "#a0.id")//spring cache缓存
//    @CachePut(cacheNames = "userCache",key = "#p0.id")//spring cache缓存
//    @CachePut(cacheNames = "userCache",key = "#result.id")//spring cache缓存
    @CachePut(cacheNames = "userCache",key = "#user.id")//spring cache缓存
    public User save(@RequestBody User user){
        userMapper.insert(user);
        return user;
    }

    @DeleteMapping
    @CacheEvict(cacheNames = "userCache",key = "#id")
    public void deleteById(Long id){
        userMapper.deleteById(id);
    }

	@DeleteMapping("/delAll")
    @CacheEvict(cacheNames = "userCache",allEntries = true)
    public void deleteAll(){
        userMapper.deleteAll();
    }

    @GetMapping
    @Cacheable(cacheNames = "userCache",key = "#id")
    public User getById(Long id){
        User user = userMapper.getById(id);
        return user;
    }

}
相关推荐
陈文锦丫21 小时前
MQ的学习
java·开发语言
乌暮21 小时前
JavaEE初阶---线程安全问题
java·java-ee
爱笑的眼睛1121 小时前
GraphQL:从数据查询到应用架构的范式演进
java·人工智能·python·ai
Seven971 天前
剑指offer-52、正则表达式匹配
java
代码or搬砖1 天前
RBAC(权限认证)小例子
java·数据库·spring boot
青蛙大侠公主1 天前
Thread及其相关类
java·开发语言
Coder_Boy_1 天前
DDD从0到企业级:迭代式学习 (共17章)之 四
java·人工智能·驱动开发·学习
2301_768350231 天前
MySQL为什么选择InnoDB作为存储引擎
java·数据库·mysql
派大鑫wink1 天前
【Java 学习日记】开篇:以日记为舟,渡 Java 进阶之海
java·笔记·程序人生·学习方法