Redis integriert den Spring-Annotation-Cache mit SSM

Inhaltsverzeichnis

1. Integration

1.1. Integrierte Anwendungen

1.1.1.pom-Konfiguration

1.1.2.Erforderliche Konfiguration

2. Annotationsentwicklung und Anwendungsszenarien

2.1. @Cacheable

2.2. @CachePut 

2.3. @CacheEvict

2.4. Zusammenfassung

3. Redis‘ Zusammenbruch und Penetrationslawine

                Das war `s für heute! ! Hoffe das hilft! !​ 


1. Integration

1.1. Integrierte Anwendungen

1.1.1.pom-Konfiguration

Redis-Abhängigkeit in der Datei pom.xml des Projekts hinzufügen

 Im Folgenden sind alle importierten Abhängigkeiten aufgeführt: 

<?xml version="1.0" encoding="UTF-8"?>
 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>org.example</groupId>
  <artifactId>ssm2</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>
 
  <name>ssm2 Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>
 
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.plugin.version>3.7.0</maven.compiler.plugin.version>
 
    <!--添加jar包依赖-->
    <!--1.spring 5.0.2.RELEASE相关-->
    <spring.version>5.0.2.RELEASE</spring.version>
    <!--2.mybatis相关-->
    <mybatis.version>3.4.5</mybatis.version>
    <!--mysql-->
    <mysql.version>5.1.44</mysql.version>
    <!--pagehelper分页jar依赖-->
    <pagehelper.version>5.1.2</pagehelper.version>
    <!--mybatis与spring集成jar依赖-->
    <mybatis.spring.version>1.3.1</mybatis.spring.version>
    <!--3.dbcp2连接池相关 druid-->
    <commons.dbcp2.version>2.1.1</commons.dbcp2.version>
    <commons.pool2.version>2.4.3</commons.pool2.version>
    <!--4.log日志相关-->
    <log4j2.version>2.9.1</log4j2.version>
    <!--5.其他-->
    <junit.version>4.12</junit.version>
    <servlet.version>4.0.0</servlet.version>
    <lombok.version>1.18.2</lombok.version>
 
    <ehcache.version>2.10.0</ehcache.version>
    <slf4j-api.version>1.7.7</slf4j-api.version>
 
    <redis.version>2.9.0</redis.version>
    <redis.spring.version>1.7.1.RELEASE</redis.spring.version>
  </properties>
 
  <dependencies>
    <!--1.spring相关-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
 
    <!--2.mybatis相关-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
    </dependency>
    <!--mysql-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>
    <!--pagehelper分页插件jar包依赖-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>${pagehelper.version}</version>
    </dependency>
    <!--mybatis与spring集成jar包依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>${mybatis.spring.version}</version>
    </dependency>
 
    <!--3.dbcp2连接池相关-->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-dbcp2</artifactId>
      <version>${commons.dbcp2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
      <version>${commons.pool2.version}</version>
    </dependency>
 
    <!--4.log日志相关依赖-->
    <!--核心log4j2jar包-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
    <!--web工程需要包含log4j-web,非web工程不需要-->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-web</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
 
    <!--5.其他-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>${lombok.version}</version>
      <scope>provided</scope>
    </dependency>
 
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
 
    <!-- jsp依赖-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.3</version>
    </dependency>
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>
 
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.3</version>
    </dependency>
 
<!--    做服务端参数校验 JSR303 的jar包依赖 -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.7.Final</version>
    </dependency>
 
<!--    用来SpringMVC支持json数据转换-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.3</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.3</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.3</version>
    </dependency>
 
<!--    shiro相关依赖 -->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.3.2</version>
    </dependency>
 
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.3.2</version>
    </dependency>
 
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.3.2</version>
    </dependency>
 
    <dependency>
      <groupId>net.sf.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>${ehcache.version}</version>
    </dependency>
 
    <!-- slf4j核心包 -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j-api.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>jcl-over-slf4j</artifactId>
      <version>${slf4j-api.version}</version>
      <scope>runtime</scope>
    </dependency>
 
    <!--用于与slf4j保持桥接 -->
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j-impl</artifactId>
      <version>${log4j2.version}</version>
    </dependency>
 
    <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>
 
  <build>
    <finalName>ssm2</finalName>
    <resources>
      <!--解决mybatis-generator-maven-plugin运行时没有将XxxMapper.xml文件放入target文件夹的问题-->
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
      <!--解决mybatis-generator-maven-plugin运行时没有将jdbc.properites文件放入target文件夹的问题-->
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>*.properties</include>
          <include>*.xml</include>
        </includes>
      </resource>
    </resources>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>${maven.compiler.plugin.version}</version>
          <configuration>
            <source>${maven.compiler.source}</source>
            <target>${maven.compiler.target}</target>
            <encoding>${project.build.sourceEncoding}</encoding>
          </configuration>
        </plugin>
        <plugin>
          <groupId>org.mybatis.generator</groupId>
          <artifactId>mybatis-generator-maven-plugin</artifactId>
          <version>1.3.2</version>
          <dependencies>
            <!--使用Mybatis-generator插件不能使用太高版本的mysql驱动 -->
            <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>${mysql.version}</version>
            </dependency>
          </dependencies>
          <configuration>
            <overwrite>true</overwrite>
          </configuration>
        </plugin>
 
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

1.1.2.Erforderliche Konfiguration

Erstellen Sie eine spring-readis.xml im SSM-Projekt, konfigurieren Sie die Redis-Verbindungsinformationen, konfigurieren Sie die Datenquelle, konfigurieren Sie den Serializer und die Redis-Schlüsselgenerierung Strategie, konfigurieren Sie RedisTemplate.

Erstellen redis.properties Schreiben Sie Datenverbindungsinformationen, einschließlich Hostname, Portnummer, Passwort usw.

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

  Erstellen Sie die Konfigurationsdatei spring-redis.xml und konfigurieren Sie darin Folgendes

Konfiguration des Redis-Verbindungspools

 <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>

Konfigurieren Sie die Redis-Verbindungsfabrik

    <!-- 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>

Redis-Vorgangsvorlage

    <!-- 4. redis操作模板,使用该对象可以操作redis
        相当于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>

Cache-Manager konfigurieren

    <!--  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>

Erstellen Sie CacheKeyGenerator.java Konfigurieren Sie die Generierungsregeln für im Cache generierte Schlüsselnamen

package com.junlinyi.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 key
    public static final int NO_PARAM_KEY = 0;
    public static final int NULL_PARAM_KEY = 53;
 
    @Override
    public 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和eqauls
                    key.append(param.hashCode());
                }
                count++;
            }
        }
 
        String finalKey = key.toString();
//        IEDA要安装lombok插件
        log.debug("using cache key={}", finalKey);
        return finalKey;
    }
}

 Schließlich spring-redis.xml Alle Konfigurationen der Konfigurationsdatei lauten wie folgt: 

<?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="${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操作模板,使用该对象可以操作redis
        相当于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.junlinyi.ssm.redis.CacheKeyGenerator"></bean>
 
    <!--7.启用缓存注解功能-->
    <cache:annotation-driven cache-manager="redisCacheManager" key-generator="cacheKeyGenerator"/>
</beans>

 Erstellen Sie applicationContext-shiro.xml Konfigurationsdatei 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <!--配置自定义的Realm-->
    <bean id="shiroRealm" class="com.junlinyi.ssm.shiro.MyRealm">
        <property name="userBiz" ref="userBiz" />
        <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
        <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
        <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
        <!--以下三个配置告诉shiro将如何对用户传来的明文密码进行加密-->
        <property name="credentialsMatcher">
            <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <!--指定hash算法为MD5-->
                <property name="hashAlgorithmName" value="md5"/>
                <!--指定散列次数为1024次-->
                <property name="hashIterations" value="1024"/>
                <!--true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储-->
                <property name="storedCredentialsHexEncoded" value="true"/>
            </bean>
        </property>
    </bean>
 
    <!--注册安全管理器-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="sessionManager" ref="sessionManager"></property>
        <property name="realm" ref="shiroRealm" />
    </bean>
 
    <!--Shiro核心过滤器-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,这个属性是必须的 -->
        <property name="securityManager" ref="securityManager" />
        <!-- 身份验证失败,跳转到登录页面 -->
        <property name="loginUrl" value="/login"/>
        <!-- 身份验证成功,跳转到指定页面 -->
        <!--<property name="successUrl" value="/index.jsp"/>-->
        <!-- 权限验证失败,跳转到指定页面 -->
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
        <!-- Shiro连接约束配置,即过滤链的定义 -->
        <property name="filterChainDefinitions">
            <value>
                <!--
                注:anon,authcBasic,auchc,user是认证过滤器
                    perms,roles,ssl,rest,port是授权过滤器
                -->
                <!--anon 表示匿名访问,不需要认证以及授权-->
                <!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
                <!--roles[admin]表示角色认证,必须是拥有admin角色的用户才行-->
                /user/login=anon
                /user/updatePwd.jsp=authc
                /admin/*.jsp=roles[4]
                /user/teacher.jsp=perms[2]
                <!-- /css/**               = anon
                 /images/**            = anon
                 /js/**                = anon
                 /                     = anon
                 /user/logout          = logout
                 /user/**              = anon
                 /userInfo/**          = authc
                 /dict/**              = authc
                 /console/**           = roles[admin]
                 /**                   = anon-->
            </value>
        </property>
    </bean>
 
    <!-- Shiro生命周期,保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
 
 
    <!-- Session ID 生成器 -->
    <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator">
    </bean>
 
    <!--sessionDao自定义会话管理,针对Session会话进行CRUD操作-->
    <bean id="customSessionDao" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO">
        <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
    </bean>
 
    <!--会话监听器-->
    <bean id="shiroSessionListener" class="com.junlinyi.ssm.shiro.MySessionListener"/>
 
    <!--会话cookie模板-->
    <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <!--设置cookie的name-->
        <constructor-arg value="shiro.session"/>
        <!--设置cookie有效时间 永不过期-->
        <property name="maxAge" value="-1"/>
        <!--设置httpOnly 防止xss攻击:cookie劫持-->
        <property name="httpOnly" value="true"/>
    </bean>
 
    <!--SessionManager会话管理器-->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <!--设置session会话过期时间 毫秒 2分钟=120000-->
        <property name="globalSessionTimeout" value="120000"/>
        <!--设置sessionDao-->
        <property name="sessionDAO" ref="customSessionDao"/>
        <!--设置间隔多久检查一次session的有效性 默认1分钟-->
        <property name="sessionValidationInterval" value="60000"/>
        <!--配置会话验证调度器-->
        <!--<property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>-->
        <!--是否开启检测,默认开启-->
        <!--<property name="sessionValidationSchedulerEnabled" value="true"/>-->
        <!--是否删除无效的session,默认开启-->
        <property name="deleteInvalidSessions" value="true"/>
        <!--配置session监听器-->
        <property name="sessionListeners">
            <list>
                <ref bean="shiroSessionListener"/>
            </list>
        </property>
        <!--会话Cookie模板-->
        <property name="sessionIdCookie" ref="sessionIdCookie"/>
        <!--取消URL后面的JSESSIONID-->
        <property name="sessionIdUrlRewritingEnabled" value="true"/>
    </bean>
</beans>

 Verweisen Sie auf die obige Konfigurationsdatei in der referenzierten Konfigurationsdatei, z. B. 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>

 Das Obige sind die grundlegenden Konfigurationsschritte, die je nach spezifischen Projektanforderungen und Framework-Versionen variieren können. In tatsächlichen Anwendungen können Sie nach Bedarf auch den Cluster, den Sentinel-Modus, die Persistenz und andere Funktionen von Redis konfigurieren, um die Verfügbarkeit und Zuverlässigkeit des Systems zu verbessern.

2. Annotationsentwicklung und Anwendungsszenarien

2.1. @Cachebar

@Cacheable ist eine Annotation im Spring Framework, die verwendet wird, um zu deklarieren, dass der Rückgabewert einer Methode zwischengespeichert werden kann. Dies bedeutet, dass der Rückgabewert der Methode im Speicher zwischengespeichert wird, sodass nachfolgende Aufrufe das zwischengespeicherte Ergebnis direkt zurückgeben können, ohne die Methode erneut auszuführen.

Im Einzelnen funktioniert@Cacheable-Annotation wie folgt:

1. Cache-Ergebnisse:Wenn eine mit der @Cacheable-Annotation geänderte Methode aufgerufen wird, prüft Spring zunächst, ob das Rückgabeergebnis der Methode im Cache vorhanden ist. Wenn es bereits im Cache vorhanden ist, wird das Ergebnis im Cache direkt zurückgegeben, ohne dass die Codelogik im Methodenkörper ausgeführt werden muss.

2. Cache-Schlüsselgenerierung:@CacheableDie Annotation kann einen Cache-Schlüssel (Schlüssel) angeben, um die Daten im Cache zu identifizieren. Standardmäßig besteht der Cache-Schlüssel aus den Parametern der Methode. Wenn die Methodenparameter in zwei Aufrufen gleich sind, wird derselbe Cache-Schlüssel verwendet und die Ergebnisse im Cache werden direkt zurückgegeben.

3. Cache-Verwaltung:@Cacheable Annotation kann in andere Cache-Verwaltungstools (wie Redis, Ehcache usw.) integriert werden. Durch die Konfiguration des entsprechenden Cache-Managers in der Konfigurationsdatei können die Rückgabeergebnisse der Methode für nachfolgende Aufrufe im angegebenen Cache gespeichert werden.

4. Cache-Ungültigmachung:@CacheableDie Annotation kann auch eine Ablaufzeit (TTL) angeben, um die Gültigkeitsdauer des Caches zu steuern. Wenn die Cache-Gültigkeitsdauer abläuft, wird beim nächsten Aufruf der Methode die Codelogik im Methodenkörper erneut ausgeführt und die neuen Ergebnisse werden im Cache gespeichert.
Durch die Verwendung der @Cacheable-Annotation kann die Anzahl der Zugriffe auf die Datenbank oder andere Ressourcen effektiv reduziert und die Reaktionsgeschwindigkeit und die gleichzeitigen Verarbeitungsfähigkeiten des Systems verbessert werden . Beachten Sie jedoch, dass Sie bei der Verwendung des Caches ein Gleichgewicht zwischen Konsistenz und Echtzeitleistung des Caches herstellen müssen, um Dateninkonsistenzen oder Probleme mit dem Ablauf zu vermeiden.

Häufig verwendete Eigenschaften und Verwendung

Die Annotation @Cacheable verfügt über die folgenden allgemeinen Attribute und Verwendungsfunktionen:

 

Wert:Gibt den Namen des Caches an, der zur Unterscheidung verschiedener Cache-Bereiche verwendet wird. Der entsprechende Cache-Manager kann in der Konfigurationsdatei so konfiguriert werden, dass er entscheidet, in welchem ​​Cache-Bereich der Cache gespeichert wird. Es können mehrere Cache-Namen angegeben werden, getrennt durch Kommas.

key:Gibt den Cache-Schlüssel an, der zur Identifizierung der Daten im Cache verwendet wird. Standardmäßig besteht der Cache-Schlüssel aus den Parametern der Methode. Der Cache-Schlüssel kann mithilfe eines SpEL-Ausdrucks angegeben werden, zum Beispiel: @Cacheable(key = "#id"), wobei id der Parameter der Methode ist.

Bedingung:Gibt einen SpEL-Ausdruck an, um zu bestimmen, ob eine Cache-Operation ausgeführt werden soll. Der Cache-Vorgang wird nur ausgeführt, wenn der Ausdruck „true“ ergibt. Beispiel: @Cacheable(condition = "#result != null"), was bedeutet, dass der Cache-Vorgang nur ausgeführt wird, wenn das Rückgabeergebnis der Methode nicht leer ist.

es sei denn:Gibt einen SpEL-Ausdruck an, um zu bestimmen, ob Cache-Vorgänge ausgeführt werden sollen. Der Cache-Vorgang wird nur ausgeführt, wenn der Ausdruck „falsch“ ergibt. Beispiel: @Cacheable(unless = "#result == null") bedeutet, dass der Cache-Vorgang nur dann nicht ausgeführt wird, wenn das Rückgabeergebnis der Methode leer ist.

keyGenerator:Gibt einen benutzerdefinierten Cache-Schlüsselgenerator an, der zum Generieren von Cache-Schlüsseln verwendet wird. Sie können die KeyGenerator-Schnittstelle implementieren, um die Logik zur Cache-Schlüsselgenerierung anzupassen.
Mithilfe der Annotation @Cacheable können die Rückgabeergebnisse der Methode zwischengespeichert werden, wodurch die Reaktionsgeschwindigkeit und die gleichzeitigen Verarbeitungsmöglichkeiten des Systems verbessert werden . Sie können Ihren Cache detaillierter steuern, indem Sie Eigenschaften wie Cache-Name, Cache-Schlüssel, Bedingungen und Schlüsselgeneratoren angeben. Gleichzeitig muss darauf geachtet werden, die Cache-Konsistenz und die Echtzeitleistung in Einklang zu bringen, um Dateninkonsistenzen oder Ablaufprobleme zu vermeiden.

Grundlegendes Anwendungsbeispiel:

@Cacheable(value = "clz" ,key = "'cid'+#cid")

 Erläuterung der Eigenschaften innerhalb der Nutzung: 

  • Wert: wird verwendet, um den Namen des Caches anzugeben. Sie können in der Konfigurationsdatei verschiedene Cache-Manager definieren. Der „Wert“ gibt hier den zu verwendenden Cache an.
  • Schlüsselattribut: Verwenden Sie den SpEL-Ausdruck „'cid'+#cid“, um den Cache-Schlüssel zu generieren. Dieser Schlüssel wird dynamisch aus dem Wert des cid-Parameters der Methode generiert. Wenn beim Aufruf der Methode unterschiedliche CID-Werte übergeben werden, werden unterschiedliche Cache-Schlüssel generiert, sodass unterschiedliche CID-Werte unterschiedlichen Cache-Elementen entsprechen. Dadurch können Sie zwischengespeicherte Daten in verschiedenen Kontexten speichern und abrufen.

2.2. @CachePut 

@CachePut ist eine Annotation im Spring Framework, die zum Speichern des Rückgabewerts einer Methode im Cache verwendet wird und normalerweise zum Aktualisieren der Daten im Cache verwendet wird.

@CachePut-Methodenfunktion:

  1. Cache-Daten aktualisieren:@CachePut wird verwendet, um zu erzwingen, dass der Rückgabewert einer Methode im Cache gespeichert wird, unabhängig davon, ob derselbe Schlüssel bereits im Cache vorhanden ist. Dies ist nützlich, um sicherzustellen, dass die Daten im Cache aktuell sind, insbesondere wenn die zwischengespeicherten Daten manuell aktualisiert werden müssen.
  2. Cache-Schlüssel dynamisch generieren:Mit @CachePut können Sie SpEL-Ausdrücke (Spring Expression Language) verwenden, um Schlüssel für Cache-Elemente dynamisch zu generieren. Dadurch können Sie Cache-Schlüssel basierend auf Methodenparametern oder anderen Bedingungen generieren, um sicherzustellen, dass verschiedene Cache-Elemente unterschiedliche Schlüssel haben.
  3. Bedingte Aktualisierung:@CachePut unterstützt Bedingungs- und Ausnahmeattribute, die steuern können, ob Cache-Aktualisierungsvorgänge basierend auf Bedingungen durchgeführt werden. Dadurch können Sie Ihren Cache flexibler verwalten, indem Sie den Cache nur unter bestimmten Bedingungen aktualisieren.
  4. Den angegebenen Cache-Eintrag löschen:Indem Sie das Attribut „allEntries“ auf „true“ konfigurieren, können Sie alle Cache-Einträge löschen, die sich auf den angegebenen Cache beziehen, anstatt nur einen bestimmten Cache-Eintrag zu aktualisieren.
  5. Update-Zeitpunkt steuern:Mit dem beforeInvocation-Attribut können Sie steuern, ob Cache-Updates vor oder nach erfolgreicher Ausführung der Methode ausgelöst werden.

Notiz:

  • Die @CachePut-Annotation wird zum Aktualisieren von Daten im Cache verwendet.Im Gegensatz zu @Cacheable führt sie den Methodenkörper aus und speichert den von der Methode zurückgegebenen Wert im Cache, um sicherzustellen, dass dies gewährleistet ist Caching Die Daten in sind die neuesten.
  • Wenn die Daten im Cache nicht vorhanden sind, erstellt @CachePut einen neuen Cache-Eintrag.

 Grundlegendes Anwendungsbeispiel:

@CachePut(value = "xx",key = "'cid:'+#cid")

Erläuterung der Eigenschaften innerhalb der Nutzung: 

  • @CachePutAnmerkungen werden zum Speichern des Rückgabewerts einer Methode im Cache verwendet und werden normalerweise zum Aktualisieren von Daten im Cache verwendet.
  • unterscheidet sich von @Cacheable. Es prüft nicht, ob derselbe Schlüssel bereits im Cache vorhanden ist. Stattdessen speichert es den Rückgabewert der Methode direkt im Cache, um sicherzustellen, dass der Die Daten im Cache sind auf dem neuesten Stand. von.
  • Dies ist nützlich, um Cache-Elemente zu aktualisieren und sicherzustellen, dass die Daten im Cache mit den Backend-Daten synchronisiert sind.

2.3. @CacheEvict

@CacheEvict ist eine Annotation im Spring Framework, die zum Entfernen bestimmter Cache-Elemente aus dem Cache oder zum Löschen des gesamten Caches verwendet wird.

@CacheEvict-Methodenfunktion:

 

  1. Angegebene Cache-Elemente löschen:Sie können @CacheEvict verwenden, um Cache-Elemente in einem oder mehreren bestimmten Caches zu löschen, um sicherzustellen, dass die Daten im Cache unter bestimmten Bedingungen auf dem neuesten Stand bleiben erfüllt sind. Cache leeren.
  2. Bedingtes Löschen:@CacheEvict unterstützt Bedingungs- und Ausnahmeattribute, die steuern können, ob Cache-Löschvorgänge basierend auf Bedingungen durchgeführt werden. Dadurch können Sie Ihren Cache flexibler verwalten, indem Sie den Cache nur dann leeren, wenn bestimmte Bedingungen erfüllt sind.
  3. Gesamten Cache löschen:Indem Sie die Eigenschaft „allEntries“ auf „true“ setzen, können Sie den gesamten Cache löschen, anstatt nur bestimmte Cache-Einträge zu löschen. Dies ist nützlich für Szenarien, in denen der Cache unter bestimmten Umständen global geleert werden muss.
  4. Löschzeitpunkt steuern:Mit dem beforeInvocation-Attribut können Sie steuern, ob der Cache-Löschvorgang vor oder nach erfolgreicher Ausführung der Methode ausgelöst wird.
  5. Mehrere Einträge aus dem Cache löschen:Sie können über das Schlüsselattribut einen Cache-Schlüsselausdruck festlegen, um Cache-Einträge zu löschen, die einem bestimmten Schlüsselmuster entsprechen. Dadurch können Sie zwischengespeicherte Elemente nach einem bestimmten Muster löschen.

Die Hauptfunktion der Annotation @CacheEvict besteht darin, bestimmte Cache-Elemente aus dem Cache zu entfernen oder den gesamten Cache zu leeren, um sicherzustellen, dass die Daten im Cache aktuell bleiben oder um den Cache basierend auf Bedingungen zu leeren. Es bietet mehrere Eigenschaften, mit denen Sie konfigurieren können, wie und wann der Cache je nach Bedarf geleert werden soll, um bestimmte Geschäftsanforderungen zu erfüllen.

 Grundlegendes Anwendungsbeispiel:

@CacheEvict(value = "xx",key = "'cid:'+#cid",allEntries = true)

 Erläuterung der Eigenschaften innerhalb der Nutzung:

  • Wertattribut: Auf „xx“ gesetzt, was angibt, dass der Cache mit dem Namen „xx“ geleert werden soll. Normalerweise müssen Sie den entsprechenden Cache-Manager in der Konfiguration definieren, um sicherzustellen, dass er diesem Cache-Namen zugeordnet ist.
  • Schlüsselattribut: Verwenden Sie den SpEL-Ausdruck „'cid:'+#cid“, um den Schlüssel für das Cache-Element zu generieren. Dieser Schlüssel wird dynamisch aus dem cid-Parameterwert der Methode mit dem Präfix „cid:“ generiert. Dadurch werden Cache-Einträge gelöscht, die mit „cid:“ gefolgt vom Parameterwert „cid“ übereinstimmen.
  • allEntries-Attribut: Auf „true“ setzen, um den gesamten Cache zu leeren. Wenn allEntries auf true gesetzt ist, wird das Schlüsselattribut ignoriert und alle zwischengespeicherten Einträge im angegebenen Cache werden gelöscht. In diesem Beispiel werden unabhängig vom Wert des Parameters cid alle Inhalte des Caches mit dem Namen „xx“ gelöscht.

2.4. Zusammenfassung

@Cacheable, @CachePut und @CacheEvict sind Annotationen, die zum Verwalten des Caches im Spring Framework verwendet werden. Sie haben unterschiedliche Funktionen und Verhaltensweisen:

  • @Cacheable:
  1. Funktion:@Cacheable wird verwendet, um zu deklarieren, dass der Rückgabewert einer Methode zwischengespeichert werden kann. Das heißt, wenn die Methode aufgerufen wird, überprüft Spring zunächst den Cache, wenn Das entsprechende Ergebnis ist im Cache vorhanden. Der zwischengespeicherte Wert wird zurückgegeben, ohne dass der Methodenkörper ausgeführt wird.
  2. Hauptzweck:Verbesserung der Leistung und Vermeidung wiederholter Ausführung derselben Methode, geeignet für Lesevorgänge, nicht zum Aktualisieren von Daten verwendet.
  3. Konfiguration:Sie können den Cache-Namen, den Cache-Schlüssel, Bedingungen usw. angeben.
  • @CachePut:
  1. Funktion:@CachePut wird verwendet, um die Speicherung des Rückgabewerts der Methode im Cache zu erzwingen, und wird normalerweise zum Aktualisieren der Daten im Cache verwendet.
  2. Hauptzweck:Aktualisieren Sie den Cache und legen Sie den von der Methode zurückgegebenen Wert in den Cache ab, der für Schreibvorgänge geeignet ist.
  3. Konfiguration:Sie können den Cache-Namen, den Cache-Schlüssel, Bedingungen usw. angeben.
  • @CacheEvict:
  1. Funktion:@CacheEvict wird verwendet, um das angegebene Cache-Element aus dem Cache zu entfernen oder den gesamten Cache zu leeren.
  2. Hauptzweck:Cache-Elemente löschen, die Daten im Cache auf dem neuesten Stand halten oder den Cache basierend auf Bedingungen leeren.
  3. Konfiguration:Sie können den Cache-Namen, den Cache-Schlüssel, Bedingungen, ob der gesamte Cache geleert werden soll usw. angeben.

Zusammenfassung der Unterschiede:

  • @Cacheable Wird zum Zwischenspeichern des Rückgabewerts einer Methode verwendet, um eine wiederholte Ausführung der Methode zu vermeiden, und eignet sich für Lesevorgänge.
  • @CachePut Wird zum Speichern des Rückgabewerts der Methode im Cache verwendet und wird normalerweise zum Aktualisieren der Daten im Cache verwendet, der für Schreibvorgänge geeignet ist.
  • @CacheEvict Wird zum Löschen von Cache-Elementen verwendet. Sie können bestimmte Cache-Elemente oder den gesamten Cache löschen.

Über die Verwendung: 

Diese Anmerkungen können je nach spezifischen Geschäftsanforderungen in Kombination verwendet werden, um flexible Caching-Strategien zu implementieren. Sie können beispielsweise @Cacheable  verwenden, um die Ergebnisse von Lesevorgängen zwischenzuspeichern,  zum Aktualisieren von Cache-Elementen verwenden und  zum Löschen verwenden die Daten im Cache, um unterschiedliche Caching-Anforderungen zu erfüllen.  @CachePut @CacheEvict

3. Redis‘ Zusammenbruch und Penetrationslawine

Bei Redis sind „Zusammenbruch“, „Penetration“ und „Lawine“ einige häufige Probleme im Zusammenhang mit der hohen Verfügbarkeit und Stabilität des Cache-Systems. Im Folgenden werde ich diese drei Fragen im Detail erläutern:

  • Cache-Aufschlüsselung:

Erscheint, wenn Hotspot-Daten ungültig sind. Wenn ein bestimmter Schlüssel abläuft und eine große Anzahl gleichzeitiger Anforderungen eingeht, umgehen diese Anforderungen den Cache und greifen direkt auf die Datenbank zu, was zu einem plötzlichen Anstieg des Datenbankdrucks führt. Dies liegt daran, dass die Daten nach der Ungültigmachung des Caches beim nächsten Zugriff nicht aus dem Cache abgerufen werden können, sondern aus der Datenbank abgerufen werden müssen.

  • Cache-Penetration:

Wenn ein böswilliger Benutzer einen Schlüssel anfordert, der nicht im Cache oder in der Datenbank vorhanden ist, kann das Cache-System die Daten nicht bereitstellen und diese Anfragen werden direkt an die Datenbank weitergeleitet. Dies kann zu einer erhöhten Datenbanklast oder sogar zu einem Denial-of-Service-Angriff führen. Um das Penetrationsproblem zu lösen, können Sie einen Nullwert festlegen, wenn der Schlüssel in der Abfrage nicht vorhanden ist, oder Methoden wie Bloom-Filter verwenden, um ungültige Anforderungen zu filtern.

  • 雪崩 (Cache Avalanche):

Wenn eine große Anzahl von Schlüsseln im Cache gleichzeitig ungültig wird, greift eine große Anzahl von Anforderungen direkt auf die Back-End-Datenbank zu, was zu einem plötzlichen Anstieg des Drucks auf die Datenbank und sogar zu einem Zusammenbruch führt. Dies ist normalerweise darauf zurückzuführen, dass die Daten im Cache auf die gleiche Ablaufzeit eingestellt sind, wodurch eine große Anzahl von Schlüsseln gleichzeitig abläuft und ein Lawineneffekt auftritt. Um Lawinenprobleme zu vermeiden, können Strategien wie eine zufällige Ablaufzeit und das Hinzufügen des Vorladens von Hotspot-Daten übernommen werden.

Um diese Probleme zu bekämpfen, können Sie folgende Lösungen wählen:

  • Bei Ausfallproblemen können Sie Mutex-Sperren verwenden oder eine kurze Ablaufzeit festlegen, um heiße Daten zu schützen und sicherzustellen, dass gültige Daten im Cache vorhanden sind.
  • Bei Penetrationsproblemen können Technologien wie Bloom-Filter zum Filtern ungültiger Anfragen eingesetzt werden, um sicherzustellen, dass das Cache-System nur gültige Anfragen verarbeitet.
  • Bei Lawinenproblemen können Strategien wie verteiltes Caching, mehrstufiges Caching und Cache-Vorwärmen verwendet werden, um eine gleichmäßige Verteilung der Daten im Cache sicherzustellen und den gleichzeitigen Ausfall einer großen Datenmenge zu vermeiden.

               Okay, das war's für heute! ! Hoffe das hilft! !​ 

Supongo que te gusta

Origin blog.csdn.net/m0_74915426/article/details/134353702
Recomendado
Clasificación