麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 數(shù)據(jù)庫(kù) > Redis > 正文

Redis整合Spring結(jié)合使用緩存實(shí)例

2020-10-28 21:39:52
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

一、Redis介紹
什么是Redis?
      redis是一個(gè)key-value存儲(chǔ)系統(tǒng)。和Memcached類似,它支持存儲(chǔ)的value類型相對(duì)更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數(shù)據(jù)類型都支持push/pop、add/remove及取交集并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎(chǔ)上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數(shù)據(jù)都是緩存在內(nèi)存中。區(qū)別的是redis會(huì)周期性的把更新的數(shù)據(jù)寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎(chǔ)上實(shí)現(xiàn)了master-slave(主從)同步。
它有什么特點(diǎn)?
(1)Redis數(shù)據(jù)庫(kù)完全在內(nèi)存中,使用磁盤僅用于持久性。
(2)相比許多鍵值數(shù)據(jù)存儲(chǔ),Redis擁有一套較為豐富的數(shù)據(jù)類型。
(3)Redis可以將數(shù)據(jù)復(fù)制到任意數(shù)量的從服務(wù)器。
Redis 優(yōu)勢(shì)?
 (1)異常快速:Redis的速度非常快,每秒能執(zhí)行約11萬(wàn)集合,每秒約81000+條記錄。
 (2)支持豐富的數(shù)據(jù)類型:Redis支持最大多數(shù)開發(fā)人員已經(jīng)知道像列表,集合,有序集合,散列數(shù)據(jù)類型。這使得它非常容易解決各種各樣的問題,因?yàn)槲覀冎滥男﹩栴}是可以處理通過它的數(shù)據(jù)類型更好。
(3)操作都是原子性:所有Redis操作是原子的,這保證了如果兩個(gè)客戶端同時(shí)訪問的Redis服務(wù)器將獲得更新后的值。
(4)多功能實(shí)用工具:Redis是一個(gè)多實(shí)用的工具,可以在多個(gè)用例如緩存,消息,隊(duì)列使用(Redis原生支持發(fā)布/訂閱),任何短暫的數(shù)據(jù),應(yīng)用程序,如Web應(yīng)用程序會(huì)話,網(wǎng)頁(yè)命中計(jì)數(shù)等。
Redis 缺點(diǎn)?
(1)單線程
(2)耗內(nèi)存
二、使用實(shí)例
本文使用maven+eclipse+sping
1、引入jar包

  <!--Redis start --> <dependency>   <groupId>org.springframework.data</groupId>   <artifactId>spring-data-redis</artifactId>   <version>1.6.1.RELEASE</version> </dependency> <dependency>   <groupId>redis.clients</groupId>   <artifactId>jedis</artifactId>   <version>2.7.3</version> </dependency>   <!--Redis end --> 

2、配置bean
在application.xml加入如下配置

<!-- jedis 配置 -->   <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" >      <property name="maxIdle" value="${redis.maxIdle}" />      <property name="maxWaitMillis" value="${redis.maxWait}" />      <property name="testOnBorrow" value="${redis.testOnBorrow}" />   </bean >  <!-- redis服務(wù)器中心 -->   <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >      <property name="poolConfig" ref="poolConfig" />      <property name="port" value="${redis.port}" />      <property name="hostName" value="${redis.host}" />      <property name="password" value="${redis.password}" />      <property name="timeout" value="${redis.timeout}" ></property>   </bean >   <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >      <property name="connectionFactory" ref="connectionFactory" />      <property name="keySerializer" >        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />      </property>      <property name="valueSerializer" >        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />      </property>   </bean >      <!-- cache配置 -->   <bean id="methodCacheInterceptor" class="com.mucfc.msm.common.MethodCacheInterceptor" >      <property name="redisUtil" ref="redisUtil" />   </bean >   <bean id="redisUtil" class="com.mucfc.msm.common.RedisUtil" >      <property name="redisTemplate" ref="redisTemplate" />   </bean > 

其中配置文件redis一些配置數(shù)據(jù)redis.properties如下:

#redis中心 redis.host=10.75.202.11 redis.port=6379 redis.password=123456 redis.maxIdle=100 redis.maxActive=300 redis.maxWait=1000 redis.testOnBorrow=true redis.timeout=100000  # 不需要加入緩存的類 targetNames=xxxRecordManager,xxxSetRecordManager,xxxStatisticsIdentificationManager # 不需要緩存的方法 methodNames=  #設(shè)置緩存失效時(shí)間 com.service.impl.xxxRecordManager= 60 com.service.impl.xxxSetRecordManager= 60 defaultCacheExpireTime=3600  fep.local.cache.capacity =10000 

要掃這些properties文件,在application.xml加入如下配置

 <!-- 引入properties配置文件 -->   <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">   <property name="locations">     <list>       <value>classpath:properties/*.properties</value>       <!--要是有多個(gè)配置文件,只需在這里繼續(xù)添加即可 -->     </list>   </property> </bean> 

3、一些工具類
(1)RedisUtil
上面的bean中,RedisUtil是用來(lái)緩存和去除數(shù)據(jù)的實(shí)例

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 工具類  *  */ public final class RedisUtil {   private Logger logger = Logger.getLogger(RedisUtil.class);   private RedisTemplate<Serializable, Object> redisTemplate;    /**    * 批量刪除對(duì)應(yīng)的value    *    * @param keys    */   public void remove(final String... keys) {     for (String key : keys) {       remove(key);     }   }    /**    * 批量刪除key    *    * @param pattern    */   public void removePattern(final String pattern) {     Set<Serializable> keys = redisTemplate.keys(pattern);     if (keys.size() > 0)       redisTemplate.delete(keys);   }    /**    * 刪除對(duì)應(yīng)的value    *    * @param key    */   public void remove(final String key) {     if (exists(key)) {       redisTemplate.delete(key);     }   }    /**    * 判斷緩存中是否有對(duì)應(yīng)的value    *    * @param key    * @return    */   public boolean exists(final String key) {     return redisTemplate.hasKey(key);   }    /**    * 讀取緩存    *    * @param key    * @return    */   public Object get(final String key) {     Object result = null;     ValueOperations<Serializable, Object> operations = redisTemplate         .opsForValue();     result = operations.get(key);     return result;   }    /**    * 寫入緩存    *    * @param key    * @param value    * @return    */   public boolean set(final String key, Object value) {     boolean result = false;     try {       ValueOperations<Serializable, Object> operations = redisTemplate           .opsForValue();       operations.set(key, value);       result = true;     } catch (Exception e) {       e.printStackTrace();     }     return result;   }    /**    * 寫入緩存    *    * @param key    * @param value    * @return    */   public boolean set(final String key, Object value, Long expireTime) {     boolean result = false;     try {       ValueOperations<Serializable, Object> 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<Serializable, Object> redisTemplate) {     this.redisTemplate = redisTemplate;   } } 

(2)MethodCacheInterceptor
切面MethodCacheInterceptor,這是用來(lái)給不同的方法來(lái)加入判斷如果緩存存在數(shù)據(jù),從緩存取數(shù)據(jù)。否則第一次從數(shù)據(jù)庫(kù)取,并將結(jié)果保存到緩存 中去。

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<String> targetNamesList; // 不加入緩存的service名稱   private List<String> methodNamesList; // 不加入緩存的方法名稱   private Long defaultCacheExpireTime; // 緩存默認(rèn)的過期時(shí)間   private Long xxxRecordManagerTime; //   private Long xxxSetRecordManagerTime; //    /**    * 初始化讀取不需要加入緩存的類名和方法名稱    */   public MethodCacheInterceptor() {     try {        File f = new File("D://lunaJee-workspace//msm//msm_core//src//main//java//com//mucfc//msm//common//cacheConf.properties");         //配置文件位置直接被寫死,有需要自己修改下        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);       // 分割字符串       String[] targetNames = p.getProperty("targetNames").split(",");       String[] methodNames = p.getProperty("methodNames").split(",");        // 加載過期時(shí)間設(shè)置       defaultCacheExpireTime = Long.valueOf(p.getProperty("defaultCacheExpireTime"));       xxxRecordManagerTime = Long.valueOf(p.getProperty("com.service.impl.xxxRecordManager"));       xxxSetRecordManagerTime = Long.valueOf(p.getProperty("com.service.impl.xxxSetRecordManager"));       // 創(chuàng)建list       targetNamesList = new ArrayList<String>(targetNames.length);       methodNamesList = new ArrayList<String>(methodNames.length);       Integer maxLen = targetNames.length > methodNames.length ? targetNames.length           : methodNames.length;       // 將不需要緩存的類名和方法名添加到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();     }   }    @Override   public Object invoke(MethodInvocation invocation) throws Throwable {     Object value = null;      String targetName = invocation.getThis().getClass().getName();     String methodName = invocation.getMethod().getName();     // 不需要緩存的內(nèi)容     //if (!isAddCache(StringUtil.subStrForLastDot(targetName), methodName)) {     if (!isAddCache(targetName, methodName)) {       // 執(zhí)行方法返回結(jié)果       return invocation.proceed();     }     Object[] arguments = invocation.getArguments();     String key = getCacheKey(targetName, methodName, arguments);     System.out.println(key);      try {       // 判斷是否有緩存       if (redisUtil.exists(key)) {         return redisUtil.get(key);       }       // 寫入緩存       value = invocation.proceed();       if (value != null) {         final String tkey = key;         final Object tvalue = value;         new Thread(new Runnable() {           @Override           public 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, defaultCacheExpireTime);             }           }         }).start();       }     } catch (Exception e) {       e.printStackTrace();       if (value == null) {         return invocation.proceed();       }     }     return value;   }    /**    * 是否加入緩存    *    * @return    */   private boolean isAddCache(String targetName, String methodName) {     boolean flag = true;     if (targetNamesList.contains(targetName)         || methodNamesList.contains(methodName)) {       flag = false;     }     return flag;   }    /**    * 創(chuàng)建緩存key    *    * @param targetName    * @param methodName    * @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、配置需要緩存的類或方法
在application.xml加入如下配置,有多個(gè)類或方法可以配置多個(gè)

<!-- 需要加入緩存的類或方法 --> <bean id="methodCachePointCut" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" >    <property name="advice" >      <ref local="methodCacheInterceptor" />    </property>    <property name="patterns" >      <list>       <!-- 確定正則表達(dá)式列表 -->        <value>com/.mucfc/.msm/.service/.impl/...*ServiceImpl.*</value >      </list>    </property> </bean > 

5、執(zhí)行結(jié)果:
寫了一個(gè)簡(jiǎn)單的單元測(cè)試如下:

@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("查找結(jié)果" + configSettUnit.getBusinessType());    // localSecondFIFOCache.put("configSettUnit", configSettUnit.getBusinessType());  // String string = localSecondFIFOCache.get("configSettUnit");    logger.info("查找結(jié)果" + string); } 

這是第一次執(zhí)行單元測(cè)試的過程:
MethodCacheInterceptor這個(gè)類中打了斷點(diǎn),然后每次查詢前都會(huì)先進(jìn)入這個(gè)方法


依次運(yùn)行,發(fā)現(xiàn)沒有緩存,所以會(huì)直接去查數(shù)據(jù)庫(kù)

打印了出來(lái)的SQL語(yǔ)句:

第二次執(zhí)行:
因?yàn)榈谝淮螆?zhí)行時(shí),已經(jīng)寫入緩存了。所以第二次直接從緩存中取數(shù)據(jù)

3、取兩次的結(jié)果進(jìn)行地址的對(duì)比:
發(fā)現(xiàn)兩個(gè)不是同一個(gè)對(duì)象,沒錯(cuò),是對(duì)的。如果是使用ehcache的話,那么二者的內(nèi)存地址會(huì)是一樣的。那是因?yàn)閞edis和ehcache使用的緩存機(jī)制是不一樣的。ehcache是基于本地電腦的內(nèi)存使用緩存,所以使用緩存取數(shù)據(jù)時(shí)直接在本地電腦上取。轉(zhuǎn)換成java對(duì)象就會(huì)是同一個(gè)內(nèi)存地址,而redis它是在裝有redis服務(wù)的電腦上(一般是另一臺(tái)電腦),所以取數(shù)據(jù)時(shí)經(jīng)過傳輸?shù)奖镜兀瑫?huì)對(duì)應(yīng)到不同的內(nèi)存地址,所以用==來(lái)比較會(huì)返回false。但是它確實(shí)是從緩存中去取的,這點(diǎn)我們從上面的斷點(diǎn)可以看到。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产 日韩 亚洲 欧美 | 国产亚洲精品久久久久久久软件 | 亚洲欧美在线视频免费 | 欧美a∨一区二区三区久久黄 | 国产一级一片免费播放 | 在线观看免费视频麻豆 | 久久成人免费网 | 午夜丰满少妇高清毛片1000部 | 成人福利视频网站 | 国产福利视频在线观看 | 成人毛片视频免费看 | 精品一区二区电影 | 欧美成人精品一区 | 一级网站 | 香蕉久久久精品 | 亚洲射逼 | 一级做a爱片久久 | 国产午夜精品一区二区三区在线观看 | 快播av在线| 小视频免费在线观看 | 可以看逼的视频 | 五月天影院,久久综合, | 国产精彩视频在线 | 成人福利在线播放 | 天堂成人一区二区三区 | 日韩美香港a一级毛片免费 欧美一级淫片007 | 黄色一级片免费在线观看 | 久久91亚洲人成电影网站 | 午夜神马福利视频 | 毛片免费视频播放 | 人成久久 | 成人富二代短视频 | 国产精品视频免费在线观看 | 国产超碰人人爽人人做人人爱 | 斗罗破苍穹在线观看免费完整观看 | 亚洲无线看 | 一级一级一级一级毛片 | 久久久久久久久久久久久久久久久久 | 国产日韩精品欧美一区视频 | 欧美日韩成人一区二区 | 日本欧美在线播放 |