“Redis与Spring整合及缓存优化“

编程入门 行业动态 更新时间:2024-10-15 00:23:13

“Redis与Spring整合及<a href=https://www.elefans.com/category/jswz/34/1771061.html style=缓存优化“"/>

“Redis与Spring整合及缓存优化“

文章目录

  • 引言
  • 1. Spring整合Redis
    • 1.1. 为什么选择Redis作为缓存解决方案?
      • Redis的特点和优势
      • Redis与传统关系数据库的对比
    • 1.2. Spring与Redis整合的基本步骤
  • 2. Redis注解式缓存
    • 2.1. Spring提供的缓存注解介绍
    • 2.2. 使用注解实现方法级别的缓存
  • 3. Redis的击穿、穿透和雪崩问题及解决方案
    • 3.1. 几种常见的Redis缓存问题
    • 3.2. 解决方案和优化策略
  • 总结

引言

在现代应用开发中,缓存是提升性能和扩展性的关键技术之一。而Redis作为一种高性能、内存存储型数据库,与Spring框架的结合可以带来更加优雅和灵活的缓存解决方案。本篇博客将深入探讨Spring整合Redis的方法和最佳实践,并重点介绍Redis注解式缓存以及解决常见的Redis问题。

1. Spring整合Redis

1.1. 为什么选择Redis作为缓存解决方案?

Redis的特点和优势

  • 内存存储:Redis将数据存储在内存中,因此具有非常高的读写速度。相比传统数据库的磁盘存储,Redis能够快速处理大量请求。

  • 键值存储:Redis使用键值对(key-value)的数据结构来存储数据。这种简单的数据模型使得数据操作非常高效和灵活,适用于各种场景。

  • 支持多种数据类型:Redis支持丰富的数据类型,包括字符串、哈希、列表、集合、有序集合等。这些数据类型的支持使得开发者可以更方便地构建复杂的应用逻辑。

  • 缓存功能:Redis常被用作缓存服务器,可以将频繁访问的数据存储在内存中,从而加快数据读取速度。同时,Redis还提供了一些高级的缓存策略,如过期时间、LRU淘汰等。

  • 发布订阅系统:Redis提供了发布订阅(pub/sub)功能,允许客户端通过订阅某个频道来接收消息的推送。这种消息发布订阅模式对于实时通信、消息队列等场景非常有用。

  • 分布式支持:Redis支持分布式部署,可以将数据分布在多个节点上进行存储和访问。这种分布式的特性使得Redis具备高可用性和横向扩展的能力。

Redis与传统关系数据库的对比

  • 数据模型:Redis采用键值对的数据模型,而传统关系数据库使用表格模型。这使得Redis在处理简单查询和高并发读写方面更加高效,而关系数据库更适合复杂的数据关联和查询操作。

  • 存储方式:Redis将数据存储在内存中,而关系数据库通常将数据持久化到磁盘中。因此,Redis在读写速度方面更快,但关系数据库在数据持久化和容量方面具有优势。

  • 功能特性:Redis提供了丰富的功能特性,如发布订阅、缓存策略等,而关系数据库更加注重数据一致性、事务管理以及复杂的查询能力。

  • 扩展性:Redis支持分布式部署和横向扩展,可以通过添加新的节点来提高性能和容量。而关系数据库通常需要进行垂直扩展,即增加更强大的硬件来应对高负载。

  • 数据一致性:Redis默认情况下是单机的,不保证数据的强一致性,而关系数据库通常会保证数据的一致性。

1.2. Spring与Redis整合的基本步骤

准备步骤:

  1. 打开redis服务
  2. 导入spring整合redis项目
  • 当spring-context.xml文件需要注册多个.properties结尾的配置文件,不能在spring-*中添加注册

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context="" xmlns:tx=""xmlns:aop=""xsi:schemaLocation=" .xsd  .xsd  .xsd  .xsd"><!--1. 引入外部多文件方式 --><bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /><property name="ignoreResourceNotFound" value="true" /><property name="locations"><list><value>classpath:jdbc.properties</value><value>classpath:redis.properties</value></list></property></bean><!--  随着后续学习,框架会越学越多,不能将所有的框架配置,放到同一个配制间,否者不便于管理  --><import resource="applicationContext-mybatis.xml"></import><import resource="spring-redis.xml"></import><import resource="applicationContext-shiro.xml"></import>
</beans>

redis.properties

redis.hostName=localhost
redis.port=6379
redis.password=123456
redis.timeout=10000
redis.maxIdle=300
redis.maxTotal=1000
redis.maxWaitMillis=1000
redis.minEvictableIdleTimeMillis=300000
redis.numTestsPerEvictionRun=1024
redis.timeBetweenEvictionRunsMillis=30000
redis.testOnBorrow=true
redis.testWhileIdle=true
redis.expiration=3600

spring-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""xmlns:xsi=""xmlns:context=""xmlns:cache=""xsi:schemaLocation="://www.springframework/schema/beans/spring-beans.xsd://www.springframework/schema/context/spring-context.xsd://www.springframework/schema/cache/spring-cache.xsd"><!-- 1. 引入properties配置文件 --><!--<context:property-placeholder location="classpath:redis.properties" />--><!-- 2. redis连接池配置--><bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"><!--最大空闲数--><property name="maxIdle" value="${redis.maxIdle}"/><!--连接池的最大数据库连接数  --><property name="maxTotal" value="${redis.maxTotal}"/><!--最大建立连接等待时间--><property name="maxWaitMillis" value="${redis.maxWaitMillis}"/><!--逐出连接的最小空闲时间 默认1800000毫秒(30分钟)--><property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"/><!--每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3--><property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"/><!--逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1--><property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"/><!--是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个--><property name="testOnBorrow" value="${redis.testOnBorrow}"/><!--在空闲时检查有效性, 默认false  --><property name="testWhileIdle" value="${redis.testWhileIdle}"/></bean><!-- 3. redis连接工厂 --><bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"destroy-method="destroy"><property name="poolConfig" ref="poolConfig"/><!--IP地址 --><property name="hostName" value="${redis.hostName}"/><!--端口号  --><property name="port" value="${redis.port}"/><!--如果Redis设置有密码  --><property name="password" value="${redis.password}"/><!--客户端超时时间单位是毫秒  --><property name="timeout" value="${redis.timeout}"/></bean><!-- 4. redis操作模板,使用该对象可以操作redishibernate课程中hibernatetemplete,相当于session,专门操作数据库。--><bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"><property name="connectionFactory" ref="connectionFactory"/><!--如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!!  --><property name="keySerializer"><bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/></property><property name="valueSerializer"><bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/></property><property name="hashKeySerializer"><bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/></property><property name="hashValueSerializer"><bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/></property><!--开启事务  --><property name="enableTransactionSupport" value="true"/></bean><!--  5.配置缓存管理器  --><bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"><constructor-arg name="redisOperations" ref="redisTemplate"/><!--redis缓存数据过期时间单位秒--><property name="defaultExpiration" value="${redis.expiration}"/><!--是否使用缓存前缀,与cachePrefix相关--><property name="usePrefix" value="true"/><!--配置缓存前缀名称--><property name="cachePrefix"><bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix"><constructor-arg index="0" value="-cache-"/></bean></property></bean><!--6.配置缓存生成键名的生成规则--><bean id="cacheKeyGenerator" class="com.zking.ssm.redis.CacheKeyGenerator"></bean><!--7.启用缓存注解功能--><cache:annotation-driven cache-manager="redisCacheManager" key-generator="cacheKeyGenerator"/>
</beans>
  • resources的配置文件的配置必须要涵盖读取.properties结尾的文件
  • redisTemplate的使用,可以参照jdbcTemplate、amqpTemplate、rabbitMQtemplate等

2. Redis注解式缓存

2.1. Spring提供的缓存注解介绍

package com.zking.ssm.biz;import com.zking.ssm.model.Clazz;
import com.zking.ssm.util.PageBean;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;import java.util.List;
import java.util.Map;public interface ClazzBiz {@CacheEvict(value = "xx",key = "'cid:'+#cid",allEntries = true)int deleteByPrimaryKey(Integer cid);int insert(Clazz record);int insertSelective(Clazz record);//    xx=cache-cid:1
//    key的作用改变原有的key生成规则
//    @Cacheable(value = "xx",key = "'cid:'+#cid",condition = "#cid > 6")@CachePut(value = "xx",key = "'cid:'+#cid",condition = "#cid > 6")Clazz selectByPrimaryKey(Integer cid);int updateByPrimaryKeySelective(Clazz record);int updateByPrimaryKey(Clazz record);List<Clazz> listPager(Clazz clazz, PageBean pageBean);List<Map> listMapPager(Clazz clazz, PageBean pageBean);
}

@Cacheable:缓存方法的返回值,可读写
@CachePut:更新缓存的方法,只写不读,适合读写分离
@CacheEvict:移除缓存中的数据

2.2. 使用注解实现方法级别的缓存

在Spring Boot项目中开启注解式缓存
定义缓存的Key和Value的生成策略
编写示例代码演示注解式缓存的使用方式

3. Redis的击穿、穿透和雪崩问题及解决方案

3.1. 几种常见的Redis缓存问题

击穿:大量请求同时查询一个不存在的Key,导致请求都落到数据库上
穿透:恶意请求查询一个不存在的Key,导致请求直接落到数据库上
雪崩:大量缓存失效导致所有请求都落到数据库上

3.2. 解决方案和优化策略

击穿解决方案:设置热点数据永不过期、互斥锁、布隆过滤器等
穿透解决方案:空值缓存、参数校验、布隆过滤器等
雪崩解决方案:限流、降级、异步更新缓存等

总结

在本篇博客中,我们深入探讨了Redis与Spring的整合以及注解式缓存的使用方式。通过学习和实践,我们了解了Redis作为一种高性能缓存解决方案的优势,并且掌握了基于Spring框架使用Redis的方法。

更多推荐

“Redis与Spring整合及缓存优化“

本文发布于:2023-11-15 23:03:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1608533.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:缓存   Redis   Spring

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!