前言
一个程序少不了对数据库的增删改查操作,我们也知道内存的速度是大大快于硬盘的速度的。当我们需要重复地获取相同的数据的时候,我们一次又一次的请求数据库或者远程服务,导致大量的时间耗费在数据库查询或者远程方法调用上,程序性能也就大打折扣,这便是数据缓存要解决的问题。
Spring boot 给我们提供了便利的缓存注解,也大大了减少了系统的耦合
需要解决的问题
怎么用缓存减少一对多关系的频繁数据库访问
怎么用缓存解决高并发的数据服务性能
下面给出一些源码和讲解
目录结构
项目依赖配置
pom.xml
实体类
为了方便测试我们直接使用了 mysql 自带的表, 注意这里的 toString 方法需要重写下,后面会用作缓存的Key
HelpTopic.java
关系实体类
HelpCategory.java
Category 业务层缓存配置
思路:把每个实体都跟表关系起来,相当于表数据的缓存,value 也跟表名一样,这里主要解决第1个问题
@Cacheable(key = "#id", value = "help_category")
@CacheEvict(key = "#id", value = "help_category")
Topic 业务层缓存配置
这里的 selectList 方法循环的去查询分类对象信息,相同的分类其实都是直接存内存中取的
Web服务配置
@Cacheable(key = "'dataGrid' + #form.toString()", value = "HelpTopicController", sync = true)
这里主要解决第二个问题,当很多用户在3秒之内都请求了同样的服务,将会直接返回缓存的结果,而不再执行 selectList 的数据库查询
缓存管理配置
Spring boot 提供了 CacheManager 用来管理所有的缓存
这里我们声明了以下缓存
new ConcurrentMapCache("help_category")
new ConcurrentMapCache("help_topic")
new CaffeineCache("HelpTopicController", Caffeine.newBuilder()
.expireAfterWrite(3, TimeUnit.SECONDS)
.build())
new CaffeineCache("HelpCategoryController", Caffeine.newBuilder()
.expireAfterWrite(3, TimeUnit.SECONDS)
.build())
前两个主要是基于内存长时间缓存的,不需要经常更新
后两个主要是解决并发请求的缓存,所以是用了 CaffeineCache 的缓存策略 expireAfterWrite 3 秒内数据没有更新就删除缓存数据, 可以理解为是数据会在缓存中存在 3 秒钟
高并发测试
测试场景 100 个线程,每个线程请求100次
不使用缓存
使用缓存后
可以看出平均响应时间提高了 14 倍多
一般情况下这样就够了,但是实际项目当中还要根据不同的项目架构,以及不同的业务场景来决定该用什么样解决方案
领取专属 10元无门槛券
私享最新 技术干货