分布式session的几种解决方案,你中意哪种?

沙海 2021年6月2日04:29:25Java评论32字数 4211阅读14分2秒阅读模式
摘要

智能摘要

智能摘要文章源自JAVA秀-https://www.javaxiu.com/28451.html

我发现了一个商城,我还没有登录,就可以往购物车中添加商品,加了好几件后,我准备付款,需要我先去登录,登录完之后付款。既然分布式环境中,一个客户端的多个请求可能会落在多个服务器上,那么我们是否可以改变策略,直接将session信息存储在客户端?这个k中的最后的1439245080000值是一个时间戳,根据这个Session过期时刻滚动至下一分钟而计算得出。第二个用来存储Session的详细信息,包括Session的过期时间间隔、最近的访问时间、attributes等等。文章源自JAVA秀-https://www.javaxiu.com/28451.html

原文约 2301 | 图片 7 | 建议阅读 5 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/28451.html

分布式session的几种解决方案,你中意哪种?

Java学习者社区 文章源自JAVA秀-https://www.javaxiu.com/28451.html

以下文章来源于Java旅途,作者大尧文章源自JAVA秀-https://www.javaxiu.com/28451.html

文章源自JAVA秀-https://www.javaxiu.com/28451.html

分布式session的几种解决方案,你中意哪种?文章源自JAVA秀-https://www.javaxiu.com/28451.html

Java旅途文章源自JAVA秀-https://www.javaxiu.com/28451.html

『Java旅途』专注于Java技术分享,包含但不局限于Spring Boot、Spring Cloud、消息队列、redis、JVM、Mysql、面经等,欢迎关注,一起学习、一起成长!文章源自JAVA秀-https://www.javaxiu.com/28451.html

文章源自JAVA秀-https://www.javaxiu.com/28451.html

我发现了一个商城,我还没有登录,就可以往购物车中添加商品,加了好几件后,我准备付款,需要我先去登录,登录完之后付款。文章源自JAVA秀-https://www.javaxiu.com/28451.html

现在很多商城,都会要求用户先去登录,登录之后再往购物车中添加商品,这样用户、购物车、商品,三个对象之间就有了绑定关系。文章源自JAVA秀-https://www.javaxiu.com/28451.html

而针对我最开始说的那种情况,其实就是基于session做的,客户端往购物车中添加第一个商品的时候,发送一个请求,服务收到请求之后,创建session,然后返回当前session对应的一个JessionId,浏览器存储在cookie中,客户端往购物车添加第二个商品时,携带JessionId,服务端收到请求后,更新session浏览器关闭后,cookie失效,JessionId也就丢失了,需要重新往购物车中添加商品,默认情况下,session有效期为30分钟。文章源自JAVA秀-https://www.javaxiu.com/28451.html

在分布式环境下,session就会出现问题了,假如服务端部署在两个服务器AB上。第一次往购物车添加商品时,请求落在了服务器A上,服务器A创建了一个session,并返回JessionId,第二次往购物车添加商品时,请求落在了服务器B上,请求携带的JesssionId在服务器B上并不会找到对应的session。这时候服务器B就会创建一个新的session,并返回对应的JessionId,客户端发现第一次添加的商品丢失了。。。文章源自JAVA秀-https://www.javaxiu.com/28451.html

接下来,一起来学习分布式环境下session一致性是如何实现的。文章源自JAVA秀-https://www.javaxiu.com/28451.html

一、客户端存储

既然分布式环境中,一个客户端的多个请求可能会落在多个服务器上,那么我们是否可以改变策略,直接将session信息存储在客户端?可以的,服务器将session信息直接存储到cookie中,这样就保证了session的一致性,但是并不推荐这样去做,因为将一些信息存储在cookie中,相当于就把这些信息暴露给了客户端,存在严重的安全隐患。文章源自JAVA秀-https://www.javaxiu.com/28451.html

缺点文章源自JAVA秀-https://www.javaxiu.com/28451.html

  • 安全性存在问题文章源自JAVA秀-https://www.javaxiu.com/28451.html

  • cookie对于数据类型及数据大小有所限制文章源自JAVA秀-https://www.javaxiu.com/28451.html

二、session复制

将服务器A的session,复制到服务器B,同样将服务器B的session也复制到服务器A,这样两台服务器的session就一致了。像tomcat等web容器都支持session复制的功能,在同一个局域网内,一台服务器的session会广播给其他服务器。文章源自JAVA秀-https://www.javaxiu.com/28451.html

分布式session的几种解决方案,你中意哪种?文章源自JAVA秀-https://www.javaxiu.com/28451.html

缺点文章源自JAVA秀-https://www.javaxiu.com/28451.html

同一个网段内服务器太多,每个服务器都会去复制session,会造成服务器内存浪费。文章源自JAVA秀-https://www.javaxiu.com/28451.html

三、session黏性

利用Nginx服务器的反向代理,将服务器A和服务器B进行代理,然后采用ip_hash的负载策略,将客户端和服务器进行绑定,也就是说客户端A第一次访问的是服务器B,那么第二次访问也必然是服务器B,这样就不存在session不一致的问题了。文章源自JAVA秀-https://www.javaxiu.com/28451.html

分布式session的几种解决方案,你中意哪种?文章源自JAVA秀-https://www.javaxiu.com/28451.html

缺点文章源自JAVA秀-https://www.javaxiu.com/28451.html

如果服务器A宕机了,那么客户端A和客户端B的session就会出现丢失。文章源自JAVA秀-https://www.javaxiu.com/28451.html

四、session集中管理

这种方式就是将所有服务器的session进行统一管理,可以使用redis等高性能服务器来集中管理session,而且spring官方提供的spirng-session就是这样处理session的一致性问题。这也是目前企业开发用到的比较多的一种分布式session解决方案。文章源自JAVA秀-https://www.javaxiu.com/28451.html

分布式session的几种解决方案,你中意哪种?文章源自JAVA秀-https://www.javaxiu.com/28451.html

五、spring-session实战

Spring提供了处理分布式session的解决方案——Spring SessionSpring Session提供了用于管理用户会话的API和实现。文章源自JAVA秀-https://www.javaxiu.com/28451.html

Spring Session提供了对redismongodbmysql等常用的存储库的支持,Spring Session提供与HttpSession的透明整合,这意味着开发人员可以使用Spring Session支持的实现切换HttpSession实现。还是原来的配方,产生了不一样的味道!文章源自JAVA秀-https://www.javaxiu.com/28451.html

分布式session的几种解决方案,你中意哪种?文章源自JAVA秀-https://www.javaxiu.com/28451.html

Spring Session添加了一个SessionRepositoryFilter的过滤器,用来修改包装请求和响应,包装后的请求为SessionRepositoryRequestWrapper,调用getSession()方法的时候实际上就是调用Spring Session实现了的session。文章源自JAVA秀-https://www.javaxiu.com/28451.html

Spring Session使用非常简单,添加了相关依赖后,直接操作HttpSession就可以实现效果。文章源自JAVA秀-https://www.javaxiu.com/28451.html

第一步:添加Spring Sessionredis的相关依赖文章源自JAVA秀-https://www.javaxiu.com/28451.html

<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相关信息文章源自JAVA秀-https://www.javaxiu.com/28451.html

spring:  redis:    # redis库    database: 0    # redis 服务器地址    host: localhost    # redis 端口号    port: 6379    # redis 密码    password:  # session 使用redis存储    session:    store-type: redis

第三步:项目中使用session文章源自JAVA秀-https://www.javaxiu.com/28451.html

public String sessionTest(HttpServletRequest request){    HttpSession session = request.getSession();    session.setAttribute("key","value");    return session.getAttribute("key").toString();}

redis中每个session存储了三条信息。文章源自JAVA秀-https://www.javaxiu.com/28451.html

分布式session的几种解决方案,你中意哪种?文章源自JAVA秀-https://www.javaxiu.com/28451.html

  • 第一个存储这个Session的id,是一个Set类型的Redis数据结构。这个k中的最后的1439245080000值是一个时间戳,根据这个Session过期时刻滚动至下一分钟而计算得出。文章源自JAVA秀-https://www.javaxiu.com/28451.html

  • 第二个用来存储Session的详细信息,包括Session的过期时间间隔、最近的访问时间、attributes等等。这个k的过期时间为Session的最大过期时间 + 5分钟。如果默认的最大过期时间为30分钟,则这个k的过期时间为35分钟。文章源自JAVA秀-https://www.javaxiu.com/28451.html

  • 第三个用来表示Session在Redis中的过期,这个k-v不存储任何有用数据,只是表示Session过期而设置。这个k在Redis中的过期时间即为Session的过期时间间隔。文章源自JAVA秀-https://www.javaxiu.com/28451.html

处理一个session为什么要存储三条数据,而不是一条呢!对于session的实现,需要监听它的创建、过期等事件,redis可以监听某个key的变化,当key发生变化时,可以快速做出相应的处理。文章源自JAVA秀-https://www.javaxiu.com/28451.html

但是Redis中带有过期的key有两种方式:文章源自JAVA秀-https://www.javaxiu.com/28451.html

  • 当访问时发现其过期文章源自JAVA秀-https://www.javaxiu.com/28451.html

  • Redis后台逐步查找过期键文章源自JAVA秀-https://www.javaxiu.com/28451.html

当访问时发现其过期,会产生过期事件,但是无法保证key的过期时间抵达后立即生成过期事件。文章源自JAVA秀-https://www.javaxiu.com/28451.html

spring-session为了能够及时的产生Session的过期时的过期事件,所以增加了:文章源自JAVA秀-https://www.javaxiu.com/28451.html

spring:session:sessions:expires:726de8fc-c045-481a-986d-f7c4c5851a67spring:session:expirations:1620393360000文章源自JAVA秀-https://www.javaxiu.com/28451.html

spring-session中有个定时任务,每个整分钟都会查询相应的spring:session:expirations:整分钟的时间戳中的过期SessionId,然后再访问一次这个SessionId,即spring:session:sessions:expires:SessionId,以便能够让Redis及时的产生key过期事件——即Session过期事件。文章源自JAVA秀-https://www.javaxiu.com/28451.html

参考

https://www.cnblogs.com/sxw123/p/13803478.html文章源自JAVA秀-https://www.javaxiu.com/28451.html

文章源自JAVA秀-https://www.javaxiu.com/28451.html

文章源自JAVA秀-https://www.javaxiu.com/28451.html

文章源自JAVA秀-https://www.javaxiu.com/28451.html

推荐阅读• 熟练掌握 MyBatis-Plus,一篇就够!• 牛逼!下一代 Docker 镜像构建神器• 你向 MySQL 数据库插入 100w 条数据用了多久?• 赞!推荐一款神仙颜值的 Redis 客户端工具最近面试BATJ,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。文章源自JAVA秀-https://www.javaxiu.com/28451.html

谢谢支持哟 (*^__^*)文章源自JAVA秀-https://www.javaxiu.com/28451.html

继续阅读
速蛙云 - 极致体验,强烈推荐!!!购买套餐就免费送各大视频网站会员!快速稳定、独家福利社、流媒体稳定解锁!速度快,全球上网、视频、游戏加速、独立IP均支持!基础套餐性价比很高!这里不多说,我一直正在使用,推荐购买:https://www.javaxiu.com/59919.html
weinxin
资源分享QQ群
本站是JAVA秀团队的技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定