Redis integrates Spring with cache instances

Source: Internet
Author: User
Tags redis server

Redis integrates Spring with cache instances

Original works of Lin bingwen Evankaka. Reprinted please indicate the source http://blog.csdn.net/evankaka

Abstract: This article introduces how to configure redis in Spring, and uses the idea of AOP in Spring to cut the cache method into the class or method that needs to enter the cache.

I. Redis Introduction

What is Redis?

Redis is a key-value storage system. Similar to Memcached, Memcached supports more storage value types, including string, list, set, and zset) and hash (hash type ). These data types support push/pop, add/remove, Intersection Set and difference set, and more abundant operations, and these operations are atomic. On this basis, redis supports sorting in different ways. Like memcached, data is cached in the memory to ensure efficiency. The difference is that redis periodically writes the updated data to the disk or writes the modification operation to the append record file, and on this basis implements master-slave (master-slave) synchronization.

What are its features?

(1) The apsaradb for Redis database is completely in the memory, and disks are used only for persistence.
(2) Redis has a rich set of data types compared to many key-value data storage systems.
(3) Redis can copy data to any number of slave servers.

What are the advantages of Redis?
(1) abnormal and fast: Redis is very fast. It can execute about 0.11 million sets per second and more than 81000 records per second.
(2) Support for a wide range of data types: Redis supports most developers who already know the image list, set, ordered set, and hash data types. This makes it very easy to solve a variety of problems, because we know which problems can be handled through its data type better.
(3) operations are atomic: All Redis operations are atomic, which ensures that if the two clients simultaneously access the Redis server, the updated value will be obtained.
(4) Multi-Function utility: Redis is a multi-utility tool that can be used in multiple applications, such as cache, message, and queue (Redis native supports publishing/subscription ), any transient data, applications, such as Web application sessions, Web page hit count, etc.

What are the disadvantages of Redis?

(1) single thread

(2) memory consumption

Ii. Use instances

This article uses maven + eclipse + sping

1. Introduce the jar package

 

       
 
  
   org.springframework.data
  spring-data-redis
  
   1.6.1.RELEASE
  
 
 
  
   redis.clients
  jedis
  
   2.7.3
  
       

2. Configure bean

 

Add the following configuration in application. xml:

 

      
           
            
             
        
    
   
  
         
           
            
             
              
               
          
     
    
   
  
     
           
            
                 
              
    
             
                 
              
    
       
  
               
           
      
  
     
           
      
  
 

Some configuration data of the configuration file redis. properties is as follows:

 

 

# Redis center redis. host = 10.75.202.11redis.port = 6379redis. password = 123456redis. maxIdle = 100redis. maxActive = 300redis. maxWait = 1000redis. testOnBorrow = trueredis. timeout = 100000 # class targetNames = xxxRecordManager, xxxSetRecordManager, xxxStatisticsIdentificationManager # method of cache not required methodNames = # Set cache expiration time com. service. impl. xxxRecordManager = 60com. service. impl. xxxSetRecordManager = 60 defaultCacheExpireTime = 3600fep. local. cache. capacity = 10000

To scan these properties files, add the following configuration in application. xml:

 

 

             
         
              
                  
    
     classpath:properties/*.properties
                                 
           
      
 

3. Some tools

(1) RedisUtil

In the bean above, RedisUtil is an instance used to cache and remove data.

 

Package com. mucfc. msm. common; import java. io. serializable; import java. util. set; import java. util. concurrent. timeUnit; import org. apache. log4j. logger; import org. springframework. data. redis. core. redisTemplate; import org. springframework. data. redis. core. valueOperations;/*** redis cache tool class **/public final class RedisUtil {private Logger logger = Logger. getLogger (RedisUtil. class); private RedisTemplate
 
  
RedisTemplate;/*** batch Delete the corresponding value ** @ param keys */public void remove (final String... keys) {for (String key: keys) {remove (key) ;}/ *** Delete keys in batches ** @ param pattern */public void removePattern (final String pattern) {Set
  
   
Keys = redisTemplate. keys (pattern); if (keys. size ()> 0) redisTemplate. delete (keys);}/*** delete the corresponding value ** @ param key */public void remove (final String key) {if (exists (key) {redisTemplate. delete (key) ;}}/*** determine whether the cache has a corresponding value ** @ param key * @ return */public boolean exists (final String key) {return redisTemplate. hasKey (key);}/*** read cache ** @ param key * @ return */public Object get (final String key) {Object result = null; ValueOperations
   
    
Operations = redisTemplate. opsForValue (); result = operations. get (key); return result;}/*** write cache ** @ param key * @ param value * @ return */public boolean set (final String key, Object value) {boolean result = false; try {ValueOperations
    
     
Operations = redisTemplate. opsForValue (); operations. set (key, value); result = true;} catch (Exception e) {e. printStackTrace ();} return result;}/*** write cache ** @ param key * @ param value * @ return */public boolean set (final String key, Object value, long expireTime) {boolean result = false; try {ValueOperations
     
      
Operations = redisTemplate. opsForValue (); operations. set (key, value); redisTemplate. expire (key, expireTime, TimeUnit. SECONDS); result = true;} catch (Exception e) {e. printStackTrace ();} return result;} public void setRedisTemplate (RedisTemplate
      
        RedisTemplate) {this. redisTemplate = redisTemplate ;}}
      
     
    
   
  
 
(2) MethodCacheInterceptor

 

This section shows MethodCacheInterceptor, which is used to add different methods to determine whether data exists in the cache and obtain data from the cache. Otherwise, the database is retrieved for the first time and the result is saved to the cache.

 

Package com. mucfc. msm. common; import java. io. file; import java. io. fileInputStream; import java. io. inputStream; import java. util. arrayList; import java. util. list; import java. util. properties; import org. aopalliance. intercept. methodInterceptor; import org. aopalliance. intercept. methodInvocation; import org. apache. log4j. logger; public class MethodCacheInterceptor implements MethodInterceptor {private Logger logger = Logger. getLogger (MethodCacheInterceptor. class); private RedisUtil redisUtil; private List
 
  
TargetNamesList; // The private List of service names not included in the cache
  
   
MethodNamesList; // method name without caching private Long defaultCacheExpireTime; // default cache expiration time private Long xxxRecordManagerTime; // private Long xxxSetRecordManagerTime; /// *** initialize and read the class name and method name that do not need to be added to the cache */public MethodCacheInterceptor () {try {File f = new File ("D: \ lunaJee-workspace \ msm \ msm_core \ src \ main \ java \ com \ mucfc \ msm \ common \ cacheConf. properties "); // The Position of the configuration file is directly written to death. You need to modify InputStream in = new FileInputStream (f); // InputStream in = getClass (). getClassLoader (). getResourceAsStream (// "D: \ lunaJee-workspace \ msm \ msm_core \ src \ main \ java \ com \ mucfc \ msm \ common \ cacheConf. properties "); Properties p = new Properties (); p. load (in); // split String [] targetNames = p. getProperty ("targetNames "). split (","); String [] methodNames = p. getProperty ("methodNames "). split (","); // set defaultCacheExpireTime = Long. valueOf (p. getProperty ("defaultCacheExpireTime"); xxxRecordManagerTime = Long. valueOf (p. getProperty ("com. service. impl. xxxRecordManager "); xxxSetRecordManagerTime = Long. valueOf (p. getProperty ("com. service. impl. xxxSetRecordManager "); // create listtargetNamesList = new ArrayList
   
    
(TargetNames. length); methodNamesList = new ArrayList
    
     
(MethodNames. length); Integer maxLen = targetNames. length> methodNames. length? TargetNames. length: methodNames. length; // Add the class name and method name that do not need to be cached to the list for (int I = 0; I <maxLen; I ++) {if (I <targetNames. length) {targetNamesList. add (targetNames [I]);} if (I <methodNames. length) {methodNamesList. add (methodNames [I]) ;}} catch (Exception e) {e. printStackTrace () ;}@ Overridepublic Object invoke (MethodInvocation invocation) throws Throwable {Object value = null; String targetName = invocati On. getThis (). getClass (). getName (); String methodName = invocation. getMethod (). getName (); // content that does not need to be cached // if (! IsAddCache (StringUtil. subStrForLastDot (targetName), methodName) {if (! IsAddCache (targetName, methodName) {// return result of return invocation returned by the execution method. proceed ();} Object [] arguments = invocation. getArguments (); String key = getCacheKey (targetName, methodName, arguments); System. out. println (key); try {// determine whether cache if (redisUtil. exists (key) {return redisUtil. get (key) ;}// write cache value = invocation. proceed (); if (value! = Null) {final String tkey = key; final Object tvalue = value; new Thread (new Runnable () {@ Overridepublic void run () {if (tkey. startsWith ("com. service. impl. xxxRecordManager ") {redisUtil. set (tkey, tvalue, xxxRecordManagerTime);} else if (tkey. startsWith ("com. service. impl. xxxSetRecordManager ") {redisUtil. set (tkey, tvalue, xxxSetRecordManagerTime);} else {redisUtil. set (tkey, tvalue, defaultCacheExpire Time );}}}). start () ;}} catch (Exception e) {e. printStackTrace (); if (value = null) {return invocation. proceed () ;}} return value;}/*** add cache? ** @ return */private boolean isAddCache (String targetName, String methodName) {boolean flag = true; if (targetNamesList. contains (targetName) | methodNamesList. contains (methodName) {flag = false;} return flag;}/*** create cache key ** @ param targetName * @ param method Name * @ param arguments */private String getCacheKey (String targetName, String methodName, Object [] arguments) {StringBuffer sbu = new StringBuffer (); sbu. append (targetName ). append ("_"). append (methodName); if (arguments! = Null) & (arguments. length! = 0) {for (int I = 0; I <arguments. length; I ++) {sbu. append ("_"). append (arguments [I]);} return sbu. toString ();} public void setRedisUtil (RedisUtil redisUtil) {this. redisUtil = redisUtil ;}}
    
   
  
 

4. Configure the classes or methods to be cached

 

Add the following configurations to application. xml. You can configure multiple classes or methods.

 

    
     
           
                
             
   
            
                
                  
                     
    
     
Com \. mucfc \. msm \. service \. impl \... * ServiceImpl .*
                  
             
      
 

5. Execution result:

 

A simple unit test is written as follows:

 

@ Test public void getSettUnitBySettUnitIdTest () {String systemId = "CES"; String merchantId = "133"; SettUnit configSettUnit = settUnitService. getSettUnitBySettUnitId (systemId, merchantId, "ESP"); SettUnit configSettUnit1 = settUnitService. getSettUnitBySettUnitId (systemId, merchantId, "ESP"); boolean flag = (configSettUnit = configSettUnit1); System. out. println (configSettUnit); logger.info ("search result" + configSettUnit. getBusinessType (); // localSecondFIFOCache. put ("configSettUnit", configSettUnit. getBusinessType (); // String string = localSecondFIFOCache. get ("configSettUnit"); // logger.info ("search result" + string );}
This is the first unit test process:

 

The MethodCacheInterceptor class has a breakpoint, and then enters this method before each query.

 


 

Run in sequence and no cache is found. Therefore, you can directly query the database.

The printed SQL statement:

Second execution:

Because the cache has been written during the first execution. Therefore, data is directly retrieved from the cache for the second time.

3. Compare the two results for the address:

We found that two objects are not the same. That's right. If ehcache is used, the memory addresses of the two will be the same. That's because redis and ehcache use different caching mechanisms. Ehcache uses the cache based on the memory of the Local Computer. Therefore, when using the cache to retrieve data, it is directly obtained on the local computer. The conversion to a java object will be the same memory address, while redis is on a computer with the redis Service (usually another computer), so the data is transmitted to the local device during data retrieval, it will correspond to different memory addresses, so false will be returned for comparison with =. But it does get from the cache, which we can see from the above breakpoint.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.