java分布式会话redis_详解springboot中redis的使用和分布式session共享问题

对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash、轮训、根据权重、随机等。不管对于哪一种负载均衡算法,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因此会出现session不同步或者丢失的问题。

实际上实现Session共享的方案很多,其中一种常用的就是使用Tomcat、Jetty等服务器提供的Session共享功能,将Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis)中。

本文旨在解决分布式系统的session如何共享问题,大致思路:session放入redis。其他解决方案:持久化、放cache等都可以,但是自从有了redis,这完全可以变的简简单单。

本文大致分两步:

1.springboot中如何使用redis。

2.redis如何解决session共享

pom依赖

org.springframework.boot

spring-boot-starter-redis

org.springframework.data

spring-data-redis

${spring-data-redis.version}

redis.clients

jedis

${jedis.version}

org.springframework.session

spring-session-data-redis

添加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 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 redisTemplate) {

RedisCacheManager rcm = new RedisCacheManager(redisTemplate);

//设置缓存过期时间

rcm.setDefaultExpiration(600000);

return rcm;

}

}

配置redis服务

# Redis数据库索引(默认为0)

spring.redis.database=0

# Redis服务器地址

spring.redis.host=192.168.1.118

# Redis服务器连接端口

spring.redis.port=6381

# Redis服务器连接密码(默认为空)

spring.redis.password=

# 连接池最大连接数(使用负值表示没有限制)

spring.redis.pool.max-active=8

# 连接池最大阻塞等待时间(使用负值表示没有限制)

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

935401fe022d3e36067000dec53dbf2f.png

key=test001

2、set值(object)

@Test

public void testObj() throws Exception {

SysUser user=new SysUser();

user.setId("123456");

user.setName("张三");

ValueOperations 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设置5秒失效,线程等待6秒再完成,期望结果:redis中有user1,没有user2,bingo!!!

8a29b4de7afc13ea68e5adbd74a68b23.png

ObjTest

解决session共享

使用spring-session-data-redis实现session共享,pom中引入该依赖(上文已添加),添加SessionConfig配置类。

对,没看错,只需要这个就够了。最长有效时间根据自己情况随意配置即可。

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:

16a9c787b7bcef3869f55e4cfecad83e.png

sessionId

看redis中,可以看到失效时间,sessionId等

b1061c74bcc3d5b8e71a8430100ed985.png

sessionId

共享session

另外找一个机器,照着这个配置再来一遍,自动启用session共享,因为sessionId都存在了同一个redis中。奏是这么简单。挽起袖子开始干吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值