分布式session的几种解决方案
现在很多商城,都会要求用户先去登录,登录之后再往购物车中添加商品,这样用户、购物车、商品,三个对象之间就有了绑定关系。
而针对我最开始说的那种情况,其实就是基于session做的,客户端往购物车中添加第一个商品的时候,发送一个请求,服务器收到请求之后,创建session,然后返回当前session对应的一个JessionId,浏览器存储在cookie中,客户端往购物车添加第二个商品时,携带JessionId,服务端收到请求后,更新session。浏览器关闭后,cookie失效,JessionId也就丢失了,需要重新往购物车中添加商品,默认情况下,session有效期为30分钟。
在分布式环境下,session就会出现问题了,假如服务端部署在两个服务器A和B上。第一次往购物车添加商品时,请求落在了服务器A上,服务器A创建了一个session,并返回JessionId,第二次往购物车添加商品时,请求落在了服务器B上,请求携带的JesssionId在服务器B上并不会找到对应的session。这时候服务器B就会创建一个新的session,并返回对应的JessionId,客户端发现第一次添加的商品丢失了。。。
接下来,一起来学习分布式环境下session一致性是如何实现的。
一、客户端存储
既然分布式环境中,一个客户端的多个请求可能会落在多个服务器上,那么我们是否可以改变策略,直接将session信息存储在客户端?可以的,服务器将session信息直接存储到cookie中,这样就保证了session的一致性,但是并不推荐这样去做,因为将一些信息存储在cookie中,相当于就把这些信息暴露给了客户端,存在严重的安全隐患。
缺点:
- 安全性存在问题
- cookie对于数据类型及数据大小有所限制
二、session复制
将服务器A的session,复制到服务器B,同样将服务器B的session也复制到服务器A,这样两台服务器的session就一致了。像tomcat等web容器都支持session复制的功能,在同一个局域网内,一台服务器的session会广播给其他服务器。

缺点:
同一个网段内服务器太多,每个服务器都会去复制session,会造成服务器内存浪费。
三、session黏性
利用Nginx服务器的反向代理,将服务器A和服务器B进行代理,然后采用ip_hash的负载策略,将客户端和服务器进行绑定,也就是说客户端A第一次访问的是服务器B,那么第二次访问也必然是服务器B,这样就不存在session不一致的问题了。

缺点:
如果服务器A宕机了,那么客户端A和客户端B的session就会出现丢失。
四、session集中管理
这种方式就是将所有服务器的session进行统一管理,可以使用redis等高性能服务器来集中管理session,而且spring官方提供的spirng-session就是这样处理session的一致性问题。这也是目前企业开发用到的比较多的一种分布式session解决方案。

五、spring-session实战
Spring提供了处理分布式session的解决方案——Spring Session。Spring Session提供了用于管理用户会话的API和实现。
Spring Session提供了对redis,mongodb,mysql等常用的存储库的支持,Spring Session提供与HttpSession的透明整合,这意味着开发人员可以使用Spring Session支持的实现切换HttpSession实现。还是原来的配方,产生了不一样的味道!

Spring Session添加了一个SessionRepositoryFilter的过滤器,用来修改包装请求和响应,包装后的请求为SessionRepositoryRequestWrapper,调用getSession()方法的时候实际上就是调用Spring Session实现了的session。
Spring Session使用非常简单,添加了相关依赖后,直接操作HttpSession就可以实现效果。
第一步:添加Spring Session和 redis的相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
第二步:配置redis相关信息
spring:
redis:
# redis库
database: 0
# redis 服务器地址
host: localhost
# redis 端口号
port: 6379
# redis 密码
password:
# session 使用redis存储
session:
store-type: redis
第三步:项目中使用session
public String sessionTest(HttpServletRequest request){
HttpSession session = request.getSession();
session.setAttribute("key","value");
return session.getAttribute("key").toString();
}
redis中每个session存储了三条信息。

第一个存储这个Session的id,是一个Set类型的Redis数据结构。这个k中的最后的1439245080000值是一个时间戳,根据这个Session过期时刻滚动至下一分钟而计算得出。
第二个用来存储Session的详细信息,包括Session的过期时间间隔、最近的访问时间、attributes等等。这个k的过期时间为Session的最大过期时间 + 5分钟。如果默认的最大过期时间为30分钟,则这个k的过期时间为35分钟。
第三个用来表示Session在Redis中的过期,这个k-v不存储任何有用数据,只是表示Session过期而设置。这个k在Redis中的过期时间即为Session的过期时间间隔。
处理一个session为什么要存储三条数据,而不是一条呢!对于session的实现,需要监听它的创建、过期等事件,redis可以监听某个key的变化,当key发生变化时,可以快速做出相应的处理。
但是Redis中带有过期的key有两种方式:
- 当访问时发现其过期
- Redis后台逐步查找过期键
当访问时发现其过期,会产生过期事件,但是无法保证key的过期时间抵达后立即生成过期事件。
spring-session为了能够及时的产生Session的过期时的过期事件,所以增加了:
spring:session:sessions:expires:726de8fc-c045-481a-986d-f7c4c5851a67spring:session:expirations:1620393360000
spring-session中有个定时任务,每个整分钟都会查询相应的spring:session:expirations:整分钟的时间戳中的过期SessionId,然后再访问一次这个SessionId,即spring:session:sessions:expires:SessionId,以便能够让Redis及时的产生key过期事件——即Session过期事件。
参考:https://www.cnblogs.com/sxw123/p/13803478.html
分布式session的几种解决方案的更多相关文章
- 关于分布式Session 的几种实现方式
分布式Session的几种实现方式 1.基于数据库的Session共享 2.基于NFS共享文件系统 3.基于memcached 的session,如何保证 memcached 本身的高可用性? 4. ...
- 分布式session的几种实现方式
在搭建完集群环境后,不得不考虑的一个问题就是用户访问产生的session如何处理.如果不做任何处理的话,用户将出现频繁登录的现象,比如集群中存在A.B两台服务器,用户在第一次访问网站时,Nginx通过 ...
- [转]分布式session的几种实现方式
我们应当对产生的Session进行处理,通过粘性Session,Session复制或Session共享等方式保证用户的体验度. 以下我将说明5种Session处理策略,并分析其优劣性. 第一种:粘性s ...
- 管理分布式session的四种方式。
应用服务器的高可用架构设计最为理想的是服务无状态,但实际上业务总会有状态的,以session记录用户信息的例子来讲,未登入时,服务器没有记入用户信息的session访问网站都是以游客方式访问的,账号密 ...
- 分布式session的实现
一.分布式Session的几种实现方式 1.基于数据库的Session共享 2.基于NFS共享文件系统3.基于memcached 的session,如何保证 memcached 本身的高可用性?4. ...
- net之session漫谈及分布式session解决方案
最近一直在纠结net下分布式会话的实现,现将近日来的个人感想记录如下,如果有什么更好的解决方案请指教. 1.什么是session: Session 对象存储特定用户会话所需的属性及配置信息.这样,当用 ...
- 搞懂分布式技术11:分布式session解决方案与一致性hash
搞懂分布式技术11:分布式session解决方案与一致性hash session一致性架构设计实践 原创: 58沈剑 架构师之路 2017-05-18 一.缘起 什么是session? 服务器为每个用 ...
- 给我说说你能想到几种分布式session实现
附录: https://mp.weixin.qq.com/s/8Hh4j0CjfF5S8zM29JZl2w # 面试官心理分析 面试官问了你一堆 dubbo 是怎么玩儿的,你会玩儿 dubbo 就可以 ...
- 集群/分布式环境下5种session处理策略
转载自:http://blog.csdn.net/u010028869/article/details/50773174?ref=myread 前言 在搭建完集群环境后,不得不考虑的一个问题就是用户访 ...
随机推荐
- 《Effective Python》笔记——第4章 元类及属性
一.用属性取代get和set方法 常规的get和set方法如下: class OldResistor(): def __init__(self, ohms): self.__ohms = ohms d ...
- 「游记」CSP-S 2021 爆零记
推荐访问本人自建博客 \(\text{cjwen.top}\) 初赛 之前参加过「难度介于 J 组(基础组)和 S 组(提高组)之间」的 [LGR-(-13) ]SCP 2021 第一轮(初赛)模拟, ...
- Go vs Java vs C# 语法对比
目录 1. 说明 2. 对比 2.1 关键字(keywords) 2.1.1 Go 2.1.2 Java 2.1.3 C# 2.1.4 小结 2.2 基本数据类型 2.2.1 Go 基本数据类型 2. ...
- java中将SimpleDateFormat类型转换成Date类型
try {String dateString = "2009-08-02 13:43:00";DateFormat df = SimpleDateFormat("yyyy ...
- iOS 如何监听用户在手机设置里改变了系统的时间?
如何监听用户未退出APP但通过Home键在手机设置里改变了系统的时间? 用户虽未退出APP,但是当它按Home键退到后台时 ,会调用该方法: - (void)applicationDidEnterBa ...
- Maven依赖,去哪儿找
1. 前言 maven是作为Javer日常开发中必不可少的工具,但是很多人对于它的使用也只是仅限于的几个功能. 前几天在使用一个依赖总是说找不到该依赖,但是在中央仓库中的确存在该构建.这个问题让我很困 ...
- 大地坐标BLH转平面坐标xyh(高斯投影坐标正算) Java版
技术背景 做过位置数据处理的小伙伴基本上都会遇到坐标转换,而基于高斯投影原理的大地坐标转平面坐标就是其中一种坐标转换,坐标转换的目的就是方便后面数据的处理工作,大地坐标转高斯平面坐标常用的有两种,即3 ...
- 【软件实施面试】MySQL和Oracle联合查询以及聚合函数面试总结
软件实施面试系列文章第二弹,MySQL和Oracle联合查询以及聚合函数的面试总结.放眼望去全是MySQL,就不能来点Oracle吗?之前面过不少公司,也做过不少笔试题,现在已经很少做笔试题了.你肚子 ...
- JUC并发工具类之Semaphore控制并发线程数
首先看看关于Semaphore的UML图: 从上图看,信号量的实现原理与锁类似,是基于AQS的:有公平与非公平之分.当初始的资源数为1时就退化为排它锁了,资源总数即state的初始值,在acquire ...
- Latex公式导出word,Latex转换MathML使用POI导出公式可编辑的Word文件
背景 之前在 使用spire.doc导出支持编辑Latex公式的标准格式word 博客中写过,使用spire.doc来生成word,不得不说spire.doc的api操作起来还是比较方便,但是使用的过 ...