赞
踩
一、缓存
当系统的并发量上来了,若是我们频仍地去接见数据库,那么会使数据库的压力不停增大,在岑岭时甚至可以泛起数据库溃逃的征象。以是一样平常我们会使用缓存来解决这个数据库并发接见问题,用户接见进来,会先从缓存里查询,若是存在则返回,若是不存在再从数据库里查询,最后添加到缓存里,然后返回给用户,固然了,接下来又能使用缓存来提供查询功效。
而缓存,一样平常我们可以分为内陆缓存和分布式缓存。
常用的内陆缓存有 ehcache、guava cache,而我们一样平常都是使用 ehcache,究竟他是纯 Java 的,泛起问题我们还可以凭据源码解决,而且还能自己举行二次开发来扩展功效。
常用的分布式缓存固然就是 Redis 了,Redis 是基于内存和单线程的,执行效率异常的高。
二、Spring Cache
信赖若是要整合缓存到项目中,人人都市使用到 Spring Cache,它不只整合了多种缓存框架(ehcache、jcache等等),还可以基于注解来使用,是相当的利便。
缓存框架的整合在 spring-context-support 中:
缓存注解在 spring-context 中:
固然了,在 Spring 的 context 中没有整合 Redis,然则我们可以在 spring-data-redis 中找到。
然则我们都知道,不管是在 Spring 项目 照样 Spring Boot 中,我们都只能整合一种缓存,不能同时整合多种缓存。
在 Spring Boot 中,我们一样平常是行使 spring.cache.type 来指定使用哪种缓存,然后填写相关设置信息来完成自动设置。
CacheType 的源码:我们可以看到,Spring 是支持异常多种缓存框架的。
package org.springframework.boot.autoconfigure.cache;
public enum CacheType {
GENERIC,
JCACHE,
EHCACHE,
HAZELCAST,
INFINISPAN,
COUCHBASE,
REDIS,
CAFFEINE,
SIMPLE,
NONE;
private CacheType() {
}
}
那么若是我们就是有这么一种需求,要整合两种缓存框架:例如一个内陆缓存 Ehcache,一个分布式缓存 Redis,
那能整么?
能是能,然则 Spring 可不提供这种多级缓存,而是需要你自己着手来整了。
三、h2cache-spring-boot-starter
1、什么是 h2cache-spring-boot-starter?
在微服务中,每个服务都是无状态的,服务之间需要经由 HTTP 或者 RPC 来举行通讯。而每个服务都拥有自己对应的数据库,以是说若是服务A 需要获取服务B 的某个表的数据,那么就需要一次 HTTP 或 RPC 通讯,那若是岑岭期每秒需要挪用100次,那岂不是需要100次 HTTP 或 RPC 通讯,这是相当花费接口性能的。
那怎么解决呢?
内陆缓存那是一定不是的,由于一样平常差别服务都是部署在差别的机械上面的,以是此时我们需要的是分布式缓存,例如 Redis;然则,接见量高的的服务固然照样需要内陆缓存了。以是最后,我们不只需要内陆缓存,还需要分布式缓存,然则 Spring Boot 却不能提供这种多级缓存的功效,以是需要我们自己来整合。
不用怕,我已经自己整了一个 Spring Boot Starter了,就是h2cache-spring-boot-starter,我们只需要在设置文件设置上对应的信息,就可以启用这个多级缓存的功效了。
2、开始使用
添加依赖:
人人正常引入下面依赖即可,由于我已经将此项目公布到 Maven 中央堆栈了~
com.github.howinfun
h2cache-spring-boot-starter
0.0.1
在 Spring Boot properties 启用服务,而且加上对应的设置:
开启多级缓存服务:
# Enable L2 cache or not
h2cache.enabled=true
设置 Ehcache:
# Ehcache Config
## the path of ehcache.xml (We can put it directly under Resources)
h2cache.ehcache.filePath=ehcache.xml
#Set whether the EhCache CacheManager should be shared (as a singleton at the ClassLoader level) or independent (typically local within the application).Default is "false", creating an independent local instance.
h2cache.ehcache.shared=true
设置 Redis:主要包罗默认的缓存设置和自定义缓存设置
要注意一点的是:h2cache-spring-boot-starter 同时引入了 Lettuce 和 Jedis 客户端,而 Spring Boot 默认使用 Lettuce 客户端,以是若是我们需要使用 Jedis 客户端,需要将 Lettuce 依赖去除掉。
# Redis Config
## default Config (expire)
h2cache.redis.default-config.ttl=200
### Disable caching {@literal null} values.Default is "false"
h2cache.redis.default-config.disable-null-values=true
### Disable using cache key prefixes.Default is "true"
h2cache.redis.default-config.use-prefix=true
## Custom Config list
### cacheName -> @CacheConfig#cacheNames @Cacheable#cacheNames and other comments, etc
h2cache.redis.config-list[0].cache-name=userCache
h2cache.redis.config-list[0].ttl=60
h2cache.redis.config-list[0].use-prefix=true
h2cache.redis.config-list[0].disable-null-values=true
h2cache.redis.config-list[1].cache-name=bookCache
h2cache.redis.config-list[1].ttl=60
h2cache.redis.config-list[1].use-prefix=true
#Redis
spring.redis.host=10.111.0.111
spring.redis.password=
spring.redis.port=6379
spring.redis.database=15
# 毗邻池最大毗邻数(使用负值示意没有限制)
spring.redis.jedis.pool.max-active=8
# 毗邻池中的最小空闲毗邻
spring.redis.jedis.pool.min-idle=0
# 毗邻池中的最大空闲毗邻
spring.redis.jedis.pool.max-idle=8
# 毗邻池最大壅闭等待时间(使用负值示意没有限制)
spring.redis.jedis.pool.max-wait=30
若何使用缓存注解
我们只要像之前一样使用 Spring Cache 的注解即可。
for example:
代码里的持久层,我使用的是: mybatis-plus.
package com.hyf.testDemo.redis;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Repository;
/**
* @author Howinfun
* @desc
* @date 2020/3/25
*/
@Repository
// Global cache config,We usually set the cacheName
@CacheConfig(cacheNames = {"userCache"})
public interface UserMapper extends BaseMapper {
/**
* put the data to cache(Ehcache & Redis)
* @param id
* @return
*/
@Cacheable(key = "#id",unless = "#result == null")
User selectById(Long id);
/**
* put the data to cache After method execution
* @param user
* @return
*/
@CachePut(key = "#user.id", condition = "#user.name != null and #user.name != ''")
default User insert0(User user) {
this.insert(user);
return user;
}
/**
* evict the data from cache
* @param id
* @return
*/
@CacheEvict(key = "#id")
int deleteById(Long id);
/**
* Using cache annotations in combination
* @param user
* @return
*/
@Caching(
evict = {@CacheEvict(key = "#user.id", beforeInvocation = true)},
put = {@CachePut(key = "#user.id")}
)
default User updateUser0(User user){
this.updateById(user);
return user;
}
}
测试一下:
查询:我们可以看到,在数据库查询到效果后,会将数据添加到 Ehcache 和 Redis 缓存中;接着之后的查询都将会先从 Ehcache 或者 Redis 里查询。
2020-04-03 09:55:09.691 INFO 5920 --- [nio-8080-exec-7] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2020-04-03 09:55:10.044 INFO 5920 --- [nio-8080-exec-7] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2020-04-03 09:55:10.051 DEBUG 5920 --- [nio-8080-exec-7] c.h.t.redis.BookMapper2.selectById : ==> Preparing: SELECT id,create_time,update_time,read_frequency,version,book_name FROM book WHERE id=?
2020-04-03 09:55:10.068 DEBUG 5920 --- [nio-8080-exec-7] c.h.t.redis.BookMapper2.selectById : ==> Parameters: 51(Long)
2020-04-03 09:55:10.107 DEBUG 5920 --- [nio-8080-exec-7] c.h.t.redis.BookMapper2.selectById : <== Total: 1
2020-04-03 09:55:10.113 INFO 5920 --- [nio-8080-exec-7] c.hyf.cache.cachetemplate.H2CacheCache : insert into ehcache,key:51,value:Book2(id=51, bookName=微服务架构, readFrequency=1, createTime=2020-03-20T16:10:13, updateTime=2020-03-27T09:14:44, version=1)
2020-04-03 09:55:10.118 INFO 5920 --- [nio-8080-exec-7] c.hyf.cache.cachetemplate.H2CacheCache : insert into redis,key:51,value:Book2(id=51, bookName=微服务架构, readFrequency=1, createTime=2020-03-20T16:10:13, updateTime=2020-03-27T09:14:44, version=1)
2020-04-03 09:55:31.864 INFO 5920 --- [nio-8080-exec-2] c.hyf.cache.cachetemplate.H2CacheCache : select from ehcache,key:51
删除:删除数据库中的数据后,也会删除 Ehcache 和 Redis 中对应的缓存数据。
2020-04-03 10:05:18.704 DEBUG 5920 --- [nio-8080-exec-3] c.h.t.redis.BookMapper2.deleteById : ==> Preparing: DELETE FROM book WHERE id=?
2020-04-03 10:05:18.704 DEBUG 5920 --- [nio-8080-exec-3] c.h.t.redis.BookMapper2.deleteById : ==> Parameters: 51(Long)
2020-04-03 10:05:18.731 DEBUG 5920 --- [nio-8080-exec-3] c.h.t.redis.BookMapper2.deleteById : <== Updates: 1
2020-04-03 10:05:18.732 INFO 5920 --- [nio-8080-exec-3] c.hyf.cache.cachetemplate.H2CacheCache : delete from ehcache,key:51
2020-04-03 10:05:18.844 INFO 5920 --- [nio-8080-exec-3] c.hyf.cache.cachetemplate.H2CacheCache : delete from redis,key:51
其他的就不用演示了…
四、最后
固然啦,这个 starter 照样比较简单的,若是人人感兴趣,可以去看看源码是若何基于 Spring Cache 实现多级缓存的~
原文链接:https://www.cnblogs.com/Howinfun/p/12651576.html
本站声明:网站内容来源于网络,若有侵权,请联系我们,我们将及时处理。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。