spring-session+redis解决共享session问题

Posted 八阿哥克星

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring-session+redis解决共享session问题相关的知识,希望对你有一定的参考价值。

在集群中,由于有多台服务器,但是session却应该还是一个,session 如何共享就需要被解决;

现在有多种方式来解决session共享问题:

1、通过nginx,根据访问者ip来做hash,从而在每次访问时都是固定的一台服务器,那个session 对象也就是固定的一个了

2、用token来代替session

3、用spring-session+redis实现session共享

spring-session+redis实现session共享的原理其实很简单,就是把session对象存到redis中,每台服务器被访问时,通过sessionid到redis中拿到session对象;

具体的实现方式是:实现了一个过滤器filter,在所有访问请求进入servlet前将其拦截,在filter中,对request对象和response对象做了一层包装,然后放行,执行后面的逻辑,后面如果要用session对象时,调用getsession()方法,其实调用的就是包装后的request对象的getsession()方法,这个方法中,就是从redis里获取session了,所有的服务器都从redis中获取同一个session,那么共享session就实现了;当然,还有一些点也需要注意一下,就是redis在创建保存某个session时,其实创建了三个相关key,了解redis的key删除策略的应该明白,redis不是实时删除到期key的这三个key的数据结构分别是:

A) "spring:session:sessions:39feb101-87d4-42c7-ab53-ac6fe0d91925"

B) "spring:session:expirations:1523934840000"

C) "spring:session:sessions:expires:39feb101-87d4-42c7-ab53-ac6fe0d91925"

他们公用的前缀是 spring:session A 类型键的组成是前缀 +”sessions”+sessionId,对应的值是一个 hash 数据结构。 "lastAccessedTime": 1523933008926,/2018/4/17 10:43:28/ "creationTime": 1523933008926, /2018/4/17 10:43:28/ "maxInactiveInterval": 1800, "sessionAttr:name": "xu" 其中 creationTime(创建时间),lastAccessedTime(最后访问时间),maxInactiveInterval(session 失效的间隔时长) 等字段是系统字段,sessionAttr:xx 是HttpServletRequest.setAttribute("xxx","xxx")存入的,它可能会存在多个键值对,用户存放在 session 中的数据如数存放于此。A 类型键对应的默认 TTL 是 30+5 分钟。(30是默认有效时间,可以设置的)

B 类型键的组成是前缀 +”expirations”+ 时间戳。其对应的值是一个 set 数据结构,这个 set 数据结构中存储着一系列的 C 类型键。B 类型键对应的默认 TTL 是 30+5 分钟 [ "expires:39feb101-87d4-42c7-ab53-ac6fe0d91925" "expires:836d11aa-11e2-44e0-a0b2-92b54dec2324" ] C 类型键的组成是前缀 +”sessions:expires”+sessionId,对应一个空值,它仅仅是 sessionId 在 redis 中的一个引用,C 类型键对应的默认 TTL 是 30 分钟。

这里注意一个细节,spring-session 中 A 类型键的过期时间是 35 分钟,比实际的 30 分钟多了 5 分钟,这意味着即便 session 已经过期,我们还是可以在 redis 中有 5 分钟间隔来操作过期的 session。于此同时,spring-session 引入了 C 类型键来作为 session 的引用。

为什么引入 C 类型键?redis只会告诉我们哪个键过期了,不会告诉我们内容是什么。关键就在于如果 session 过期后监听器可能想要访问 session 的具体内容,然而自身都过期了,还怎么获取内容 。所以,C 类型键存在的意义便是解耦 session 的存储和 session 的过期,并且使得 server 获取到过期通知后可以访问到 session 真实的值。对于用户来说,C 类型键过期后,意味着登录失效,而对于服务端而言,真正的过期其实是 A 类型键过期,这中间会有 5 分钟的误差。

以上是关于spring-session+redis解决共享session问题的主要内容,如果未能解决你的问题,请参考以下文章

Spring-SESSION+Redis 实现Session共享

Spring-Session+Redis实现session共享

spring-session用redis实现session共享实践

spring-session实现session共享案例(单点登录)

spring-session使用配置(分布式共享session配置)

Spring-session整合到Redis