Spring mind map, so that Spring is no longer difficult to understand (cache)

About caching

Caching is a very commonly used method to improve performance in practice. In java, the so-called cache is to store the objects that the program or system often calls in the memory, and the objects can be quickly obtained from the memory when they are called again, without having to create new and repeated instances. Doing so can reduce system overhead and improve system efficiency.

In CRUD, database queries account for more than 80% of database operations, and very frequent disk I/O read operations will result in extremely low database performance. The importance of the database is self-evident:

  • The database is usually the core part of the enterprise application system
  • The amount of data stored in the database is usually very large
  • Database query operations are often frequent and sometimes complex

Between different levels of the system architecture, in order to speed up access, there can be caches

The role of caching at different levels.png

Spring cache features and shortcomings

The mainstream cache frameworks on the market now include ehcache, redis, and memcached. Spring cache can be used together with simple configuration. The easiest way is to use annotations.

Features and defects.png

Cache annotation

cache annotation.png

As can be seen from the above annotations, although the use of annotations is indeed convenient, it lacks a flexible caching strategy.

Cache strategy:

  • TTL (Time To Live) lifetime, that is, a period of time from the point of creation in the cache until it expires (it will expire regardless of whether there is access during this period)

  • TTI (Time To Idle) idle period, that is, how long a data has not been accessed will be removed from the cache

There may be many caches in the project with different TTLs. In this case, you need to use the write cache code.

Conditional caching

According to the running process, the following @Cacheable will judge the condition before executing the method (#result cannot get the return value), and if it returns true, check the cache; 

@Cacheable(value = "user", key = "#id", condition = "#id lt 10")  
public User conditionFindById(final Long id)  

The following @CachePut will judge the condition after executing the method (#result can get the return value), and if it returns true, put it into the cache

@CachePut(value = "user", key = "#id", condition = "#result.username ne 'zhang'")  
public User conditionSave(final User user)   

  The following @CachePut will judge unless after the method is executed (#result can get the return value), and if it returns false, it will be put into the cache; (that is, the opposite of condition)

@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'")  
public User conditionSave2(final User user)   

  As follows @CacheEvict, beforeInvocation=false means to call after the method is executed (#result can get the return value); and judge the condition, if it returns true, remove the cache;

@CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'") 
public User conditionDelete(final User user)   
  • Small test knife, comprehensive use:
    @CachePut(value = "user", key = "#user.id")
    public User save(User user) {
        users.add(user);
        return user;
    }

    @CachePut(value = "user", key = "#user.id")
    public User update(User user) {
        users.remove(user);
        users.add(user);
        return user;
    }

    @CacheEvict(value = "user", key = "#user.id")
    public User delete(User user) {
        users.remove(user);
        return user;
    }

    @CacheEvict(value = "user", allEntries = true)
    public void deleteAll() {
        users.clear();
    }

    @Cacheable(value = "user", key = "#id")
    public User findById(final Long id) {
        System.out.println("cache miss, invoke find by id, id:" + id);
        for (User user : users) {
            if (user.getId().equals(id)) {
                return user;
            }
        }
        return null;
    }

Configure ehcache and redis

  • Spring cache integrates ehcache, the main content of spring-ehcache.xml:
<dependency>
	<groupId>net.sf.ehcache</groupId>
	<artifactId>ehcache-core</artifactId>
	<version>${ehcache.version}</version>
</dependency>
<!-- Spring提供的基于的Ehcache实现的缓存管理器 -->
    
<!-- 如果有多个ehcacheManager要在bean加上p:shared="true" -->
<bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
     <property name="configLocation" value="classpath:xml/ehcache.xml"/>
</bean>
    
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
     <property name="cacheManager" ref="ehcacheManager"/>
     <property name="transactionAware" value="true"/>
</bean>
    
<!-- cache注解,和spring-redis.xml中的只能使用一个 -->
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>
  • Spring cache integrates redis, the main content of spring-redis.xml:
<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-redis</artifactId>
	<version>1.8.1.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-pool2</artifactId>
	<version>2.4.2</version>
</dependency>
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.9.0</version>
</dependency>
<!-- 注意需要添加Spring Data Redis等jar包 -->
<description>redis配置</description>

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
	<property name="maxIdle" value="${redis.pool.maxIdle}"/>
	<property name="maxTotal" value="${redis.pool.maxActive}"/>
	<property name="maxWaitMillis" value="${redis.pool.maxWait}"/>
	<property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
	<property name="testOnReturn" value="${redis.pool.testOnReturn}"/>
</bean>

<!-- JedisConnectionFactory -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
	<property name="hostName" value="${redis.master.ip}"/>
	<property name="port" value="${redis.master.port}"/>
	<property name="poolConfig" ref="jedisPoolConfig"/>
</bean>

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
	  p:connectionFactory-ref="jedisConnectionFactory">
	<property name="keySerializer">
		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
	</property>
	<property name="valueSerializer">
		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
	</property>
	<property name="hashKeySerializer">
		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
	</property>
	<property name="hashValueSerializer">
		<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
	</property>
</bean>

<!--spring cache-->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"
	  c:redisOperations-ref="redisTemplate">
	<!-- 默认缓存10分钟 -->
	<property name="defaultExpiration" value="600"/>
	<property name="usePrefix" value="true"/>
	<!-- cacheName 缓存超时配置,半小时,一小时,一天 -->
	<property name="expires">
		<map key-type="java.lang.String" value-type="java.lang.Long">
			<entry key="halfHour" value="1800"/>
			<entry key="hour" value="3600"/>
			<entry key="oneDay" value="86400"/>
			<!-- shiro cache keys -->
			<entry key="authorizationCache" value="1800"/>
			<entry key="authenticationCache" value="1800"/>
			<entry key="activeSessionCache" value="1800"/>
		</map>
	</property>
</bean>
<!-- cache注解,和spring-ehcache.xml中的只能使用一个 -->
<cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>

Only one annotation cache can be configured in the project, so you can decide which cache to use by introducing which configuration file below.

<import resource="classpath:spring/spring-ehcache.xml"/>
<!-- <import resource="classpath:spring/spring-redis.xml"/>-->

Of course, the two caching mechanisms can be used in combination with other configurations. For example, ecache is the first-level cache, and redis is the second-level cache.

Cache comparison.png

For more detailed usage and configuration, you can refer to the configuration of spring cache in spring-shiro-training in the project.

write at the end

Welcome to my WeChat public account java mind map, download map source files, and more java mind maps and project materials for your study, and take you into the world of memory brain maps.

Follow the official account and reply to "mind map" to download the source xmind map immediately.

Read the previous article

Scan to pay attention to java-mindmap public number.jpg

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325517084&siteId=291194637