分布式Session解决方案
什么是session
Session是通过服务器来存储用户数据的,在一次会话中,客户端向浏览器发送请求,首先cookie会自动携带上次请求存储的数据(JSESSIONID)到服务器,服务器根据这个参数到session库中查询,就可以识别浏览器的身份,如果不存在该id,就会创建一个JSESSIONID,并返回给客户端,同时将此JSESSIONID在客户端cookie中进行保存,默认session会保存30分钟.
分布式session一致性问题
客户端发送一个请求,经过负载均衡后该请求会被分配到服务器中的其中一个,由于不同服务器含有不同的web服务器(例如Tomcat),不同的web服务器中并不能发现之前web服务器保存的session信息,就会再次生成一个JSESSIONID,之前的状态就会丢失
解决方案
session复制
任何一个服务器上的session发生改变(增删改),该节点会把这个 session的所有内容序列化,然后广播给所有其它节点,不管其他服务器需不需要session,以此来保证Session同步
优点:
- 各个服务器之间可以实时响应同步
- 无需修改代码,只需要修改Tomcat配置,
缺点:
- 占用内网带宽,需要频繁的广播来同步session
- 水平拓展性差,添加服务器时都需要内存来存储这些复制来的session
前端存储
直接将session信息存储在cookie中,这样登录时不需要通过id来去session库中寻找对应session
缺点:
- 安全性差
- 数据量受cookie限制
session粘滞
将用户锁定到某一台服务器中,基于nginx的ip-hash策略,可以对客户端和服务器进行绑定,同一个客户端就只能访问该服务器,无论客户端发送多少次请求都被同一个服务器处理
缺点:
- 容易造成单点故障,如果有一台服务器宕机,那么该台服务器上的session信息将会丢失
- 如果前端也进行负载均衡,会导致hash失效,session绑定将会出问题
- 增加新机器就需要重新进行hash,用户需要重新登录
持久化到数据库
原理:拿出一个数据库,专门用来存储session信息。保证session的持久化。
优点:服务器出现问题,session不会丢失
缺点:如果网站的访问量很大,把session存储到数据库中,会对数据库造成很大压力,还需要增加额外的开销维护数据库
session共享机制
使用分布式缓存方案比如memcached、Redis
优点:
- 这是企业中使用的最多的一种方式
- spring为我们封装好了spring-session,直接引入依赖即可
- 数据保存在redis中,无缝接入,不存在任何安全隐患
- redis自身可做集群,搭建主从,同时方便管理
terracotta实现session复制
Terracotta的基本原理是对于集群间共享的数据,当在一个节点发生变化的时候,Terracotta只把变化的部分发送给Terracotta服务器,然后由服务器把它转发给真正需要这个数据的节点。
优点:
- 这样对网络的压力就非常小,各个节点也不必浪费CPU时间和内存进行大量的序列化操作。把这种集群间数据共享的机制应用在session同步上,既避免了对数据库的依赖,又能达到负载均衡和灾难恢复的效果。