分布式系统session一致性的问题

session的概念

什么是session?

服务器为每一个用户建立一个会话,存储用户的相关信息,以便屡次请求可以定位到同一个上下文。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,若是该用户尚未会话,则 Web 服务器将自动建立一个 Session 对象。当会话过时或被放弃后,服务器将终止该会话。nginx

Web开发中,web-server能够自动为同一个浏览器的访问用户自动建立session,提供数据存储功能。最多见的,会把用户的登陆信息、用户信息存储在session中,以保持登陆状态。web

什么是session一致性问题?

只要用户不重启浏览器,每次http短链接请求,理论上服务端都能定位到session,保持会话。数据库

分布式session

单服务器web应用中,session信息只需存在该服务器中,这是咱们前几年最常接触的方式,可是近几年随着分布式系统的流行,单系统已经不能知足日益增加的百万级用户的需求,集群方式部署服务器已在不少公司运用起来,当高并发量的请求到达服务端的时候经过负载均衡的方式分发到集群中的某个服务器,这样就有可能致使同一个用户的屡次请求被分发到集群的不一样服务器上,就会出现取不到session数据的状况,因而session的共享就成了一个问题。后端

如上图,假设用户包含登陆信息的session都记录在第一台web-server上,反向代理若是将请求路由到另外一台web-server上,可能就找不到相关信息,而致使用户须要从新登陆。浏览器

Session一致性解决方案

1.session复制(同步)

 

思路:多个web-server之间相互同步session,这样每一个web-server之间都包含所有的session缓存

优势:web-server支持的功能,应用程序不须要修改代码安全

不足服务器

  • session的同步须要数据传输,占内网带宽,有时延cookie

  • 全部web-server都包含全部session数据,数据量受内存限制,没法水平扩展网络

  • 有更多web-server时要歇菜

 

2.客户端存储法 

思路:服务端存储全部用户的session,内存占用较大,能够将session存储到浏览器cookie中,每一个端只要存储一个用户的数据了

优势:服务端不须要存储

缺点

  • 每次http请求都携带session,占外网带宽

  • 数据存储在端上,并在网络传输,存在泄漏、篡改、窃取等安全隐患

  • session存储的数据大小受cookie限制

“端存储”的方案虽然不经常使用,但确实是一种思路。

 

3.反向代理hash一致性

 思路:web-server为了保证高可用,有多台冗余,反向代理层能不能作一些事情,让同一个用户的请求保证落在一台web-server上呢?

 

 

方案一:四层代理hash

反向代理层使用用户ip来作hash,以保证同一个ip的请求落在同一个web-server上

 

方案二:七层代理hash

反向代理使用http协议中的某些业务属性来作hash,例如sid,city_id,user_id等,可以更加灵活的实施hash策略,以保证同一个浏览器用户的请求落在同一个web-server上

优势

  • 只须要改nginx配置,不须要修改应用代码

  • 负载均衡,只要hash属性是均匀的,多台web-server的负载是均衡的

  • 能够支持web-server水平扩展(session同步法是不行的,受内存限制)

不足

  • 若是web-server重启,一部分session会丢失,产生业务影响,例如部分用户从新登陆

  • 若是web-server水平扩展,rehash后session从新分布,也会有一部分用户路由不到正确的session

session通常是有有效期的,全部不足中的两点,能够认为等同于部分session失效,通常问题不大。

对于四层hash仍是七层hash,我的推荐前者:让专业的软件作专业的事情,反向代理就负责转发,尽可能不要引入应用层业务属性,除非不得不这么作(例如,有时候多机房多活须要按照业务属性路由到不一样机房的web-server)。

 

4.后端统一集中存储

 

思路:将session存储在web-server后端的存储层,数据库或者缓存

优势

  • 没有安全隐患

  • 能够水平扩展,数据库/缓存水平切分便可

  • web-server重启或者扩容都不会有session丢失

不足:增长了一次网络调用,而且须要修改应用代码

对于db存储仍是cache,我的推荐后者:session读取的频率会很高,数据库压力会比较大。若是有session高可用需求,cache能够作高可用,但大部分状况下session能够丢失,通常也不须要考虑高可用。

 

总结

保证session一致性的架构设计常见方法:

  • session同步法:多台web-server相互同步数据

  • 客户端存储法:一个用户只存储本身的数据

  • 反向代理hash一致性:四层hash和七层hash均可以作,保证一个用户的请求落在一台web-server上

  • 后端统一存储:web-server重启和扩容,session也不会丢失

 

对于方案3和方案4,我的建议推荐后者:

  • web层、service层无状态是大规模分布式系统设计原则之一,session属于状态,不宜放在web层

  • 让专业的软件作专业的事情,web-server存session?仍是让cache去作这样的事情吧。

 

来源:架构师之路

相关文章
相关标签/搜索