当前位置: 首页 > news >正文

成都网站建设公司兴田德润在哪儿产品代理推广方案

成都网站建设公司兴田德润在哪儿,产品代理推广方案,微信公众平台开发代理,顺的品牌网站建设目录 一、整合redis 1、介绍 1.1、redis(Remote Dictionary Server) 1.2、MySQL 1.3、区别 2、整合 2.1、配置 2.2、文件配置 2.3、key的生成规则方法 2.4、注意 二、redis注解式缓存 1、Cacheable注解 2、CachePut注解 3、CacheEvict注解…

目录

一、整合redis

1、介绍

1.1、redis(Remote Dictionary Server)

1.2、MySQL

1.3、区别

2、整合

2.1、配置

2.2、文件配置

2.3、key的生成规则方法

2.4、注意

二、redis注解式缓存

1、@Cacheable注解

2、@CachePut注解

3、@CacheEvict注解

4、应用场景

三、redis击穿穿透雪崩

1、击穿(Cache Miss)

2、穿透(Cache Penetration)

3、雪崩(Cache Avalanche)


一、整合redis

1、介绍

1.1、redis(Remote Dictionary Server)

  • Redis是一种基于内存的键值存储系统,它将数据存储在内存中,因此读写速度非常快。
  • Redis支持多种数据结构,如字符串、哈希、列表、集合、有序集合等,这使得Redis适用于各种应用场景,如缓存、消息队列、计数器等。
  • Redis具有高可用性和可扩展性,支持主从复制和分片,以实现数据的备份和负载均衡。
  • Redis的持久化方式有RDB(快照)和AOF(日志追加),可以将数据持久化到磁盘,保证数据的安全性。

1.2、MySQL

  • MySQL是一种关系型数据库管理系统,使用标准的SQL语言进行数据操作。
  • MySQL将数据存储在磁盘上,因此相对于Redis来说,读写速度较慢。
  • MySQL支持事务处理和复杂的查询,适用于需要处理结构化数据的应用,如网站、电子商务等。
  • MySQL具有较高的稳定性和成熟度,支持ACID特性(原子性、一致性、隔离性、持久性),可以保证数据的完整性和一致性。

1.3、区别

  1. redis是nosql数据库

  2. MySQL是sql数据库

更一步的理解:

  • 存储方式:Redis将数据存储在内存中,而MySQL将数据存储在磁盘中。
  • 数据结构:Redis支持多种数据结构,MySQL使用表格和关系进行数据存储。
  • 读写性能:由于Redis使用内存存储,读写速度较快,而MySQL较慢。
  • 功能特性:Redis适用于缓存和实时数据处理,MySQL适用于结构化数据的存储和复杂查询。
  • ACID特性:MySQL支持事务处理和ACID特性,而Redis在默认情况下不支持事务处理。
  • 持久化方式:Redis可以将数据持久化到磁盘,MySQL具有多种持久化方式,如日志文件和复制。

2、整合

2.1、配置

创建ssm的项目,在配置文件的pom文件添加

<redis.version>2.9.0</redis.version>
<redis.spring.version>1.7.1.RELEASE</redis.spring.version><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>

2.2、文件配置

编写一个配置文件redis.properties,在我们的resources包里面。

redis.hostName:对应的IP地址
redis.port:对应的端口号
redis.password:对应的redis连接的密码

redis.hostName=localhsot
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里面包含了

  1. 添加注册
  2. redis的连接池配置:对应的value值是redis.properties里面的配置
  3. redis的的连接工厂:这里就用到了连接池的配置redis。
  4. 配置序列化:里面有string、json、hash的序列化器
  5. 配置key的生成
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/cachehttp://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="${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.tgq.ssm.redis.CacheKeyGenerator"></bean><!--7.启用缓存注解功能--><cache:annotation-driven cache-manager="redisCacheManager" key-generator="cacheKeyGenerator"/>
</beans>

redis.propertiesjdbc.properties在与Spring做整合时会发生冲突;所以引入配置文件的地方要放到applicationContext.xml

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>

2.3、key的生成规则方法

spring-redis.xml的最后的配置就说明了键的配置规则。

package com.tgq.ssm.redis;import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.util.ClassUtils;import java.lang.reflect.Array;
import java.lang.reflect.Method;@Slf4j
public class CacheKeyGenerator implements KeyGenerator {// custom cache keypublic static final int NO_PARAM_KEY = 0;public static final int NULL_PARAM_KEY = 53;@Overridepublic Object generate(Object target, Method method, Object... params) {StringBuilder key = new StringBuilder();key.append(target.getClass().getSimpleName()).append(".").append(method.getName()).append(":");if (params.length == 0) {key.append(NO_PARAM_KEY);} else {int count = 0;for (Object param : params) {if (0 != count) {//参数之间用,进行分隔key.append(',');}if (param == null) {key.append(NULL_PARAM_KEY);} else if (ClassUtils.isPrimitiveArray(param.getClass())) {int length = Array.getLength(param);for (int i = 0; i < length; i++) {key.append(Array.get(param, i));key.append(',');}} else if (ClassUtils.isPrimitiveOrWrapper(param.getClass()) || param instanceof String) {key.append(param);} else {//Java一定要重写hashCode和eqaulskey.append(param.hashCode());}count++;}}String finalKey = key.toString();
//        IEDA要安装lombok插件log.debug("using cache key={}", finalKey);return finalKey;}
}

2.4、注意

  1. applicationContext.xml中注册多个.properties结尾配置,那么不能在spring-*.xml添加注册。
  2. resources的配置必须要涵盖读取.properties结尾的文件。
  3. redisTemplate的使用可以参考jdbcTemplate、amqpTemplate、rabbitMQTemplate等。

二、redis注解式缓存

1、@Cacheable注解


        配置在方法或类上,作用:本方法执行后,先去缓存看有没有数据,如果没有,从数据库中查找出来,给缓存中存一份,返回结果,
        下次本方法执行,在缓存未过期情况下,先在缓存中查找,有的话直接返回,没有的话从数据库查找。

value缓存位置的一段名称,不能为空
key缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL
condition触发条件,满足条件就加入缓存,默认为空,表示全部都加入缓存,支持SpEL

  • @Cacheable测试

但我们调用查询的方法而没有用@Cacheable注解的时候我们可以看到我们查询出来的结果是两个,而且查询了数据库两次。

当我们用到@Cacheable注解的时候我们只查询了数据库一次,如果再次查询就不会出现sql语句,而且已经缓存到了redis里面。

测试结果:redis中有数据,则访问redis;如果没有数据,则访问MySQL;

  • 改变原有的key生成规则

改变原有的规则之后我们再次运行,我们的redis的键就不一样了。

condition:当某个值大于或者小于某个值才进行缓存。

2、@CachePut注解

        类似于更新操作,即每次不管缓存中有没有结果,都从数据库查找结果,并将结果更新到缓存,并返回结果。

value:缓存的名称,在 spring 配置文件中定义,必须指定至少一个。
key:缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合。
condition:缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存。

当我们使用它测试出来的结果则是:只存不取

  • @Cacheable与@CachePut区别

@Cacheable 注解表示方法的返回值可以被缓存,下次访问相同的方法时,会直接从缓存中获取结果,而不会再执行方法内部的逻辑。该注解标记在方法上,指定了缓存的名称(也可以使用默认的缓存名称),也可以通过参数指定缓存的Key。如果缓存中已有相应的Key存在,则会直接返回缓存中的值;若缓存中不存在对应的Key,则会执行方法,并将方法的返回值添加到缓存中。

@CachePut 注解表示无条件地执行方法内部的逻辑,并将方法的返回值添加到缓存中。该注解也标记在方法上,通常用于更新缓存的操作。它与 @Cacheable 注解的不同之处在于,每次调用带有 @CachePut 注解的方法时,都会执行方法内部的逻辑,并将结果添加到缓存中,覆盖原有的缓存值。

@CachePut 注解常用于需要更新缓存中数据的场景,可以保证每次调用方法时都会执行方法内部的逻辑,并更新缓存的结果。

Cacheable:会在redis中存储数据,同时也会读取数据。

CachePut:会在redis中写数据,不会读取数据。

3、@CacheEvict注解

        用来清除用在本方法或者类上的缓存数据(用在哪里清除哪里)

value:缓存位置的一段名称,不能为空
key:缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL
condition:触发条件,满足条件就加入缓存,默认为空,表示全部都加入缓存,支持SpEL
allEntries:true表示清除value中的全部缓存,默认为false

测试结果:可以配置删除指定缓存数据,也可以删除符合规则的所有缓存数据;

4、应用场景

Redis注解式缓存是一种通过使用注解来简化缓存操作的方法,它可以方便地在方法调用前后自动进行缓存的读取和写入。以下是Redis注解式缓存的常见应用场景:

  1. 方法结果缓存:对于一些计算成本较高的方法,可以使用注解将其结果缓存起来,避免重复计算。当下次调用相同的方法时,可以直接从缓存中获取结果,提高性能并减轻服务器负载。

  2. 数据查询缓存:对于频繁读取的数据查询操作,可以使用注解将查询结果缓存起来。这样可以避免反复查询数据库,提高系统的响应速度。

  3. 限流和熔断:通过使用注解实现限流,可以控制对某些资源或接口的并发请求量,避免系统过载。同时,可以设置特定的缓存时间,当资源或接口不可用时,返回缓存中的数据,实现熔断降级。

  4. 防止缓存穿透:通过使用注解和布隆过滤器等技术,可以在查询之前拦截请求,并且判断缓存中是否存在对应的数据。如果不存在,则直接返回空值,避免对数据库的无效查询。

  5. 异步刷新缓存:通过使用注解和异步任务,在数据更新时可以同时异步地更新相应的缓存,保持缓存和数据库的一致性。

三、redis击穿穿透雪崩

        redis的简单的作用:能够极大的减轻MySQL的访问压力

        大部分的解决方案需要根据具体的场景和需求选择合适的解决方案。同时,合理的缓存策略、数据预热和监控是缓解这些问题的关键,以确保系统的稳定性和可靠性。

1、击穿(Cache Miss)

什么事缓存击穿?

        缓存击穿就是在处于集中式高并发访问的情况下,当某个热点 key 在失效的瞬间,大量的请求在缓存中获取不到。瞬间击穿了缓存,所有请求直接打到数据库,就像是在一道屏障上击穿了一个洞。

高并发量的同时key失效,导致请求直接到达数据库;

  • 解决方案之一:设置锁
    • 使用互斥锁(Mutex Lock)或分布式锁(Distributed Lock)来防止并发请求同时访问数据库。
      • 获取 Redis 锁,如果没有获取到,则回到任务队列继续排队
      • 获取到锁,从数据库拉取数据并放入缓存中
      • 释放锁,其他请求从缓存中拿到数据
  • 另一种方式:限流
    • 在缓存中设置短暂的过期时间,并使用异步更新机制,即在缓存失效时,只有一个请求重新加载数据到缓存中,其他请求等待缓存数据更新完成后再读取。
    • 请求redis之前做流量削峰

2、穿透(Cache Penetration)

很多请求都在访问数据库一定不存在的数据,造成请求将缓存和数据库都穿透的情况。 

解决方案如下:

  • 规则排除:
    1. 使用布隆过滤器(Bloom Filter)等数据结构来过滤不存在的请求,在查询缓存之前先进行判断,避免对数据库进行不必要的查询。
    2. 或者可以增加一些参数检验。例如数据库数据 id 一般都是递增的,如果请求 id = -10 这种参数,势必绕过Redis。避免这种情况,可以对用户真实性检验等操作。
  • 缓存空值(Null Cache):
    1. 即将空结果缓存一段时间,以避免频繁查询不存在的数据。
    2. 可以理解为当缓存穿透时,redis存入一个类似null的值,下次访问则直接缓存返回空,当数据库中存在该数据的值则需要把redis存在的null值清除并载入新值,此方案不能解决频繁随机不规则的key请求。

3、雪崩(Cache Avalanche)

 雪崩和击穿类似,不同的是击穿是一个热点 Key 某时刻失效,而雪崩是大量的热点 Key 在一瞬间失效 。

方案如下:

  • 设置合适的缓存失效时间,可以使用随机值或添加一定的时间偏移量,避免多个键同时失效,导致数据库负载过大。
  • 使用多级缓存架构,将缓存分为多个层次,如本地缓存、分布式缓存等,提高缓存命中率和可用性。
  • 实时监控缓存健康状态,当缓存出现异常时,采取相应的措施,如自动降级、限流等,保护后端系统。

更快捷的解决方案是:给不同的热点key设置不同的缓存策略

http://www.15wanjia.com/news/31441.html

相关文章:

  • dw做的网站能搜到吗淄博头条新闻今天
  • 免费b2b网站大全免费黄页软文写作范文500字
  • 福永网站建设线上培训
  • 定制网站建设公司哪家好bing搜索引擎入口官网
  • 电子商务网站建设实训总结电脑优化工具
  • 网站开发+职位描述南京seo网络优化公司
  • 深圳网站建设公司简介it培训
  • 大连公司名称大全福清市百度seo
  • 怎么用百度云做网站空间怎么提高关键词搜索排名
  • 成都市网站建设哪家好最近三天的新闻大事简短
  • 网站动态图怎么做百度认证怎么认证
  • 广州网站建设公司有哪些南京seo收费
  • udacity 网站开发怎样注册个人网站
  • 做网站用模版公司网站免费自建
  • 云虚拟主机可以做多少个网站国外搜索引擎
  • 东莞专业网站推广方式长沙seo排名公司
  • 谷歌网站管理员账号seo网络推广知识
  • 昆明网站建设 技术支持技术培训
  • 新闻摘抄大全苏州seo优化
  • 网站的折线图怎么做郑州见效果付费优化公司
  • 江苏网站建设官网简述搜索引擎优化的方法
  • 长白山网站学做管理平台网易企业邮箱
  • 网站安全建设方案前言郑州网站建设优化
  • 门户网站模块百度推广开户免费
  • 网站建设有免费的吗湖北短视频seo营销
  • 客服24小时在线服务qq群排名优化软件购买
  • 扁平风网站免费b2b推广网站大全
  • 贸易网站模板百度一下打开网页
  • 珠海网站建设科速互联网站批量查询
  • 专门做设计的网站百度浏览器打开