SpringBoot-缓存(缓存、JSR107规范、Springboot缓存注解)

知识要点

  • 认识缓存
    缓存的定义
    缓存的作用
    缓存指标
    缓存同步方案
    缓存穿透和缓存击穿
    缓存雪崩
  • JSR107规范
  • Spring缓存注解
  • SpringBoot缓存注解

1.认识缓存
缓存的定义

  • 缓存是指可以进行高速数据交换的存储器,使用它可以更快速的操作和访问数据
  • 缓存是一个比较大的概念,用来预读取信息(比如硬盘的缓存),或者是暂时存储一些不需要长久保存的信息

特点

  • 特点是速度快、临时存放、保存时间短、读操作大于写操作
    使用缓存可以避免访问数据库,节省数据库服务器的资源
    性能更快,缓存属于内存级的服务器,而DB牵扯到更多的业务逻辑判断和磁盘操作,因此缓存的性能更高

与内存的区别

  • 内存是内部存储器,是一个硬件设备

缓存的作用

  • 数据访问频率高的地方
  • 数据读多写少的情况
  • 数据对一致性要求不高的地方
  • CPU缓存、操作系统缓存、数据库缓存、JVM编译缓存、CDN缓存、代理与反向代理缓存、前端缓存、应用程序缓存、分布式对象缓存

缓存指标

  • 1.命中率:确保通过key快速找到
  • 2.过期策略:旧缓存数据需要为新数据腾空间
  • 3.缓存键集合的大小:缓存中的每一个对象使用缓存键识别,定位一个对象的唯一方式就是对缓存键执行精准匹配,缓存键越少,命中率越高
  • 4.缓存可使用内存空间:缓存可使用空间直接决定了缓存对象的平均大小和缓存对象数量
  • 5.缓存对象生存空间:缓存对象生存空间TTL(Time To Live),对象缓存的时间越长,缓存对象被重用的可能性越高

缓存同步方案

  • 同步
    实时更新,同步调用cache的增删改方法
    利用观察者模式/发布订阅/mq等方法进行同步更新
  • 异步
    缓存设备过期时间,比如一小时
    缓存每天定时更新(不设置过期时间)

缓存穿透

  • 缓存穿透:是指缓存和数据库都没有的数据,而用户不断发起请求,如发起id为"-1"的数据或id为特别大不存在的数据。这是的用户很有可能是攻击者,攻击会导致数据库压力过大
  • 解决方案:
    接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截
    从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没啥使用)。这样可以防止攻击用户反复

缓存击穿

  • 缓存击穿:是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读取缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
  • 设置热点数据永远不过期
  • 加互斥锁

缓存雪崩

  • 缓存雪崩:是指缓存总数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不用数据都过期了,很多数据都查不到而查数据库
  • 解决方案:
    缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生
    如果缓存数据是分布式部署,将热点数据均匀分布在不用的缓存数据库中
    设置热点数据永远不过期

2.JSR107规范
JSP

  • Java Specification Requests的缩写

JCache

  • JCache规范定义了一种对Java对象临时在内存中进行缓存的方法,包括对象的创建、共享访问、假脱机、失效、各JVM的一致性等,可被用于缓存JSP内最经常读取的数据,如产品目录和价格列表。利用JCACHE,多数查询的反应时间会因为有缓存的数据而加快(内部测试表明反应时间大约快15倍)

JCache

  • CachingProvider:定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期访问多个CachingProvider
  • CacheManager:定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于Cachemanager的上下文中。一个CacheManager仅被一个CachingProvider所拥有
  • Cache:一个类似Map的数据结构并临时存储以key为索引的值,一个Cache仅被一个CacheManager所拥有
  • Entry:一个存储在Cache中的key-value对
  • Expiry:每一个存储在Cache中的条目有一个定义的有效期,一旦超过这个有效期,条目为过期的状态,一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置

3.Spring缓存注解

  • Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.Cache.CacheManager接口来统一不同的缓存技术;并支持使用JCache(JSR107)注解简化开发
  • Cache接口下Spring提供了各种xxxCache的实现;如RedisCache,EnCacheCache,ConcurrentMapCache等
  • 每次调用需要缓存功能的方法时,Spring会检查指定的目标方法是否已经被调用锅,如果有就直接从缓存中获取方法调用后的结果;如果没有就调用方法并缓存结果返回给用户,下次调用直接从缓存中获取

Class和注解说明
Cache缓存接口,定义缓存操作,实现:RedisCache,EhCacheCache,ConcurrentMapCache等
Cache缓存接口,定义缓存操作,实现:RedisCache,EhCacheCache,ConcurrentMapCache等
CacheManager缓存管理器,管理各种缓存组件
@Cacheable主要针对方法进行配置,根据方法的请求参数对其结果进行缓存
@CacheEvict清空缓存
@CachePut确保方法被调用,又希望结果被缓存
@EnableCaching开启基于注解的缓存
KeyGenetator缓存数据时key生成策略
serialize缓存数据时value序列化策略

Springboot缓存注解

  • 引入依赖
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-stater-cache</artifactId>
</dependency>
  • 开启缓存
  • 启动器类上配置@EnableCaching
  • 指定mapper接口路径@MapperScan

缓存操作方法

  • 查询
    cacheNames/value:指定缓存组件的名字;
    key:缓存数据使用的key,可以指定。默认即使用方法参数的值
    condition:指定符合条件的情况下才缓存;如condition=“#id>0”

  • 更新
    修改了数据库的某个数据,同时更新缓存
    value:缓存名
    key:确保更新的key和已经存在缓存中的key(#id)一致即可做到同时更新数据库数据和缓存中的数据

  • 删除
    key:指定要清除的数据(对应上key可实现删除数据库和缓存中的数据)

  • 缓存策略
    @Caching:组合组件,可以设置多个缓存策略


SPEL表达式

表达式举例说明
#root.methodName当前被调用的方法名
#root.method.name当前被调用的方法
#root.target当前被调用的目标方法
#root.targerClass当前被调用的目标对象类
#root.args[0]当前被调用的方法的参数列表
@Cacheable(value={“cache1”,“cache2”})当前方法调用使用的缓存列表
#p0,#p1方法参数的名字,可以直接#参数名
#result方法执行后的返回值

eg:
pom文件

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-stater-cache</artifactId>
</dependency>

Application.java

@SpringBootApplication
@EnableCacheing
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(App.class,args);
	}
}

UserServiceImpl.java

...
@Autowired
private UserMapeer userMapper;

@Cacheeable(value="cache”,key="#root.args[0])
public User selectByName(String username){
	return userMapper.selectByName(username);
}

@Cacheable(value="cache",key="#root.args[0]".contion="#id>5")
public User selectById(Integer id) {
	return userMapper.selectById(id);
}

@CachePut(value="cache",key="#root")
public Integer updateUser(User user){
	return userMapper.updateUser(user);
}

@CacheEvict(value="cache",key="#id",beforeInvocation=true,allEntries=false)
public Integer deleteById(Integer id){
	return userMapper.deleteById(id);
}
... 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值