About caching

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, and there is no need 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


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.



Cache annotation


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

caching 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

is based on 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;

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


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

code
  1. @CachePut(value = "user", key = "#id", condition = "#result.username ne 'zhang'")    
  2. 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)

code
  1. @CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'")    
  2. 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;

code
  1. @CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'")   
  2. public User conditionDelete(final User user)  


Small test knife, comprehensive use:

code
  1. @CachePut(value = "user", key = "#user.id")  
  2.    public User save(User user) {  
  3.        users.add(user);  
  4.        return user;  
  5.    }  
  6.   
  7.    @CachePut(value = "user", key = "#user.id")  
  8.    public User update(User user) {  
  9.        users.remove(user);  
  10.        users.add(user);  
  11.        return user;  
  12.    }  
  13.   
  14.    @CacheEvict(value = "user", key = "#user.id")  
  15.    public User delete(User user) {  
  16.        users.remove(user);  
  17.        return user;  
  18.    }  
  19.   
  20.    @CacheEvict(value = "user", allEntries = true)  
  21.    public void deleteAll() {  
  22.        users.clear();  
  23.    }  
  24.   
  25.    @Cacheable(value = "user", key = "#id")  
  26.    public User findById(final Long id) {  
  27.        System.out.println("cache miss, invoke find by id, id:" + id);  
  28.        for (User user : users) {  
  29.            if (user.getId().equals(id)) {  
  30.                return user;  
  31.            }  
  32.        }  
  33.        return null;  
  34.    }  


Configure ehcache to integrate ehcache with redis
spring cache, the main content of spring-ehcache.xml:

code
  1. <dependency>  
  2.     <groupId>net.sf.ehcache</groupId>  
  3.     <artifactId>ehcache-core</artifactId>  
  4.     <version>${ehcache.version}</version>  
  5. </dependency>  

 

code
  1. <!-- The cache manager based on the Ehcache implementation provided by Spring -->  
  2.       
  3. <!-- If there are multiple ehcacheManagers, add p:shared= "true" to the bean  -->  
  4. <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
  5.      <property name="configLocation" value="classpath:xml/ehcache.xml"/>  
  6. </bean>  
  7.       
  8. <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">  
  9.      <property name="cacheManager" ref="ehcacheManager"/>  
  10.      <property name="transactionAware" value="true"/>  
  11. </bean>  
  12.       
  13. <!-- cache annotation, and only one in spring-redis.xml -->  
  14. <cache:annotation-driven cache-manager="cacheManager" proxy-target-class="true"/>  


Spring cache integrates redis, the main content of spring-redis.xml:

code
  1. <dependency>  
  2.     <groupId>org.springframework.data</groupId>  
  3.     <artifactId>spring-data-redis</artifactId>  
  4.     <version>1.8.1.RELEASE</version>  
  5. </dependency>  
  6. <dependency>  
  7.     <groupId>org.apache.commons</groupId>  
  8.     <artifactId>commons-pool2</artifactId>  
  9.     <version>2.4.2</version>  
  10. </dependency>  
  11. <dependency>  
  12.     <groupId>redis.clients</groupId>  
  13.     <artifactId>jedis</artifactId>  
  14.     <version>2.9.0</version>  
  15. </dependency>  

 

code
  1. <!-- Note that you need to add jar packages such as Spring Data Redis -->  
  2. <description>redis配置</description>  
  3.   
  4. <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">  
  5.     <property name="maxIdle" value="${redis.pool.maxIdle}"/>  
  6.     <property name="maxTotal" value="${redis.pool.maxActive}"/>  
  7.     <property name="maxWaitMillis" value="${redis.pool.maxWait}"/>  
  8.     <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>  
  9.     <property name="testOnReturn" value="${redis.pool.testOnReturn}"/>  
  10. </bean>  
  11.   
  12. <!-- JedisConnectionFactory -->  
  13. <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">  
  14.     <property name="hostName" value="${redis.master.ip}"/>  
  15.     <property name="port" value="${redis.master.port}"/>  
  16.     <property name="poolConfig" ref="jedisPoolConfig"/>  
  17. </bean>  
  18.   
  19. <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"  
  20.       p:connectionFactory-ref="jedisConnectionFactory">  
  21.     <property name="keySerializer">  
  22.         <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>  
  23.     </property>  
  24.     <property name="valueSerializer">  
  25.         <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>  
  26.     </property>  
  27.     <property name="hashKeySerializer">  
  28.         <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>  
  29.     </property>  
  30.     <property name="hashValueSerializer">  
  31.         <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>  
  32.     </property>  
  33. </bean>  
  34.   
  35. <!--spring cache-->  
  36. <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"  
  37.       c:redisOperations-ref="redisTemplate">  
  38.     <!-- Default cache for 10 minutes -->  
  39.     <property name="defaultExpiration" value="600"/>  
  40.     <property name="usePrefix" value="true"/>  
  41.     <!-- cacheName cache timeout configuration, half an hour, one hour, one day -->  
  42.     <property name="expires">  
  43.         <map key-type="java.lang.String" value-type="java.lang.Long">  
  44.             <entry key="halfHour" value="1800"/>  
  45.             <entry key="hour" value="3600"/>  
  46.             <entry key="oneDay" value="86400"/>  
  47.             <!-- shiro cache keys -->  
  48.             <entry key="authorizationCache" value="1800"/>  
  49.             <entry key="authenticationCache" value="1800"/>  
  50.             <entry key="activeSessionCache" value="1800"/>  
  51.         </map>  
  52.     </property>  
  53. </bean>  
  54. <!-- cache annotation, and only one in spring-ehcache.xml can be used -->  
  55. <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.
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.


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

Guess you like

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