签名:但行好事,莫问前程。
SpringBoot+Vue 博客系统(连载系列)
YangCunle`s Blog 博客网址:http://www.yangcunle.com
SpringBoot+Vue 博客系统(一):个人网站的由来
SpringBoot+Vue 博客系统(二):个人博客的搭建
SpringBoot+Vue 博客系统(三):个人博客的设计
SpringBoot+Vue 博客系统(五):整合阿里云OSS
SpringBoot+Vue 博客系统(六):整合Redis
SpringBoot+Vue 博客系统(七):Blog前端Vue项目的搭建
SpringBoot+Vue 博客系统(八):前端项目引入Element-UI
SpringBoot+Vue 博客系统(九):安装Axios处理跨域
SpringBoot+Vue 博客系统(十):VUE路由 vue-route
SpringBoot+Vue 博客系统(十一):博客后台管理
SpringBoot+Vue 博客系统(十二):博客前台展示
SpringBoot+Vue 博客系统(十三):项目打包部署到服务器
文章目录
一、SpringBoot整合Redis
1、引入Redis依赖
<!-- Redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--Redis连接池的依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2、配置Redis连接信息
spring:
redis: # Redis配置
host: 119.23.106.219
port: 6379
password: 123456
lettuce: # springboot默认引入的是lettuce连接池,如果要是用jedis连接池需要引入jedis依赖
pool:
max-active: 8 # 最大连接
max-idle: 8 # 最大空闲连接
min-idle: 0 # 最小空闲连接
max-wait: 1000ms # 连接等待时间
3、编写Redis测试类
@SpringBootTest
class BlogApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void testString() {
redisTemplate.opsForValue().set("ycl","杨存乐");
Object name = redisTemplate.opsForValue().get("ycl");
System.out.println(name);
}
}
但是用Redis连接工具查看,看到的是序列化的
点开源码看一下
if (this.defaultSerializer == null) {
this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader());
}
4、给RedisTemplate的key和values设置序列化
@Configuration
public class RedisConfig {
/**
* 给RedisTemplate的key和values设置序列化
* @param connectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
// 创建RedisTemplate对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置连接工厂
template.setConnectionFactory(connectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置Key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 设置Value的序列化
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
// 返回
return template;
}
}
5、测试序列化是否成功
去Redis连接工具查看
序列化成功
6、测试存入一个对象
/**
* 测试存入一个对象
*/
@Test
void testUser() {
User user = new User();
user.setUsername("杨存乐");
user.setEmail("357487967@qq,com");
redisTemplate.opsForValue().set("user:ycl",user);
User user1 = (User) redisTemplate.opsForValue().get("user:ycl");
System.out.println(user1.toString());
}
查看
7、使用StringRedisTemplate操作数据
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* 测试存入一个对象用StringRedisTemplate操作
*/
@Test
void testUser2() {
User user = new User();
user.setUsername("杨存乐");
user.setEmail("357487967@qq,com");
String userString = JSON.toJSONString(user);
stringRedisTemplate.opsForValue().set("user:str:ycl", userString);
String s = stringRedisTemplate.opsForValue().get("user:str:ycl");
User user1 = JSON.parseObject(userString, User.class);
System.out.println(user1);
}
引入fastJSON依赖,用fastJSON手动序列化JSON
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.71</version>
</dependency>
二、缓存穿透
缓存穿透的原因:是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库,给数据库带来巨大的压力。
常见的两种解决方案:缓存空对象 布隆过滤
1、缓存空对象
先查缓存,缓存没有查数据库,数据库再没有,缓存一个null对象(避免请求一直访问数据库),并设置一个过期时间(避免无用数据过多的占用Redis内存)
优点:实现简单,维护方便
缺点:额外的内存消耗可能造成短期的不一致
2、布隆过滤
优点:内存占用较少,没有多余key
缺点:实现复杂存在误判可能
三、缓存雪崩
缓存雪崩的原因:在同一时间大量缓存的key失效或者Redis服务宕机,导致大量请求到达数据库,给数据库带来巨大的压力。
解决方案:
- 给不同的key的过期时间设置随机值(避免在同一时间大量key过期)
- Redis做集群(防止Redis宕机)
- 给缓存业务添加降级或限流策略
- 给业务增加多级缓存
四、缓存击穿
缓存击穿的原因:一个被高频访问并且缓存重建业务比较复杂的key突然失效,无数的请求访问会在瞬间给数据库带来巨大的压力
常见的解决方案:互斥锁、逻辑过期
五、博客添加缓存
@Override
@Transactional
public Blog queryBlog(Integer id) {
// 先从Redis中查询
Blog blog = redisUtil.getObject(RedisKeyConstants.Blog_INFO_KEY + id, Blog.class);
if (ObjectUtil.isNotEmpty(blog)) {
return blog;
}
// 从数据库查
blog = getById(id);
if (ObjectUtil.isNotEmpty(blog)) {
// 写入Redis
redisUtil.set(RedisKeyConstants.Blog_INFO_KEY + id, blog);
}
return blog;
}
六、缓存更新策略
在项目中我们采用主动更新策略
主动更新又分为直接更新缓存和直接删除缓存
1、直接更新缓存
好处就是下次查到的是最新的数据
缺点就是每次更新都有对缓存的操作,如果两次更新中没人访问,对缓存的无效写操作较多
2直接删除缓存
更新数据库时让缓存失效,查询时再更新缓存
2.1先删除缓存,再更新数据库
2.2先更新数据库,再删除缓存
由于写缓存比更新数据库要快得多,这种出现异常的情况非常少,所以采用这种。
@Override
@Transactional
public Boolean updateBlog(Blog blog) {
boolean b = updateById(blog);
// 判断缓存key是否存在
if (redisUtil.exists(RedisKeyConstants.Blog_INFO_KEY + blog.getId())) {
// 若存在,删除缓存
redisUtil.deleteKey(RedisKeyConstants.Blog_INFO_KEY + blog.getId());
}
return b;
}
3延时双删
大概就是这么个意思,理解就行。
总结
以上主要记录了在博客系统中如何整合Redis以及Redis的常见问题,如果对你有所帮助,请一键三连。