session 的共享问题

Jackey 其他 3,140 次浏览 没有评论

为啥会有这个问题?

随着网站访问量的增加,初期的一台服务器已经完全不能支持业务,这个时候我们就需要增加服务器设备,来抗住请求的增量。如下所示:

负载均衡的目的本来就是要为了平均分配请求,所以没有固定第一次访问和第二次访问是同一台服务器,实际上无法确定的。第一秒访问可能是a服务器,第二秒访问的可能是c服务器。这样的话,生成的 session 文件不可能恰巧都在同一台服务器上,所以,当同一个登录会员,访问第一台服务器生成了一个 session 数据。第二秒负载请求到第三台服务器,结果获取不到刚才生成的 session 数据。

只有涉及到多台后端服务器(php,java等处理服务器)的时候,才涉及到session读取不到的问题

session共享方案

session复制

使用一些文件同步工具(linux下的rsync),当a服务器中的 session 数据有更改的时候,就会把这些更改也同步到bc服务器上去。通过复制的方式,最终abc各个服务器上都拷贝了一份 session 数据。

坏处

  • 速度慢。复制数据会出现延迟。比如第一秒访问是a服务器,修改了session数据,负载均衡,可能下一秒访问是b服务器,session数据如果没有被复制到b服务器,则是读取不到session数据的,出现时间上的延迟。这种复制数据要消耗很多网络带宽的。在实际中业界用得比较少。机器的数量越多,复制数据的性能损耗越大。不具备
    高度扩展性。
  • 复制session的方式,无论是网络带宽成本还是硬件开销上都很大的

session存储客户端

把原来存储在服务器磁盘上的 session 数据存储到客户端的 cookie 中,一般是把session 数据按照自己定义的加密规则,加密后后存在 cookie

坏处

好处是服务器的压力减小了,因为 session 数据不存在服务器磁盘上。根本就不会出现session 读取不到的问题

  • 网络请求占用很多。每次请求时,客户端都要通过 cookie 发送 session 数据给服务器
  • 浏览器对 cookie 的大小存在限制。每个浏览器限制是不同的。
    • Firefox Safari 允许 cookie 多达4097个字节
    • Opera 允许 cookie 多达4096个字节
    • Internet Explorer 允许 cookie 多达4095个字节
  • 一般 session 中存的都是重要性数据(帐号、昵称、用户id),会存在安全问题
  • 淘宝以前用过这种方式,把session数据存储到cookie中,根据cookie来识别用户

访问规则

设计用一种算法(简单理解为规则),什么机制下 session 是保存在哪台服务器下,那么读取的时候就按照这种规则去读取,就能定位到原来的服务器。其原理是存session和读session数据保证都在一台服务器操作,就不会需要涉及到共享,具体实现方式是通过约定一种分发机制来实现。也叫做sticky模式(粘性会话模式),同一个用户的访问请求都被派送到同一个服务器上。

坏处

如果这台机子挂掉了,那么后续的请求按照session的规则还是会分发到这台服务器上去,但是现在不可用了,比如用户编号是1-200涉及到的session数据保存到a服务器上去。所以只要一台出问题,1-200的用户就无法实现登录了。后面就不可用了

Session中间层

做一个中间层服务器,专门来存储所有访问涉及到的session。也就是所有的session都存储在这里。服务器端统一从这里读取session数据。

NFS做中间层

通过nfs的方式,各个php服务器操作session数据的时候,是读取本地磁盘目录,但实际上是一个共享网络文件。各个php服务器实际上操作的都是同一个目录的文件。

关系型数据库做中间层

把以前存储在文件中的 session 数据存储到数据库中去,那么这样做,其实就不用到php内置的session机制了(session_start()之类的函数都不需要去用了)

从数据库拿session数据,约定什么情况下数据过期了然后自动清理,这里是指删除数据库中的行。保存在文件中的时候,php有垃圾回收机制会去自动清理过期的session文件。

有些做法跟这种思想是类似的:比如ecshopphpcms是把session数据都存储在数据库中去。服务端就是从数据库中拿session的数据。

坏处

  • 放在数据库里面,访问量小没有问题。大流量网站这么做,只会拖慢速度。因为得查询数据库,造成数据库压力大。高并发访问的情况下,会出现很大的性能问题。
  • 在线人数决定了其瓶颈,主要问题是影响性能。在线人数,因为登录的session数据存储在数据库中,只要是登录的用户就会涉及到频繁操作数据库。
  • 小网站,同时1-2万个人在线情况下。应该没什么问题。

对于大访问量的网站,数据库存储session方法可行性有待商榷。

访问量大的话,一个用户访问了n多个页面,哪怕是刷新页面,都需要去数据库取session 数据。数据库的承受压力,确实很恐怖。pv是多少,就要请求多少次数据库服务器。

访问每个页面都会去数据库查询是否登录,或者添加数据进数据库的 sessions 表保存在文件中的时候,则交给了操作系统去控制。一个用户怎么刷新页面,查看其他页面,都只需要读取单个 session 文件

非关系型数据库做中间层

session 数据保存在 memcached redis 之类内存数据库中,因为内存的数据读取速度是很快的,与磁盘读取的速度不是一个数量级的, 所以性能很高,用户并发量很大的时候尤其合适。而且方便统计在线人数,内存数据库系统能够控制内存中的过期数据自动失效(刚好符合session过期需要)

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Go