1. Integration of Redis and ssm
1.1 pom.xml configuration
Configure related redis files in pom.xml
redis file:
<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>
The entire pom.xml file:
<?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> <!--Add jar package dependencies--> <!--1.spring 5.0.2.RELEASE related--> <spring.version>5.0.2.RELEASE</spring.version> <!--2.mybatis related--> <mybatis.version>3.4.5</mybatis.version> <!--mysql--> <mysql.version>5.1.44</mysql.version> <!--pagehelper paging jar dependency--> <pagehelper.version>5.1.2</pagehelper.version> <!--mybatis and spring integrated jar dependencies--> <mybatis.spring.version>1.3.1</mybatis.spring.version> <!--3.dbcp2 connection pool related druid--> <commons.dbcp2.version>2.1.1</commons.dbcp2.version> <commons.pool2.version>2.4.3</commons.pool2.version> <!--4.log log related--> <log4j2.version>2.9.1</log4j2.version> <!--5.Others--> <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 related--> <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 related--> <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 paging plug-in jar package dependency--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pagehelper.version}</version> </dependency> <!--mybatis and spring integrated jar package dependencies--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis.spring.version}</version> </dependency> <!--3.dbcp2 connection pool related--> <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 related dependencies--> <!--Core log4j2jar package--> <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 projects need to include log4j-web, non-web projects do not need to include --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-web</artifactId> <version>${log4j2.version}</version> </dependency> <!--5.Others--> <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 --> <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> <!-- Do server-side parameter verification JSR303 jar package dependency --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.7.Final</version> </dependency> <!-- Used by SpringMVC to support json data conversion--> <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 related dependencies --> <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 core package --> <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> <!--Used to maintain a bridge with 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> <!--Solve the problem that the XxxMapper.xml file is not placed in the target folder when mybatis-generator-maven-plugin is running--> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <!--Solve the problem that the jdbc.properites file is not put into the target folder when mybatis-generator-maven-plugin is running--> <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> <!--Using the Mybatis-generator plug-in cannot use too high a version of mysql driver --> <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.2 spring-redis.xml configuration
This configuration file is mainly used to configure data sources and connection factories as well as configure serialization.
step:
① Register redis.properties
② Configure data source [connection]
③Connect factory
④ Configure serializer
⑤ Configure redis key generation strategy
See the code below for specific steps:
spring-redis.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. Introduce properties configuration file --> <context:property-placeholder location="classpath:redis.properties" /> <!-- 2. redis connection pool configuration --> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!--Maximum idle number--> <property name="maxIdle" value="300"/> <!--The maximum number of database connections in the connection pool --> <property name="maxTotal" value="${redis.maxTotal}"/> <!--Maximum waiting time to establish a connection--> <property name="maxWaitMillis" value="${redis.maxWaitMillis}"/> <!--Minimum idle time for evicted connections, default 1800000 milliseconds (30 minutes)--> <property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"/> <!--The maximum number of evictions during each eviction check. If it is a negative number, it is: 1/abs(n), default 3--> <property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"/> <!--The time interval for eviction scanning (milliseconds). If it is a negative number, the eviction thread will not run. The default is -1--> <property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"/> <!--Whether to check before taking out the connection from the pool, if the check fails, remove the connection from the pool and try to take out another one--> <property name="testOnBorrow" value="${redis.testOnBorrow}"/> <!--Check validity when idle, default false --> <property name="testWhileIdle" value="${redis.testWhileIdle}"/> </bean> <!-- 3. redis connection factory --> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy"> <property name="poolConfig" ref="poolConfig"/> <!--IP address --> <property name="hostName" value="${redis.hostName}"/> <!--Port number --> <property name="port" value="${redis.port}"/> <!--If Redis is set with a password --> <property name="password" value="${redis.password}"/> <!--The client timeout unit is milliseconds --> <property name="timeout" value="${redis.timeout}"/> </bean> <!-- 4. redis operation template, use this object to operate redis In the hibernate course, hibernatetemplete is equivalent to session and specializes in operating databases. --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <!--If Serializer is not configured, String will be used by default when storing. If the User type is used to store, the error User can't cast to String will be prompted! ! --> <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> <!--Open transaction --> <property name="enableTransactionSupport" value="true"/> </bean> <!-- 5. Configure cache manager --> <bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg name="redisOperations" ref="redisTemplate"/> <!--redis cache data expiration time unit seconds--> <property name="defaultExpiration" value="${redis.expiration}"/> <!--Whether to use cache prefix, related to cachePrefix--> <property name="usePrefix" value="true"/> <!--Configure cache prefix name--> <property name="cachePrefix"> <bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix"> <constructor-arg index="0" value="-cache-"/> </bean> </property> </bean> <!--6. Configure the generation rules for cache generated key names--> <bean id="cacheKeyGenerator" class="com.zking.ssm.redis.CacheKeyGenerator"></bean> <!--7. Enable cache annotation function--> <cache:annotation-driven cache-manager="redisCacheManager" key-generator="cacheKeyGenerator"/> </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
1.3 spring context configuration
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. Introduce external multi-file method --> <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> <!-- As you continue to learn, you will learn more and more frameworks. You cannot configure all frameworks in the same preparation room, otherwise it will be inconvenient to manage --> <import resource="applicationContext-mybatis.xml"></import> <import resource="spring-redis.xml"></import> <import resource="applicationContext-shiro.xml"></import> </beans>
Second, Redis annotation formula
① @Cacheable (can read and write)
@Cacheable is a caching annotation provided by the Spring framework, which is used to mark the return results of methods that can be cached to improve system performance.
as follows:
Test code:
classBiz:
@Cacheable("clz") Clazz selectByPrimaryKey(Integer cid);Test class text:
@Test public void test1(){ System.out.println(clazzBiz.selectByPrimaryKey(1)); System.out.println(clazzBiz.selectByPrimaryKey(1)); }The running results will only go to the database once, and then the redis cache will be used, which reduces the pressure on the database
database:
value: a name of the cache location, cannot be empty
key: cached key, empty by default, indicating that the parameter type and parameter value of the method are used as the key, supporting SpEL
condition: Trigger condition. If the condition is met, it will be added to the cache. The default is empty, which means all are added to the cache. SpEL is supported.
② CachePut (read-only data)
The
@CachePut
annotation is used to update the content in the cache. When a method marked with an annotation is called, Spring will update the value in the cache regardless of whether the corresponding key-value pair already exists in the cache, as followsclassBiz:
@CachePut(value = "xx",key = "'cid:' + #cid") Clazz selectByPrimaryKey(Integer cid);Test class text:
value: The name of the cache, defined in the spring configuration file, at least one must be specified
key: cached key, which can be empty. If specified, it should be written according to SpEL expression. If not specified, it will be combined according to all parameters of the method by default.
condition: cache condition, can be empty, written in SpEL, returns true or false, only cached if true
③ @
CacheEvict (clear or cache)
@CacheEvict is a cache annotation provided by the Spring framework, which is used to clear the data in the cache after marking the method execution.
@CacheEvict(value = "xx",key = "'cid:' + #cid",allEntries = true) int deleteByPrimaryKey(Integer cid);value: a name of the cache location, cannot be empty
key: cached key, empty by default, indicating that the parameter type and parameter value of the method are used as the key, supporting SpEL
condition: Trigger condition. If the condition is met, it will be added to the cache. The default is empty, which means all are added to the cache. SpEL is supported.
allEntries: true means clearing all caches in value, the default is false
Three, breakdown, penetration and avalanche of Redis cache
Three common phenomena in caches: Breakdown, penetration, and avalanche
① Breakdown
When the data for a certain key does not exist in the cache, and there are a large number of concurrent requests to access this key, these requests will directly pass through the cache to access the database, causing excessive pressure on the database and even downtime.
Solution:
Use mutex locks or distributed locks to ensure that only one thread accesses the database and other threads wait for the results.
② Penetration
If when requesting data, no data that meets the conditions is found in the cache layer and database layer, that is, no data is hit in the cache layer and database layer, then this situation is called cache penetration.
Solution:
Preset the null value or default value corresponding to this key in the cache to avoid direct access to the database by a large number of requests.
legend:
③ Avalanche
When a large amount of data in the cache fails at the same time and is accessed by a large number of requests, these requests will directly access the database, causing excessive pressure on the database or even downtime.
Solution:
– The expiration time of cached data is set randomly to avoid the simultaneous expiration of a large amount of data.
– Use a multi-level cache architecture to avoid single points of failure.
– Use the circuit breaker mechanism to temporarily block access to the database when the cache fails to avoid excessive pressure.legend:
The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. MySQL entry-level skills treeDatabase compositionTable 77675 people are learning the system