一口气说出 4 种分布式一致性 Session 实现方式,面试杠杠的~
前言
公司有一个 Web 管理系统,使用 Tomcat 进行部署。由于是后台管理系统,所有的网页都需要登录授权之后才能进行相应的操作。
起初这个系统的用的人也不多,为了节省资源,这个系统仅仅只是单机部署。后来随着用的人越来越多,单机已经有点扛不住了,于是我决定再部署了一台机器。
这时后端系统有两台服务,于是我们使用 Nginx 作为反向代理,整体架构图如下:
这个架构图想必大家应该比较熟悉,现在主流的 Web 系统应该都是这么部署。
经过一些调试之后,在一个夜深人静的晚上,将这套系统部署到了生产。本以为没有什么事的,很稳的交给测试小姐姐开始测试。
这一测,出了大问题!测试小姐姐反馈,登录过后,没过一会又需要登录,操作好几次都是这样。
检查了一下,系统应用,配置什么也没问题,那到底哪里出了问题?
这个时候组长刚准备下班,看到我们这里有问题,于是过来了看了一下。简单了解的一下基本情况,很快就找到了问题的原因,然后在 Nginx 端修改了下配置,重启解决了问题。
先点后赞,养成习惯~关注公号『程序通事』,快来呀!!
分布式一致性 Session
解决完问题,组长坐下解释了问题原因:分布式一致性 Session。
原先我们登录之后将会把用户登录信息放在 Session 中,用户每次操作首先先校验 Session 是否存在用户信息,如果不存在将会强制让用户先去登录。
原先架构的中我们只有一台应用系统,所有操作都在一台 Tomcat 上,这当然没有什么问题。
但是现在我们部署了两台系统,由于 Nginx 使用默认负载均衡策略(轮询),请求将会按照时间顺序逐一分发到后端应用上。
也就是说刚开始我们在 Tomcat1 登录之后,用户信息放在 Tomcat1 的 Session 里。过了一会,请求又被 Nginx 分发到了 Tomcat2 上,这时 Tomcat2 上 Session 里还没有用户信息,于是又要登录。
另外由于我们系统采用单点登录的方式,Tomcat2 登录之后会将 Tomcat1 登录信息失效,于是乎等到 Nginx 再把流量分发到 Tomcat1 时,Session 中用户登录信息已经失效,又要重新登录。
知道了问题,当然想知道解决办法了,于是组长教了下分布式一致性 Session 四种解决办法,小黑哥给大家整理了一下:
下面小黑哥将会以跟组长对话的形式,讲解分布式一致性 Session 解决办法。
Session 复制
组长:
如果此时 Tomcat1 Session 存在用户信息,而 Tomcat2 上没有存在。
这时如果我们将 Tomcat1 的 Session 复制到 Tomcat2 上,后面 Nginx 将请求转发到 Tomcat2 上,由于 Tomcat2 存在 Session ,这时就不需要再重新登录了。
架构图如下:
Tomcat 的 Session 复制的配置,网上有比较多的例子,这里小黑就不再贴了,感兴趣的同学可以自行搜索一下。
小黑:
对的,这种方式挺好啊。Tomcat 就支持这种方式,我们只需要修改 Tomcat 配置就好,我们应用代码都不用修改了。
组长:
说的对,但是这种方式还是有很多缺点。
第一,Session 复制传输需要占用内网带宽。
第二,我们的例子就只有两台机器,这个复制性能还可以。但是假设我们有 N 台机器,那么每次复制都要复制给 N-1 台机器,如果机器很多,可能会形成网络风暴,复制性能也会呈指数级下降。
第三, Tomcat 需要保存所有的 Session 数据,这个方案的 Session 存储在内存中,容易受到机器的总内存的限制。我们没办法通过加机器的方式水平扩展,我们能做的方式就是加大机器内存。但是机器内存越大,价格真的很贵!!!
所以不推荐使用这种方案。
Session 前端存储
小黑:
恩,这个方案确实有点不靠谱~
哎,有了!我们的 Session 里面其实就是存了用户的信息,那我现在不存 Tomcat Session 里,我把信息拿出来,存到浏览器的 Cookie 中。
这样,每个用户浏览器存储自己的 Cookie 信息,服务端就不需要存储,这就解决了 Session 复制方案的缺陷了。
接下来用户每次请求都把这个 Cookie 给我发过来,我判断 Cookie 里面用户信息不就好了。
架构图如下:
组长,欣赏看了一下我:
对,你这个方案确实可行。
不过么,如果用这种方案,首先你要想好加密方案。
用户信息可是我们的敏感数据,不能让别人轻易的窃取或者篡改数据了。
除了这个,这个方案每次请求都要携带 Cookie 传输,这会占用外网的带宽,如果 Cookie 过大,会增大网络的开销。
另外,我们存储的数据大小,容易受到 Cookie 限制。
所以这种还是不怎么常用,不过也是一种思路。
我比较推荐下面两种方案。
Session 粘滞(Sticky Sessions)
组长:
刚才应该看到了,我只是对 Nginx 的配置做了一些修改,然后这个问题就解决了吧。
其实这是因为我修改 Nginx 默认的负载均衡策略,使用 IP Hash 的方式。
Nginx 会使用请求者的 IP 来做 Hash,然后分发到一台机器上,这样可以保证同一 IP 的请求都落在同一台 Tomcat 上。
架构图如下:
上面这种方式我们使用 Nginx 四层负载均衡方式,其实 Nginx 还可以做到七层负载均衡方式,也就是使用 Http 协议中的一些业务属性来做 Hash,常见的有 userId,loginId等等。
架构图如下:
小黑:
这种方案看起来挺简单的,我们只需要修改 Nginx 配置就好了,应用端配置无需改动。
只要请求来源 IP 足够的随机,那么 IP HASH 之后两台应用上的流量将会足够随机。
另外后面如果两台机器扛不住,我们还可以水平扩展,再加机器,只要修改 Nginx 配置即可。
组长:
你说的这几点都很正确!
不过你有没有想过,像我们公司这种情况,所有人的出口的 IP 都是一个。那么我们公司的所有请求只会到一台机器上,那我们这种情况等于又变成单点了。
另外如果 Tomcat 重启,Session 由于是放置在内存内存中,这一部分的 Session 将会丢失,这就导致这部分用户将会重新登录。
最后,如果我们临时再加机器,修改完 Nginx 配置,重新启动之后,Nginx 将会重新计算 Hash 分发请求。
这种情况就会导致有一部分用户重新路由到一台新机器上,由于没有 Session,又需要重新登录了。
不过么,Tomcat 重启或者新加机器次数不会很多,所以这个问题也不大,用户体验稍差点。
今天的我们这个问题解决方案就先使用这个。
不过后面我们还是改成下面这种方式。
后端集中存储
组长:
上面几种的方式我们都是把 Session 存储在应用内存上,应用机器只要重启,Session 就会丢失。
为了这个解决这个问题,我们将 Session 单独存起来,保存到 Redis 或者 MySQL 中。
不过由于 Session 需要过期失效的特性,不需要持久化保存,所以这里我建议使用 Redis 来保存。
这样架构就变成下方这样的:
我们使用这种方案,上没有 Session 丢失的风险,当然前提是 Redis 不能宕机。
另外后期如果应用可以直接水平扩展。
如果后面应用的请求量很大,一台 Redis 扛不住了,那我们可以其实可以做集群扩展,根据缓存 Key 做路由。
小黑:
对对,这种方式好~
组长:
你不要高兴的太早,我们使用这个方案需要付出一定的代价的。
首先我们每次请求都需要调用一次 Redis ,这就增加一次网络的开销。
另外,引入 Redis,我们需要对相应的代码做出修改,这样复杂度就变高。
所以说,这个方案有利也有弊,当然对于我们的场景来说,利大于弊。
小黑:
恩,好像是这样的。
组长:
好了,这么晚了,问题解决了,我们去撸个串,我请客!
小黑:
老大,
一口气说出 4 种分布式一致性 Session 实现方式,面试杠杠的~的更多相关文章
- 一口气说出 9种 分布式ID生成方式,面试官有点懵了
整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 本文作者:程序员内点事 原文链接:https://mp.weix ...
- 一口气说出9种分布式ID生成方式,面试官有点懵
一.为什么要用分布式ID? 在说分布式ID的具体实现之前,我们来简单分析一下为什么用分布式ID?分布式ID应该满足哪些特征? 1.1.什么是分布式ID? 拿MySQL数据库举个栗子:在我们业务数据量不 ...
- 一口气说出 6种,@Transactional注解的失效场景
整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 一口气说出 9种 分布式ID生成方式,面试官有点懵了 面试总被问 ...
- 5种分布式共享session的方法
集群/分布式环境下5种session处理策略 转载 2016年03月16日 08:59:53 标签: session / nginx / 分布式 / 集群 11098 转载自:http://blog. ...
- 一口气说出 4种 LBS “附近的人” 实现方式,面试官笑了
引言 昨天一位公众号粉丝和我讨论了一道面试题,个人觉得比较有意义,这里整理了一下分享给大家,愿小伙伴们面试路上少踩坑.面试题目比较简单:"让你实现一个附近的人功能,你有什么方案?" ...
- 一般实现分布式锁都有哪些方式?使用redis如何设计分布式锁?使用zk来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
#(1)redis分布式锁 官方叫做RedLock算法,是redis官方支持的分布式锁算法. 这个分布式锁有3个重要的考量点,互斥(只能有一个客户端获取锁),不能死锁,容错(大部分redis节点创建了 ...
- 一口气说出Redis 5种数据结构及对应使用场景,面试要加分的
整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 更多优选 一口气说出 9种 分布式ID生成方式,面试官有点懵了 ...
- 9种分布式ID生成之 美团(Leaf)实战
整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 更多优选 一口气说出 9种 分布式ID生成方式,面试官有点懵了 ...
- 从Paxos到Zookeeper 分布式一致性原理与实践读书心得
一 本书作者介绍 此书名为从Paxos到ZooKeeper分布式一致性原理与实践,作者倪超,阿里巴巴集团高级研发工程师,国家认证系统分析师,毕业于杭州电子科技大学计算机系.2010年加入阿里巴巴中间件 ...
随机推荐
- Zookeeper面试专题
Zookeeper面试专题 1. Zookeeper是什么框架 分布式的.开源的分布式应用程序协调服务,原本是Hadoop.HBase的一个重要组件.它为分布式应用提供一致性服务的软件,包括:配置维护 ...
- 7000 字说清楚 HashMap,面试点都在里面了
我是风筝,公众号「古时的风筝」,一个兼具深度与广度的程序员鼓励师,一个本打算写诗却写起了代码的田园码农! 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在 ...
- Zookeeper分布式过程协同技术 - 群首选举
Zookeeper分布式过程协同技术 - 群首选举 群首概念 群首为集群中服务器选择出来的一个服务器,并被集群认可.设置群首目的在与对客户端所发起的状态变更请求进行排序,包括:create.setDa ...
- SQL注入之MySQL常用的查询语句
MySQL是一种使用很广的数据库,大部分网站都是用MySQL,所以熟悉对MySQL数据库的注入很重要. 首先来说下MySQL注入的相关知识点 在MySQL5.0版本之后,MySQL默认在数据库存放一个 ...
- 入门大数据---SparkSQL外部数据源
一.简介 1.1 多数据源支持 Spark 支持以下六个核心数据源,同时 Spark 社区还提供了多达上百种数据源的读取方式,能够满足绝大部分使用场景. CSV JSON Parquet ORC JD ...
- JavaScript基础对象创建模式之静态成员(027)
在支持“类”的面向对象语言中,静态成员指的是那些所有实例对象共有的类成员.静态成员实际是是“类”的成员,而非“对象”的成员.所以如果 MathUtils类中有个叫 max()的静态成员方法,那么调用这 ...
- JQuery 优缺点略谈
1.jQuery实现脚本与页面的分离 ; 2.最少的代码做最多的事情; 3.性能; 在大型JavaScript框架中,jQuery对性能的理解最好.尽管不同版本拥有众多新功能,其最精简版本只有18KB ...
- 洛谷 P4047 [JSOI2010]部落划分
这道题其实就是无线通讯网的双倍经验啦,只是在输出的时候不同罢了.还是一样的\(kruskal\)算法,但是在求的时候,应该在\(now=n-k+1\)的时候结束.本来到\(n-k\)就行了的,但是由于 ...
- Python3笔记001 - 1.1 python概述
第1章 认识python python语言特点 跨平台 开源的 解释型 面向对象 python语言的特点是:以对象为核心组织代码,支持多种编程范式,采用动态类型,自动进行内存回收,并能调用C语言库进行 ...
- (私人收藏)蓝色抽象科技感工作计划PPT模板
蓝色抽象科技感工作计划PPT模板 https://pan.baidu.com/s/16iFYH94dVXp_izksVMGMBg0ozp