session多服务器共享的方案梳理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了session多服务器共享的方案梳理相关的知识,希望对你有一定的参考价值。

    实际上,session在php,.net,java等只要是后端语言都会用到。session的存储机制,各种语言都大体差不多。我觉得这跟cookie在各个语言中都会用到差不多。.net,java我没去了解过。但是存储原理是差不多的。区别就是,php,java,.net调用的函数,读和取session数据的方式不同。默认都是存储在本地文件中的(不然怎么会涉及到session共享问题呢,存储在数据库本身就可以实现共享的)。

    所以,无论是.net还是java都会涉及到session数据共享的问题。

    其实我的理解是,session的原理都是一样的。讨论session共享方案设计,是可以抛开具体的语言去讨论session共享方案设计。


目前业界解决session共享的几种思路,我总结如下:

 

第一种办法:把原来存储在服务器磁盘上的session数据存储到客户端的cookie中去。

    这样子,就不需要涉及到数据共享了。a客户端请求的时候,原来生成在服务器的数据生成到浏览器的cookie中,根据cookie中的数据识别用户。
    php由原来的”从本地(也就是服务器)磁盘上读取session数据”转变为”浏览器的cookie中读取数据”,

    这样子,在多台php服务器负载均衡的情况下,即便第一秒请求是a服务器,第二秒请求是b服务器,都不需要管哪台服务器了。反正都是读取客户端上的cookie数据。

    一般是把session数据按照自己定义的加密规则,加密后后存在cookie中。

    数据保存在cookie中这种做法有好处,也有坏处。

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

    带来的弊端是:

        网络请求占用很多。每次请求时,客户端都要通过cookie发送session数据给服务器。

        另外,浏览器对cookie的大小存在限制。每个浏览器限制是不同的。

        Firefox和Safari允许cookie多达4097个字节,包括名(name)、值(value)和等号。

        Opera允许cookie多达4096个字节,包括:名(name)、值(value)和等号。

        Internet Explorer允许cookie多达4095个字节,包括:名(name)、值(value)和等号。

 

    所以第一种方案不适合高访问量的情况下,因为高访问量的情况下,每次请求浏览器都要发送session数据给服务器。一般一个cookie大小2k的样子。

    要占用很多带宽了(服务器购买带宽是一个很大费用),成本增高。归纳为带宽性能,速度问题。

    存储到cookie中去,第二方面是安全问题:把session数据放到客户端,一般session中存的都是重要性数据(帐号、昵称、用户id等),会存在安全问题。

    了解到,淘宝以前用过这种方式,把session数据存储到cookie中,根据cookie来识别用户。

     

第二种思路:用一种算法(简单理解为规则),什么机制下session是保存在哪台服务器下,那么读取的时候就按照这种规则去读取,就能定位到原来的服务器。叫做分发请求,分发到特定的服务器上去,我理解其原理是存session和读session数据保证都在一台服务器操作,就不会需要涉及到共享,具体实现方式是通过约定一种分发机制来实现。

    也叫做sticky模式(粘性会话模式),同一个用户的访问请求都被派送到同一个服务器上。

    假设是同一个用户user1,每次访问都路由到同一台服务器上,这样即便是在负载均衡的情况下,也能保证每次访问都能读取到session,不需要做session数据共享了。

    关键多台server的原因是为负载均衡而做的,那么就得把原来负载均衡的规则假设是—a,现在改为按照session来均衡分发请求的规则—b。

     

    如果这台机子挂掉了,那么后续的请求按照session的规则还是会分发到这台服务器上去,但是现在不可用了。

    本来负载均衡有一个目的就是:当其中一台机子不可用的时候,会自动分发到可用的机子上去(自动判断现在要请求的机子是否可用)

     

    因为某种规则的session都是保存在一台服务器上,比如用户编号是1-200涉及到的session数据保存到a服务器上去。所以只要一台出问题,1-200的用户就无法实现登录了。后面就不可用了(可能想到1-200用户的session服务器用多台进行复制,这感觉很蹩脚,仍然需要用到复制的话,还不如用其他简便的方法)

 

第三种思路:做一个中间层,专门来存储所有访问涉及到的session。也就是所有的session都存储在这里。

    服务器端统一从这里读取session数据。

    使用这种中间层的思想来实现共享,具体的技术方案,我归纳为以下几种:

        1、 通过NFS文件共享的方式,多台php服务器共享保存session文件的磁盘。   

        2、保存在数据库中,这种方式的扩展性很强,可以随意增加WEB而不受影响。放在数据库里面安全方面好。

    

    弊端

        放在数据库里面,访问量小没有问题。大流量网站这么做,只会拖慢速度。因为得查询数据库,造成数据库压力大。

        高并发访问的情况下,会出现很大的性能问题。

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

        放到数据库存储后,就可以实现:多台web服务器统一操作数据库,因为数据都在数据库,web服务器都能从数据库进行读取,那么session数据就能实现共享。

        存储在数据库的做法,在线人数决定了其瓶颈,主要问题是影响性能。在线人数,因为登录的session数据存储在数据库中,只要是登录的用户就会涉及到频繁操作数据库。

        我觉得小网站,同时1-2万个人在线情况下。应该没什么问题。

        看网上丢出一个问题:对于大访问量的网站,数据库存储session方法可行性有待商榷。


   3、可以将session数据保存在memcached,redis之类内存数据库中,memcached是基于内存存储数据的,性能很高,用户并发量很大的时候尤其合适。

        主要是利用内存的数据读取速度是很快的,与磁盘读取的速度不是一个数量级的。

        使用内存存储:方便统计在线人数,内存的速度比磁盘访问快、内存数据库系统能够控制内存中的过期数据自动失效(刚好符合session过期需要)。 

        存储在redis比较理想的选择,存储在数据库中方便存储统计在线人数,那么存储在redis中也实现了这个要求。

        也可以存储在memcache中。但redis支持的数据类型多。所以用它好点



以上是关于session多服务器共享的方案梳理的主要内容,如果未能解决你的问题,请参考以下文章

多Web服务器之间共享Session的解决方案

Spring Session + Redis实现分布式Session共享

跨服务器Session共享解决方案(借鉴网络 记录一下)

Spring Session + Redis实现分布式Session共享

PHP实现多服务器SESSION共享

session共享方案