詳解springboot中redis的使用和分布式session共享問題
對于分布式使用Nginx+Tomcat實現(xiàn)負(fù)載均衡,最常用的均衡算法有IP_Hash、輪訓(xùn)、根據(jù)權(quán)重、隨機(jī)等。不管對于哪一種負(fù)載均衡算法,由于Nginx對不同的請求分發(fā)到某一個Tomcat,Tomcat在運行的時候分別是不同的容器里,因此會出現(xiàn)session不同步或者丟失的問題。
實際上實現(xiàn)Session共享的方案很多,其中一種常用的就是使用Tomcat、Jetty等服務(wù)器提供的Session共享功能,將Session的內(nèi)容統(tǒng)一存儲在一個數(shù)據(jù)庫(如MySQL)或緩存(如Redis)中。
本文旨在解決分布式系統(tǒng)的session如何共享問題,大致思路:session放入redis。其他解決方案:持久化、放cache等都可以,但是自從有了redis,這完全可以變的簡簡單單。
本文大致分兩步:
1.springboot中如何使用redis。
2.redis如何解決session共享
pom依賴
<!--redis配置開始--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>${spring-data-redis.version}</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${jedis.version}</version> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <!--redis配置結(jié)束-->
添加redis配置類
該配置類同樣可以配置緩存失效時間等。
package com.mos.quote.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; /** * @author Administrator */ @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public KeyGenerator KeyGenerator(){ return (target, method, params) -> { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); }; } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } @Bean public CacheManager cacheManager(RedisTemplate<String,String> redisTemplate) { RedisCacheManager rcm = new RedisCacheManager(redisTemplate); //設(shè)置緩存過期時間 rcm.setDefaultExpiration(600000); return rcm; } }
配置redis服務(wù)
# Redis數(shù)據(jù)庫索引(默認(rèn)為0) spring.redis.database=0 # Redis服務(wù)器地址 spring.redis.host=192.168.1.118 # Redis服務(wù)器連接端口 spring.redis.port=6381 # Redis服務(wù)器連接密碼(默認(rèn)為空) spring.redis.password= # 連接池最大連接數(shù)(使用負(fù)值表示沒有限制) spring.redis.pool.max-active=8 # 連接池最大阻塞等待時間(使用負(fù)值表示沒有限制) spring.redis.pool.max-wait=-1 # 連接池中的最大空閑連接 spring.redis.pool.max-idle=8 # 連接池中的最小空閑連接 spring.redis.pool.min-idle=0 # 連接超時時間(毫秒) spring.redis.timeout=0
單元測試
1、set值(字符串)
@Test public void put(){ stringRedisTemplate.opsForValue().set("test001","test001"); Assert.assertEquals("test001", stringRedisTemplate.opsForValue().get("test001")); }
往redis放一個key為test001、value為test001的值,然后查看redis
key=test001
2、set值(object)
@Test public void testObj() throws Exception { SysUser user=new SysUser(); user.setId("123456"); user.setName("張三"); ValueOperations<String, SysUser> operations=redisTemplate.opsForValue(); operations.set("user1", user); operations.set("user2", user,5, TimeUnit.SECONDS); Thread.sleep(6000); Assert.assertFalse(redisTemplate.hasKey("user2")); }
往redis分別放key為user1和user2的對象,user2設(shè)置5秒失效,線程等待6秒再完成,期望結(jié)果:redis中有user1,沒有user2,bingo?。。?/p>
ObjTest
解決session共享
使用spring-session-data-redis實現(xiàn)session共享,pom中引入該依賴(上文已添加),添加SessionConfig配置類。
對,沒看錯,只需要這個就夠了。最長有效時間根據(jù)自己情況隨意配置即可。
package com.mos.quote.config; import org.springframework.context.annotation.Configuration; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; /** * @author Administrator */ @Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3000) public class SessionConfig { }
測試
寫一個簡單Controller,如下
@RequestMapping("testSessionTimeOut") public String testSessionTimeOut(String id,HttpSession session,Model model){ Area area = areaService.getById(id); System.out.println("sessionId-------->"+session.getId()); model.addAttribute("area",JSON.toJSONString(area)); session.setAttribute("area",JSON.toJSONString(area)); return "demo/test1"; }
這里可以看到sessionId:
sessionId
看redis中,可以看到失效時間,sessionId等
sessionId
共享session
另外找一個機(jī)器,照著這個配置再來一遍,自動啟用session共享,因為sessionId都存在了同一個redis中。奏是這么簡單。挽起袖子開始干吧。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringBoot+SpringSession+Redis實現(xiàn)session共享及唯一登錄示例
- spring-redis-session 自定義 key 和過期時間
- 基于SpringBoot+Redis的Session共享與單點登錄詳解
- 解決Spring session(redis存儲方式)監(jiān)聽導(dǎo)致創(chuàng)建大量redisMessageListenerContailner-X線程問題
- SpringCloud實現(xiàn)Redis在各個微服務(wù)的Session共享問題
- Spring整合redis(jedis)實現(xiàn)Session共享的過程
- spring boot整合redis實現(xiàn)shiro的分布式session共享的方法
- 如何將Spring Session存儲到Redis中實現(xiàn)持久化
相關(guān)文章
logback FixedWindowRollingPolicy固定窗口算法重命名文件滾動策略
這篇文章主要介紹了FixedWindowRollingPolicy根據(jù)logback 固定窗口算法重命名文件滾動策略源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11SpringMVC自定義參數(shù)綁定實現(xiàn)詳解
這篇文章主要介紹了SpringMVC自定義參數(shù)綁定實現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-11-11spring學(xué)習(xí)之參數(shù)傳遞與檢驗詳解
這篇文章主要給大家介紹了關(guān)于spring參數(shù)傳遞與檢驗的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作能帶來一定的幫助,需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-07-07SpringBoot實現(xiàn)動態(tài)定時任務(wù)
這篇文章主要為大家詳細(xì)介紹了SpringBoot實現(xiàn)動態(tài)定時任務(wù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-04-04MyBatis-Plus中使用EntityWrappe進(jìn)行列表數(shù)據(jù)倒序設(shè)置方式
這篇文章主要介紹了MyBatis-Plus中使用EntityWrappe進(jìn)行列表數(shù)據(jù)倒序設(shè)置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03淺談Java中實現(xiàn)深拷貝的兩種方式—clone() & Serialized
這篇文章主要介紹了Java中實現(xiàn)深拷貝的兩種方式—clone() & Serialized,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03