SSM之spring注解式缓存redis

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: SSM之spring注解式缓存redis

SSM(Spring + SpringMVC + MyBatis)是一种常用的 Java Web 开发框架,而 Redis 是一种常用的 NoSQL 数据库。在 SSM 框架中,可以通过整合 Redis 来实现数据缓存、分布式锁等功能,提高系统的性能和可靠性。

SSM整合redis

Redis 和 MySQL 是两种不同类型的数据库,下面是它们之间的主要区别:

1.数据存储方式:Redis 是一种基于键值对存储的内存数据库,而 MySQL 是一种基于表的关系型数据库。


2.数据查询语言:Redis 是一种 NoSQL 数据库,不支持 SQL 语言,没有像 SQL 那样的复杂查询语句,而 MySQL 支持 SQL 语言,可以进行复杂的查询操作。


3.数据存储方式:Redis 数据以键值对的方式进行存储,可以存储多种数据类型,如字符串、哈希、列表、集合、有序集合等。MySQL 则基于表的数据模型进行存储,支持多种数据类型,如整型、字符型、日期型等。


4.数据库容量:Redis 基于内存存储,数据容量有限,适用于存储较小量的数据。MySQL 支持大容量的存储,适合存储大量数据。


5.数据库性能:Redis 基于内存存储,读写速度极快,通常可以支持高并发访问,适合实时数据读写操作。MySQL 则需要通过硬盘进行存储和读写操作,速度相对较慢,但对于复杂的数据处理,MySQL 的性能通常比 Redis 更优。


综上所述,Redis 和 MySQL 分别适用于不同的应用场景,需要结合具体业务需求进行选择。


可以去参考整合mysql,即整合mybatis


1.pom配置


2.spring-mydatis.xml -->mybatis.cfg.xml


               1.包扫描


               2.注册一个jdbc.properties


               3.配置数据源(数据连接池)


               4.配置sqlsession,配置会话


               5.配置事务。。。


3.springContext.xml中添加spring-mybatis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/cache
       http://www.springframework.org/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="300"/>
        <!--连接池的最大数据库连接数  -->
        <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操作模板,使用该对象可以操作redis
        hibernate课程中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>

整合redis

1. pom配置

2.spring-redis.xml

               1.注册了一个redis.properties

            2.配置数据源(数据库连接池)


               3.连接工厂


               4.配置序列化器


               5.配置redis的key生成策略


3.springContext.xml中添加spring-redis.xml

导入

导入我们的SSM项目,在我们的导入项目的时候开启服务

查看我们的配置

注意1:当spring-comtext.xml中需要注册多个.properties结尾的配置文件,那么不能在spring-*.xml添加注册


注意2:resources的配置必须要涵盖读取.properties结尾的文件


注意3:redisTemplate的使用,可以参照jdbcTemplate,new Jedi(ip,port).auth().get


pom
  <properties>    
    <redis.version>2.9.0</redis.version>
    <redis.spring.version>1.7.1.RELEASE</redis.spring.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>${redis.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-redis</artifactId>
      <version>${redis.spring.version}</version>
    </dependency>
  </dependencies>
redis.properties配置
redis.hostName=47.100.191.44
redis.port=6379
redis.password=xiaoli_redis
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

 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.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>

注解式开发及应用场景

注解式开发是一种基于注解的编程模型,它允许在代码中声明注解,以此来描述应用程序的元素和行为。注解式开发可以提高代码的可读性、可维护性和可扩展性,常用于各种框架和库中,如Spring、Hibernate、JUnit等。

以下是注解式开发应用的一些场景:

  1. 配置和管理对象声明:通过注解来描述对象的属性和行为,可以减少配置文件的数量和复杂度,同时也提高了代码的可读性和可维护性。
  2. 实现声明式事务处理:在方法上使用注解来声明事务的属性和行为,可以使事务处理更加简单和可控。
  3. 实现依赖注入:注解可以用于标记需要注入的对象或属性,从而使依赖注入更加简单和灵活。
  4. 执行AOP切面:通过注解来声明切面和切点,可以在运行时动态地织入切面。
  5. 描述测试用例:通过注解来描述测试用例的属性和行为,可以使测试代码更加简洁和可读。

总之,注解式开发的应用场景非常广泛,可以在各种类型的应用程序中使用,从而提高代码的可维护性和可扩展性。

@Cacheable

@Cacheable是Spring框架中的一个注解,用于将方法的返回值缓存起来,以提高应用程序的性能。当在相同参数下再次调用该方法时,会直接从缓存中获取结果,而不是重新执行一遍方法。


@Cacheable可以标注在类或方法上。当标注在类上时,表示该类的所有方法都可以被缓存。当标注在方法上时,表示该方法可以被缓存。


@Cacheable可以设置以下属性:


  • value:缓存的名称,必填项。
  • key:缓存的键值,可以使用SpEL表达式,缺省值为方法的所有参数。
  • condition:缓存的条件,可以使用SpEL表达式,缺省值为“true”。
  • unless:缓存的结果是否需要反向存储,可以使用SpEL表达式。

以下是一个使用@Cacheable注解的示例:

@Cacheable(value = "myCache", key = "#id") public User getUserById(String id) { User user = userRepository.findById(id); return user; }

在这个示例中,getUserById方法的返回值会被缓存起来,并放入名称为“myCache”的缓存中,缓存的键值为方法的参数id。当再次调用该方法时,如果参数id相同,则直接从缓存中获取结果,而不是重新执行一遍方法。

@CachePut

@CachePut是Spring框架中的一个注解,用于更新缓存中的数据。与@Cacheable注解不同的是,@CachePut注解无论缓存中是否存在对应的数据,都会执行方法并将返回值更新到缓存中。


@CachePut可以标注在类或方法上。当标注在类上时,表示该类的所有方法都可以被更新缓存。当标注在方法上时,表示该方法可以更新缓存。


@CachePut可以设置以下属性:


  • value:缓存的名称,必填项。
  • key:缓存的键值,可以使用SpEL表达式,缺省值为方法的所有参数。
  • condition:缓存的条件,可以使用SpEL表达式,缺省值为“true”。
  • unless:缓存的结果是否需要反向存储,可以使用SpEL表达式。

以下是一个使用@CachePut注解的示例:

@CachePut(value = "myCache", key = "#id") public User updateUserById(String id, User user) { userRepository.updateById(id, user); return user; }

在这个示例中,updateUserById方法会更新数据库中的数据,并将更新后的User对象放入名称为“myCache”的缓存中,缓存的键值为方法的参数id。无论缓存中是否存在对应的数据,都会执行该方法并更新缓存。

@CacheEvict

@CacheEvict是Spring框架中的一个注解,用于从缓存中删除数据。当我们更新或删除数据时,需要将缓存中的数据同步删除,避免脏数据的出现,这时可以使用@CacheEvict注解。


@CacheEvict可以标注在类或方法上。当标注在类上时,表示该类的所有方法都可以被删除缓存。当标注在方法上时,表示该方法可以删除缓存。


@CacheEvict可以设置以下属性:


  • value:缓存的名称,必填项。
  • key:缓存的键值,可以使用SpEL表达式,缺省值为方法的所有参数。
  • condition:删除缓存的条件,可以使用SpEL表达式,缺省值为“true”。
  • allEntries:是否删除缓存中的所有数据,缺省值为false。

以下是一个使用@CacheEvict注解的示例:

@CacheEvict(value = "myCache", key = "#id") public void deleteUserById(String id) { userRepository.deleteById(id); }

在这个示例中,deleteUserById方法会从数据库中删除对应的数据,并将名称为“myCache”、键值为id的缓存数据删除。如果allEntries属性设置为true,则会删除“myCache”中所有的数据。

击穿、穿透、雪崩

这三个术语都是与缓存相关的问题。

击穿

击穿指的是一个非常热点的数据在缓存中失效,此时大量请求直接请求到数据库,导致数据库压力骤增,进而导致系统性能急剧下降。通常的解决方案是设置热点数据永远不过期,或者使用互斥锁(比如Redis中的SETNX),只允许一个线程去更新缓存。


常见的解决方案有两种:


互斥锁


逻辑过期

穿透

穿透则是指请求的数据在缓存中不存在,且数据库中也不存在,这样大量请求会直接透过缓存请求到数据库上,造成数据库压力增大,系统性能下降。为避免这种情况,可以在缓存中加入空对象,并设置一个较短的过期时间,这样请求队列中的请求在得到空对象后就不会再去请求数据库。

解决方案

缓存null值

布隆过滤

增强id的复杂度,避免被猜测id规律

做好数据的基础格式校验

加强用户权限校验

做好热点参数的限流

雪崩

雪崩是指缓存中的大量数据同时失效,导致一大批请求直接访问数据库,造成数据库瞬间压力过大,系统崩溃。为了避免这种情况,可以在缓存中设置不同的过期时间,使得不同的数据在不同的时间失效,从而减轻数据库的压力。同时,可以设置本地缓存或者分布式锁来避免缓存失效时大量请求同时访问数据库的情况。


解决方案:


给不同的Key的TTL添加随机值


利用Redis集群提高服务的可用性


给缓存业务添加降级限流策略


给业务添加多级缓存

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
15天前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
26天前
|
缓存 NoSQL Java
Redis+Caffeine构建高性能二级缓存
大家好,我是摘星。今天为大家带来的是Redis+Caffeine构建高性能二级缓存,废话不多说直接开始~
178 0
|
2月前
|
NoSQL 安全 Java
深入理解 RedisConnectionFactory:Spring Data Redis 的核心组件
在 Spring Data Redis 中,`RedisConnectionFactory` 是核心组件,负责创建和管理与 Redis 的连接。它支持单机、集群及哨兵等多种模式,为上层组件(如 `RedisTemplate`)提供连接抽象。Spring 提供了 Lettuce 和 Jedis 两种主要实现,其中 Lettuce 因其线程安全和高性能特性被广泛推荐。通过手动配置或 Spring Boot 自动化配置,开发者可轻松集成 Redis,提升应用性能与扩展性。本文深入解析其作用、实现方式及常见问题解决方法,助你高效使用 Redis。
200 4
|
30天前
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
92 32
|
1月前
|
缓存 NoSQL Java
Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡
Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡
51 5
Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡
|
4月前
|
存储 Java 关系型数据库
ssm026校园美食交流系统(文档+源码)_kaic
本文介绍了基于Java语言和MySQL数据库的校园美食交流系统的设计与实现。该系统采用B/S架构和SSM框架,旨在提高校园美食信息管理的效率与便捷性。主要内容包括:系统的开发背景、目的及内容;对Java技术、MySQL数据库、B/S结构和SSM框架的介绍;系统分析部分涵盖可行性分析、性能分析和功能需求分析;最后详细描述了系统各功能模块的具体实现,如登录、管理员功能(美食分类管理、用户管理等)和前台首页功能。通过此系统,管理员可以高效管理美食信息,用户也能方便地获取和分享美食资讯,从而提升校园美食交流的管理水平和用户体验。
|
3月前
|
Java 关系型数据库 MySQL
weixin050高校体育场管理系统+ssm(文档+源码)_kaic
本文针对高校体育场管理系统的开发与实现进行详细介绍。随着经济快速发展,人们对手机软件需求增加,高校体育场管理系统应运而生。系统采用JAVA技术、Mysql数据库和SSM框架等成熟技术,通过分析功能需求、可行性及性能,设计出包含管理员、用户和学生角色的功能模块。系统实现用户注册登录、信息管理等功能,简化传统手工统计模式,提高管理效率,满足用户对信息获取的及时性与准确性需求。
weixin050高校体育场管理系统+ssm(文档+源码)_kaic
|
3月前
|
前端开发 Java 关系型数据库
基于ssm的社区物业管理系统,附源码+数据库+论文+任务书
社区物业管理系统采用B/S架构,基于Java语言开发,使用MySQL数据库。系统涵盖个人中心、用户管理、楼盘管理、收费管理、停车登记、报修与投诉管理等功能模块,方便管理员及用户操作。前端采用Vue、HTML、JavaScript等技术,后端使用SSM框架。系统支持远程安装调试,确保顺利运行。提供演示视频和详细文档截图,帮助用户快速上手。
145 17
|
3月前
|
前端开发 Java 关系型数据库
基于ssm的超市会员(积分)管理系统,附源码+数据库+论文,包安装调试
本项目为简单内容浏览和信息处理系统,具备管理员和员工权限。管理员可管理会员、员工、商品及积分记录,员工则负责积分、商品信息和兑换管理。技术框架采用Java编程语言,B/S架构,前端使用Vue+JSP+JavaScript+Css+LayUI,后端为SSM框架,数据库为MySQL。运行环境为Windows,JDK8+Tomcat8.5,非前后端分离的Maven项目。提供演示视频和详细文档,购买后支持免费远程安装调试。
171 19
|
3月前
|
前端开发 JavaScript Java
[Java计算机毕设]基于ssm的OA办公管理系统的设计与实现,附源码+数据库+论文+开题,包安装调试
OA办公管理系统是一款基于Java和SSM框架开发的B/S架构应用,适用于Windows系统。项目包含管理员、项目管理人员和普通用户三种角色,分别负责系统管理、请假审批、图书借阅等日常办公事务。系统使用Vue、HTML、JavaScript、CSS和LayUI构建前端,后端采用SSM框架,数据库为MySQL,共24张表。提供完整演示视频和详细文档截图,支持远程安装调试,确保顺利运行。
170 17