日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

Spring整合Redis做数据缓存(Windows环境)

發(fā)布時間:2023/12/20 windows 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring整合Redis做数据缓存(Windows环境) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

當(dāng)我們一個項(xiàng)目的數(shù)據(jù)量很大的時候,就需要做一些緩存機(jī)制來減輕數(shù)據(jù)庫的壓力,提升應(yīng)用程序的性能,對于java項(xiàng)目來說,最常用的緩存組件有Redis、Ehcache和Memcached。

Ehcache是用java開發(fā)的緩存組件,和java結(jié)合良好,直接在jvm虛擬機(jī)中運(yùn)行,不需要額外安裝什么東西,效率也很高;但是由于和java結(jié)合的太緊密了,導(dǎo)致緩存共享麻煩,分布式集群應(yīng)用不方便,所以比較適合單個部署的應(yīng)用。

Redis需要額外單獨(dú)安裝,是通過socket訪問到緩存服務(wù),效率比Ehcache低,但比數(shù)據(jù)庫要快很多很多,而且處理集群和分布式緩存方便,有成熟的方案,比較適合分布式集群部署的項(xiàng)目;也有很多的應(yīng)用將Ehcache和Redis結(jié)合使用,做成二級緩存。

至于Memcached嘛和Redis很類似,功能方面嘛理論上來說沒有Redis強(qiáng)大(但對于我們來說也完全足夠了),因此我們這里先不講,后面如果有時間在寫一篇關(guān)于Memcached的文章;由于我們后面會涉及到Tomcat的集群部署,所以這里就先講講Redis的應(yīng)用,好為后面的文章打個基礎(chǔ)~~下面正式開始!

?

代碼URL:http://git.oschina.net/tian5017/UserDemoRedis

?

一、Redis環(huán)境準(zhǔn)備

Redis有中文官方網(wǎng)站,地址為http://www.redis.cn/

Redis沒有官方的Windows版本,但是微軟開源技術(shù)團(tuán)隊(duì)(Microsoft Open Tech group)開發(fā)和維護(hù)著一個 Win64 的版本,下載地址為

https://github.com/MicrosoftArchive/redis/releases

截止文章完成之時,Redis的最新win64版本為3.2.100,我們這里就是使用的此版本;下載安裝好之后,打開安裝目錄,如下

上圖紅框中標(biāo)出的redis-cli.exe就是我們用來操作Redis的客戶端,要操作Redis,先要啟動Redis服務(wù),在windows中將Redis作為服務(wù)啟動的方法是,在上圖的安裝目錄下,打開命令行窗口,輸入命令

redis-server --service-install redis.windows.conf --loglevel verbose

這樣就將Redis作為Windows的服務(wù)啟動了

然后再在此安裝目錄下打開命令行窗口,輸入redis-cli.exe回車,如下

?可以看到已經(jīng)連接到了Redis,地址是127.0.0.1(本機(jī)),默認(rèn)的端口為6379,至于操作Redis的命令,大家可以自己百度,常用的也就那么幾個,很簡單,我們來簡單演示下

Redis是采用key-value鍵值對來存儲數(shù)據(jù)的,使用命令 set "haha" "123456",就表示將值(value)"123456"賦給鍵(key)"haha",再用 get "haha",就可以查看到值,好了關(guān)于Redis的別的東西,大家自己去玩,我們繼續(xù)我們的正題。

二、Spring集成

1、我們都知道,要在java中使用一個組件或者框架什么的,第一步都是加載它的jar包,java中操作Redis的jar包叫做jedis,這里我們還是利用上一篇文章《Spring+Mybatis+SpringMVC整合》所建立的UserDemo(項(xiàng)目連接:https://git.oschina.net/tian5017/UserDemo)

2、利用Maven來加載jedis的jar包,在UserDemo中的pom.xml的dependencies中添加如下代碼

<!-- redis相關(guān) --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.8.1</version></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId><version>1.7.10.RELEASE</version></dependency>

?

?除了jedis之外,還需要另外一個jar包spring-data-redis,這是讓Spring管理Redis用的;我們先來改造我們的代碼,試試往Redis里面存點(diǎn)數(shù)據(jù),再來查詢。

3、在/resources/下新建redis.properties文件

配置項(xiàng)如下

##Redis連接信息配置 #redis地址 cache.redis.host=127.0.0.1 #redis端口號 cache.redis.port=6379 #redis密碼 cache.redis.password= #redis使用的數(shù)據(jù)庫(Redis內(nèi)置18個數(shù)據(jù)庫,編號為0-17,默認(rèn)使用0) cache.redis.db=0 #redis鏈接超時時間 cache.redis.timeout=2000 #redis鏈接池中最大空閑數(shù) cache.redis.maxIdle=5 #redis鏈接池中最大連接數(shù) cache.redis.maxActive=20 #建立連接最長等待時間 cache.redis.maxWait=1000

?

4、在/resources/springConfig/下新建applicationContext-redis.xml文件作為Spring集成Redis的配置文件

配置代碼如下

<?xml version="1.0" encoding="UTF-8"?> <!-- 緩存redis相關(guān)配置 --> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"><bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"><property name="maxTotal" value="${cache.redis.maxActive}"/><property name="maxIdle" value="${cache.redis.maxIdle}"/><property name="maxWaitMillis" value="${cache.redis.maxWait}"/><property name="testOnBorrow" value="${cache.redis.testOnBorrow}"/></bean><bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"><property name="usePool" value="true"/><property name="hostName" value="${cache.redis.host}"/><property name="port" value="${cache.redis.port}"/><property name="password" value="${cache.redis.password}"/><property name="timeout" value="${cache.redis.timeout}"/><property name="database" value="${cache.redis.db}"/><constructor-arg index="0" ref="jedisPoolConfig"/></bean><bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" /><bean id="redisCache" class="org.springframework.data.redis.core.RedisTemplate"><property name="connectionFactory" ref="redisConnectionFactory"/><property name="keySerializer" ref="stringRedisSerializer"/><property name="valueSerializer" ref="stringRedisSerializer"/><property name="hashKeySerializer" ref="stringRedisSerializer"/><property name="hashValueSerializer" ref="stringRedisSerializer"/></bean> </beans>

?

?5、到這里,我們的準(zhǔn)備工作已經(jīng)全部完成,接下來就是在代碼中使用redis了,我們修改UserServiceImpl.java

修改思路為,查詢數(shù)據(jù)的時候,先查詢Redis緩存,如果查到了就直接返回數(shù)據(jù),如果沒查到數(shù)據(jù),就去數(shù)據(jù)庫中查詢,查到了數(shù)據(jù)先緩存進(jìn)Redis再返回,代碼如下:

package com.user.demo.service.impl;import com.alibaba.fastjson.JSON; import com.user.demo.dao.UserDao; import com.user.demo.entity.User; import com.user.demo.service.IUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils;import javax.annotation.Resource; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set;/*** Service接口實(shí)現(xiàn)類*/ @Service public class UserServiceImpl implements IUserService {@Resourceprivate UserDao userDao;@Autowiredprivate RedisTemplate<String, String> redisCache;@Overridepublic List<User> findAll() {List<User> users = new ArrayList<User>();//先從redis緩存中獲取數(shù)據(jù),如果緩存中沒有,去數(shù)據(jù)庫中查詢數(shù)據(jù),查到后在寫入緩存Set<String> sets = redisCache.keys("USER*");if(sets==null || sets.isEmpty()){users = userDao.findAll();if(!CollectionUtils.isEmpty(users)){for(User user : users){redisCache.opsForValue().set("USER"+user.getUserId(), JSON.toJSONString(user));}}}else{Iterator<String> it = sets.iterator();while (it.hasNext()){String item = it.next();String value = redisCache.opsForValue().get(item);users.add(JSON.parseObject(value, User.class));}}return users;}@Override@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) //事物public void saveUser(User user) {userDao.saveUser(user);} }

?

6、接下來我們來驗(yàn)證緩存是否生效,編譯,運(yùn)行項(xiàng)目,如下圖

打開redis-cli,輸入命令KEYS * (查看所有的key),如下

可以看到我們的緩存已經(jīng)加入進(jìn)去了,key就是我們在UserServiceImpl.java中設(shè)置的(redisCache.opsForValue().set("USER"+user.getUserId(), JSON.toJSONString(user))),以USER開頭加上userId構(gòu)成,為了進(jìn)一步驗(yàn)證有了緩存之后,查詢的數(shù)據(jù)優(yōu)先來源于緩存,我們在數(shù)據(jù)庫中刪除一條數(shù)據(jù),就刪除userId為1的那條數(shù)據(jù)

??

刪除之后,由于我們代碼中檢測緩存的邏輯只是檢測了能否查詢到緩存,而沒有檢測緩存數(shù)量是否和數(shù)據(jù)庫數(shù)據(jù)量一致,所以緩存中還是會存在這條數(shù)據(jù)

? ? ? ? ? ? ??

可以看到,userId為1的數(shù)據(jù)依然存在,說明數(shù)據(jù)是從Redis緩存中查詢出來的。

三、數(shù)據(jù)同步

上面其實(shí)說明了一個問題,就是數(shù)據(jù)同步,我們很可能會出現(xiàn),數(shù)據(jù)庫中數(shù)據(jù)變了,但是緩存中的數(shù)據(jù)還沒有變,因此和數(shù)據(jù)庫中的數(shù)據(jù)不一致,所以我們需要一些策略來保證數(shù)據(jù)庫的數(shù)據(jù)和Redis的數(shù)據(jù)能夠保持一致,至于選用什么策略,那要具體項(xiàng)目具體分析,如果對數(shù)據(jù)的實(shí)時性要求很高的項(xiàng)目,那么就要在查詢的時候,檢測數(shù)據(jù)庫的數(shù)據(jù)和Redis的緩存數(shù)據(jù)是否一致,如果不一致就要刷新Redis的數(shù)據(jù),但是這樣必然對性能會有很高的要求;如果項(xiàng)目對數(shù)據(jù)的實(shí)時性要求沒有那么高,我們完全可以做一個定時任務(wù),比如每隔10分鐘或者半小時去數(shù)據(jù)庫拉一次數(shù)據(jù),再刷新到Redis緩存中,所以下面我們就來做一個定時任務(wù),每隔10分鐘去拉一次數(shù)據(jù),然后往Redis中刷新一次。

四、定時刷新緩存

?我們用Spring中的InitializingBean和DisposableBean接口(這兩個接口的具體用法請自行百度,大概就是在SpringBean的生命周期中,影響bean的行為,我們這里就是影響了bean,讓它去刷新緩存)來實(shí)現(xiàn)刷新緩存,在com.user.demo下新建包c(diǎn)ache,在cache下面新建類UserCache.java,具體代碼如下

package com.user.demo.cache;import com.alibaba.fastjson.JSON; import com.user.demo.dao.UserDao; import com.user.demo.entity.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.util.List; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit;/*** Redis緩存User數(shù)據(jù)并定時刷新* 每間隔一定時間后(如10分鐘)刷新一次緩存,刷新時另起一個線程,不影響執(zhí)行主任務(wù)的線程*/ @Component public class UserCache implements InitializingBean, DisposableBean {private final Logger log = LoggerFactory.getLogger(UserCache.class);//獲取電腦的CPU核心數(shù)量,設(shè)置線程池大小為核心數(shù)的2倍(比如我的電腦為4核心,那么這里的值就為8)private static final int CORE_NUM = Runtime.getRuntime().availableProcessors() * 2;//初始化值為redis.properties中配置的cache.redis.cacheExpire的值,表示每隔多長時間后執(zhí)行任務(wù)@Value("${cache.redis.cacheExpire}")private long cacheExpire;//執(zhí)行定時任務(wù)的類private ScheduledThreadPoolExecutor executor = null;@Resourceprivate RedisTemplate<String, String> redisCache;@Resourceprivate UserDao userDao;@Overridepublic void destroy() throws Exception {executor.shutdownNow();}@Overridepublic void afterPropertiesSet() throws Exception {executor = new ScheduledThreadPoolExecutor(CORE_NUM);RefreshCache refreshCache = new RefreshCache();refreshCache.run();executor.scheduleWithFixedDelay(refreshCache, cacheExpire, cacheExpire, TimeUnit.SECONDS);}//內(nèi)部類,開啟新線程執(zhí)行緩存刷新private class RefreshCache implements Runnable {@Overridepublic void run() {log.info("---開始刷新用戶信息緩存---");List<User> userList = userDao.findAll();if(!CollectionUtils.isEmpty(userList)){for(User user : userList){redisCache.opsForValue().set("USER" + user.getUserId(), JSON.toJSONString(user));}}}} }

在redis.properties中加入cache.redis.cacheExpire配置項(xiàng),代碼如下

##Redis連接信息配置 #redis地址 cache.redis.host=127.0.0.1 #redis端口號 cache.redis.port=6379 #redis密碼 cache.redis.password= #redis使用的數(shù)據(jù)庫(Redis內(nèi)置18個數(shù)據(jù)庫,編號為0-17,默認(rèn)使用0) cache.redis.db=0 #redis鏈接超時時間 cache.redis.timeout=2000 #redis鏈接池中最大空閑數(shù) cache.redis.maxIdle=5 #redis鏈接池中最大連接數(shù) cache.redis.maxActive=20 #建立連接最長等待時間 cache.redis.maxWait=1000#定時任務(wù)執(zhí)行時間間隔,單位為毫秒,這里相當(dāng)于10分鐘 cache.redis.cacheExpire=600

同時修改UserServiceImpl.java中的代碼如下

package com.user.demo.service.impl;import com.alibaba.fastjson.JSON; import com.user.demo.dao.UserDao; import com.user.demo.entity.User; import com.user.demo.service.IUserService; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set;/*** Service接口實(shí)現(xiàn)類*/ @Service public class UserServiceImpl implements IUserService {@Resourceprivate UserDao userDao;@Resourceprivate RedisTemplate<String, String> redisCache;@Overridepublic List<User> findAll() {List<User> result = new ArrayList<User>();Set<String> sets = redisCache.keys("USER*");//如果緩存有數(shù)據(jù)則從緩存中取數(shù)據(jù),如果沒有則從數(shù)據(jù)庫中取數(shù)據(jù)if(!CollectionUtils.isEmpty(sets)){Iterator<String> it = sets.iterator();while(it.hasNext()){String item = it.next();String value = redisCache.opsForValue().get(item);result.add(JSON.parseObject(value, User.class));}}else{result = userDao.findAll();}return result;}@Override@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) //事物public void saveUser(User user) {userDao.saveUser(user);}}

此時,項(xiàng)目已經(jīng)可以定時(每隔十分鐘)刷新緩存,我們編譯啟動

我們新提交一個用戶“三德子”,剛提交后,刷新是查不出來數(shù)據(jù)的,但是數(shù)據(jù)庫是有數(shù)據(jù)的

? ??

然后等待10分鐘之后,再來查看,可以看到緩存已經(jīng)被自動刷新到了Redis中

?

OK,到這里,這篇文章就結(jié)束了,關(guān)于Spring集成Redis做數(shù)據(jù)緩存我們也講的差不多了,其實(shí)關(guān)于Redis的應(yīng)用,遠(yuǎn)遠(yuǎn)不止這么簡單,我們可以很容易的搭建Redis集群,做分布式數(shù)據(jù)管理,也可以實(shí)現(xiàn)分布式session共享(這個我后面會有一篇文章講到),甚至假如寫數(shù)據(jù)量很大,我們也可以先緩存進(jìn)Redis中,再利用多線程來將數(shù)據(jù)寫入數(shù)據(jù)庫中,減輕數(shù)據(jù)庫的負(fù)擔(dān)(因?yàn)閿?shù)據(jù)庫寫操作是很耗費(fèi)資源的)等等~~那如果大家有什么意見和建議,也歡迎留言交流;下一篇文章我會講講mysql的讀寫分離,歡迎繼續(xù)關(guān)注!!

?

代碼URL:http://git.oschina.net/tian5017/UserDemoRedis

?

轉(zhuǎn)載于:https://www.cnblogs.com/tian5017/p/7171744.html

總結(jié)

以上是生活随笔為你收集整理的Spring整合Redis做数据缓存(Windows环境)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。