session的存储了解以前是怎么做的,搞清楚了来龙去脉,才会明白进行共享背后的思想和出发点。我喜欢按照这样的方式来问(或者去搞清楚):为什么要session要进行共享,不共享会什么问题呢?

php中session的原理,以前做了一下总结,可以参考:http://www.cnblogs.com/wangtao_20/archive/2011/02/16/1955659.html

以前业界使用session的做法:

默认情况下,php的session文件是保存在磁盘文件中。在php.ini配置文件中的配置项如下:

session.save_handler = files

session.save_path = "N;/path"

第一个配置项是指定使用files(文件形式)存储session数据。

第二个参数指定保存的路径。N表示生成多少级目录(不放到一个目录下,分散到多个磁盘目录中去)

我的配置项是:session.save_path = "F:/wamp/tmp"。那么就会去这个目录下面看到很多session数据的文件。

当我们使用php的内置函数session_start()的时候,就是去上面指定的磁盘目录把session数据载入,实际上就是拿类似

sess_74dd7807n2mfml49a1i12hkc45的文件。

74dd7807n2mfml49a1i12hkc45就是大家经常说的什么session的id号。

php.ini中还有一个关键配置项,如下:

session.name = PHPSESSID

PHPSESSID就是cookie的名称,其实上面一串"74dd7807n2mfml49a1i12hkc45"会保存在一个名为PHPSESSID的cookie中。

根据http的请求机制,当浏览器请求的时候,头部信息会把浏览器中的cookie一起发给服务器。PHPSESSID这个cookie也

是在其中发给了服务器,php引擎通过读取PHPSESSID的值来确定要载入哪个session文件。

比如值为74dd7807n2mfml49a1i12hkc45,载入的就是"sess_74dd7807n2mfml49a1i12hkc45"。

注:当你调用php的函数session_start(),才表明你需要使用session文件了。不然平白无故就去载入文件,浪费性能。

===========================================

根据如上原理。session的数据默认是保存在磁盘文件中。假设这种情况:多台php服务器进行负载均衡的时候,比如有三台php服务器,为了实现负载均衡,那么三台服务器上面的php代码都是一样(拷贝一份)。

上面的图是nginx+fpm部署图。可以看到多台php服务器进行负载均衡。

生成session数据文件都是在本地了(a,b,c各自的服务器磁盘上)。负载均衡的目的本来就是要为了平均分配请求,所以没有固定第一次访问和第二次访问是同一台服务器,实际上无法确定的。第一秒访问可能是a服务器,第二秒访问的可能是c服务器。

所以同一个登录会员,实际上就会出现:第一秒访问第一台php服务器,第二秒访问的是第二台服务器。登录的信息一般是保存在session中的。这 样子登录保存的session数据就需要进行共享了。不然的话会出现,访问第一台服务器生成了一个session数据。第二秒负载请求到第三台服务器,结 果获取不到刚才生成的session数据。

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

在php环境中,只有多台php服务器(php服务器而非web服务器,session文件是php引擎生成的)的情况下,才会涉及到

session共享的问题。单台php服务器,存储都在一台主机上。不涉及到共享问题。因为session直接存储在这台服务器磁盘上是能够被本机读取到的。

如果是:一台php服务器,多台mysql服务器。这种也是负载均衡,这种负载均衡不涉及到共享问题。因为怎么session数据怎么操作都是保存在一台服务器上。

==================================

ps:实际上,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数据。

具体实现方式很多种。我的理解是,这里只是一种思想层面上的。我不知道淘宝的tbsession框架的具体实现。但是大致思想差不多,

由这个session框架来维护所有网站的session数据。我根据自己的理解,猜测淘宝的结构画图大致如下:

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

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

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

具体的操作细节。到时候还需要详细写一下。我根据理解,画了下面的图:

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

其实我理解本质是:自己写程序(php,java都可以实现,反正是保存在数据库中)模拟实现session的机制。

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

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

====================================弊端

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

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

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

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

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

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

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

我搜寻了一些资料,理解如下:

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

访问每个页面都会去数据库查询是否登录,或者添加数据进数据库的sessions表

保存在文件中的时候,则交给了操作系统去控制。一个用户怎么刷新页面,查看其他页面,都只需要读取单个session文件(sess_74dd7807n2mfml49a1i12hkc45)。

我觉得,ecshop,discuz之类的系统之所以把session存储在数据库中去,跟网站的应用级别有关。他们设计的系统本身就是给中小站长 用的,这些中小站长一般由于规模小,经济成本考虑,使用的是虚拟主机之类的。不具备对服务器的完全控制权限,比如还要安个memcache之类的,修改 php.ini之类的都需要自己拥有独立服务器才能操控的(vps也算,只是虚拟出来的硬件而已)。

其实真正要做到网站大了,系统承受不住了。也会自己有独立的技术人员可以进行二次开发。

discuz这些做通用的软件要考虑思路有个特点:得考虑大部分用户的服务器环境。比如经常看到源代码里面要做php版本判断的代码,判断是5.0之前的要如何处理,以求尽量适应大部分环境。而我们公司自己运营的内部系统,环境我们完全可控。做这些确实是多余的工作量。

另外一个点是,这些通用软件不会为了高级用户的特殊需求,做一些改变,结果另外一部分用户就无法使用了。没法两全。所以我的理解是,他们一般不会随 便去响应站长的需求,比如你明明是一个很大用户的站点,你用了我的系统,还要说数据量大了承受不住,表容易损坏。你都达到某种级别的应用了,还不自己进行 开发。来这里抱怨。找我按照你们方式定制,愿意给钱就好。

从这里我看到,不是说这些软件技术含量就多好,是多么成熟的解决方案。他们针对的用户群不同。

由于http是短连接,每次过程是:建立连接(握手)》》数据通信》》通信结束后结束连接。如果频繁的这样子连接后再断开,性能会非常差。

session存储在数据库中,有多少pv,就要多少次这样的数据库连接操作(得去数据库拿session才能知道有没有登录,登录是否过时)。

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

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

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

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

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

关于使用技术工具复制session数据同步到多台服务器的方案权衡:

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

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

复制session的方式,无论是网络带宽成本还是硬件开销上都很大的。

session多服务器共享的方案的更多相关文章

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

    session的存储了解以前是怎么做的,搞清楚了来龙去脉,才会明白进行共享背后的思想和出发点.我喜欢按照这样的方式来问(或者去搞清楚):为什么要session要进行共享,不共享会什么问题呢? php中 ...

  2. 集群环境(session多服务器共享的方案梳理)

    目前业界解决session共享的几种思路,我总结如下: 第一种办法:把原来存储在服务器磁盘上的session数据存储到客户端的cookie中去. 这样子,就不需要涉及到数据共享了.a客户端请求的时候, ...

  3. [转载]session多服务器共享的方案梳理

    转载网址: http://www.cnblogs.com/wangtao_20/archive/2013/10/29/3395518.html session的存储了解以前是怎么做的,搞清楚了来龙去脉 ...

  4. 如何实现session跨服务器共享

    Session共享有多种解决方法,常用的有四种:客户端Cookie保存.服务器间Session同步.使用集群管理Session.把Session持久化到数据库. 1.客户端Cookie保存 以cook ...

  5. tomcat8的session共享实现方案

    tomcat8的session共享实现 下载tomcat 版本:apache-tomcat-8.0.53.zip 实现步骤,只需要两步 两个tomcat的server.xml都增加一样cluster配 ...

  6. 【转】centos安装memcached+php多服务器共享+session多机共享问题

    参考博文: centos安装memcached 源码安装 Yum安装Memcache Memcached内存分配优化及使用问题 <转>php+memcached 实现session共享 P ...

  7. Session共享实现方案调研

    1.背景 随 着互联网的日益壮大,网站的pv和uv成线性或者指数倍的增加.单服务器单数据库早已经不能满足实际需求.目前大多数大型网站的服务器都采用了分布式服务 集群的部署方式,所谓集群,就是让一组计算 ...

  8. 服务器共享session的方式

    服务器共享session的方式 简介 1. 基于NFS的Session共享 NFS是Net FileSystem的简称,最早由Sun公司为解决Unix网络主机间的目录共享而研发.这个方案实现最为简单, ...

  9. PHP 实现多服务器共享 SESSION 数据

    PHP 实现多服务器共享 SESSION 数据 2011 年 12 月 05 日评论暂缺 一.问题起源 稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一 ...

随机推荐

  1. 201521123063 《JAVA程序设计》 第5周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 上周学习了继承和多态,满足is-a条件,但是发现会导致继承的滥用,如果只是但以的 ...

  2. 201521123030《Java程序设计》第5周学习总结

    1. 本周学习总结 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 因为i在类中是priv ...

  3. 201521123026《Java程序设计》第2周学习总结

    1. 本章学习收获 1.熟悉了码云的部分功能的使用 2.java编程基础的巩固以及延伸 3.解决了部分PTA编程时所遇到困难并明白了解决困难的方法的原理 4.了解了用package和import管理类 ...

  4. java第十三次作业

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相内关容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...

  5. 201521123059 《Java程序设计》第十周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 多线程的相关理解图: 2. 书面作业 本次PTA作业题集异常.多线程 Q1:finally 题目4-2 1. ...

  6. 多线程面试题系列(2): CreateThread与_beginthreadex本质区别

    本文将带领你与多线程作第一次亲密接触,并深入分析CreateThread与_beginthreadex的本质区别,相信阅读本文后你能轻松的使用多线程并能流畅准确的回答CreateThread与_beg ...

  7. 移动商城第八篇【添加商品之基本属性和大字段数据(FCK文本编辑器)】

    添加商品 修改对应的超链接url,controller转发到对应的JSP页面 <a href="${path}/item/toAddItem.do" class=" ...

  8. java.lang.RuntimeException: java.sql.SQLException: Too many parameters: expected 0, was given 1 Quer

    如果出现类似这样的错误,检查一下是否sql语句和参数的位置对调了. java.lang.RuntimeException: java.sql.SQLException: Too many parame ...

  9. Linux Ubuntu从零开始部署web环境及项目 -----部署项目 (三)

    上一篇讲了如何在linux搭建web环境,这边将如何部署项目. 1,打包项目包 2,上传项目包 将.war项目包通过xftp上传到tomcat目录wabapps目录下 3,启动项目 通过xshell命 ...

  10. Day4 装饰器——迭代器——生成器

    一 装饰器 1.1 函数对象 一 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素 二 利用该特性,优雅的取代多 ...