多台web如何共享session进行存储(转载)
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代码都是一样(拷贝一份)。
生成session数据文件都是在本地了(a,b,c各自的服务器磁盘上)。负载均衡的目的本来就是要为了平均分配请求,所以没有固定第一次访问和第二次访问是同一台服务器,实际上无法确定的。第一秒访问可能是a服务器,第二秒访问的可能是c服务器。
所以同一个登录会员,实际上就会出现:第一秒访问第一台php服务器,第二秒访问的是第二台服务器。登录的信息一般是保存在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。也就是所有的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文件。
====================================弊端
放在数据库里面,访问量小没有问题。大流量网站这么做,只会拖慢速度。因为得查询数据库,造成数据库压力大。
高并发访问的情况下,会出现很大的性能问题。
放到数据库存储后,就可以实现:多台web服务器统一操作数据库,因为数据都在数据库,web服务器都能从数据库进行读取,那么session数据就能实现共享。
存储在数据库的做法,在线人数决定了其瓶颈,主要问题是影响性能。在线人数,因为登录的session数据存储在数据库中,只要是登录的用户就会涉及到频繁操作数据库。
我觉得小网站,同时1-2万个人在线情况下。应该没什么问题。
看网上丢出一个问题:对于大访问量的网站,数据库存储session方法可行性有待商榷。
我搜寻了一些资料,理解如下:
访问量大的话,一个用户访问了n多个页面,哪怕是刷新页面,都需要去数据库取session数据。数据库的承受压力,确实很恐怖。pv是多少,就要请求多少次数据库服务器。
可以将session数据保存在memcached,redis之类内存数据库中,memcached是基于内存存储数据的,性能很高,用户并发量很大的时候尤其合适。
主要是利用内存的数据读取速度是很快的,与磁盘读取的速度不是一个数量级的。
使用内存存储:方便统计在线人数,内存的速度比磁盘访问快、内存数据库系统能够控制内存中的过期数据自动失效(刚好符合session过期需要)。
存储在redis比较理想的选择,存储在数据库中方便存储统计在线人数,那么存储在redis中也实现了这个要求。
也可以存储在memcache中。但redis支持的数据类型多。所以用它好点。
4.关于使用技术工具复制session数据同步到多台服务器的方案权衡:
这种方案是,使用一些文件同步工具(linux下的rsync),当a服务器中的session数据有更改的时候,就会把这些更改也同步到b,c服务器上去。通过复制的方式,最终a,b,c各个服务器上都拷贝了一份session数据。
这种方式的弊端是,速度慢。复制数据会出现延迟。比如第一秒访问是a服务器,修改了session数据,负载均衡,可能下一秒访问是b服务器,session数据如果没有被复制到b服务器,则是读取不到session数据的,出现时间上的延迟。这种复制数据要消耗很多网络带宽的。在实际中业界用得比较少。机器的数量越多,复制数据的性能损耗越大。不具备高度扩展性。
复制session的方式,无论是网络带宽成本还是硬件开销上都很大的。
多台web如何共享session进行存储(转载)的更多相关文章
- php 高级 多台web服务器共享session的方法
解决多台web服务器共享session的问题,至少有以下三种方法: 一.将本该保存在web服务器磁盘上的session数据保存到cookie中 即用cookie会话机制替代session会话机制, ...
- php面试题12(多态web服务器共享session的方法:将session存到数据库)($val=&$data[$key];)
php面试题12(多态web服务器共享session的方法:将session存到数据库)($val=&$data[$key];) 一.总结 1.多态web服务器共享session的方法: ...
- 多台服务之间共享Session
一.问题:为了满足足够大的应用,满足更多的客户,就需要架设N台Web服务器(N>=2),在多台Web服务器的情况下,就会涉及到一个问题:用户登陆一台服务器以后,如果在跨越到另一台服务器的时候能够 ...
- 同一个tomcat多个web应用共享session
tomcat版本:apache-tomcat-6.0.29(次方tomcat6和tomcat7支持) 1.修改D:\apache-tomcat-6.0.29\conf\server.xml文件 ...
- PHP实现多web服务器共享SESSION数据-session数据写入mysql数据库
http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2010/0822/5276.html http://hi.baidu.com/lei_com/ ...
- cookie、session的联系和区别,多台web服务器如何共享session
1.Cookie与Session的联系: cookie在客户端保存状态,session在服务器端保存状态.但是由于在服务器端保存状态的时候,在客户端也需要一个标识,所以session也可能要借助coo ...
- session和cookie区别,多台WEB服务器如何共享session,禁用COOKIE后SESSION是否可用,为什么?
答:session的运行机制: 用户A访问站点Y,如果站点Y指定了session_start();(以下假设session_start()总是存在)那么会产生一个session_id,这个sessio ...
- 多台web服务器之间共享session
常见的几种方法如下: 1. 写客户端Cookie的方式 当用户登陆成功以后,把网站域名.用户名.密码.token.session有效时间全部采用cookie的形式写入到客户端的cookie里面,如果用 ...
- web服务器集群(多台web服务器)后session如何同步和共享
在访问量上去以后,很多人会采用web集群的方式在满足逐渐增长的用户量.这时候就不得不面对一个问题,那就是在多个服务器下,每次请求都会因为负载均衡而分配到不同的服务器上.用户在登录服务器后,下一次请求被 ...
随机推荐
- UVA 12661(动态权值+最短路,dij)
题意:赛车背景,给你n个节点,m条边的图以及起点和终点:其中每条边的信息包括u(起点),v(终点),a(开启的时间),b(关闭的时间),d(通过这条道路的时间):求最短通过的时间,其中车在进的时候,保 ...
- php实现文件下载
<?php $filename = '路径+实际文件名'; //文件的类型 header('Content-type: application/octstream'); //下载显示的名字 he ...
- WebDriver定位元素方法
如果把页面上的元素看作人的话,在现实世界如何找到某人呢?方法有三: 一.通过人本身的属性,例如他的姓名,手机号,身份证号,性别,这些可区别他人的属性.在web页面上的元素也有这些属性,例如,id.na ...
- day5--<装饰器、模块、字符串格式化、生成器、迭代器>logging模块
本节大纲: 一:双层装饰器:一个函数可以被多层装饰器进行装饰,函数渲染(编译)从下到上,函数执行从上到下.如下程序: #!/usr/bin/env python #-*-coding:utf-8-*- ...
- CentOS 6.5 安装CodeBlocks
CentOS 6.5 安装CodeBlocks 经历了无数痛苦的折磨,Linux上的库依赖真是能把人逼疯,终于在Google上找到了办法,勉强将CodeBlocks安装成功. 1.为了避免最新版本的C ...
- java中的static关键词
以下来自:http://www.cnblogs.com/codc-5117/archive/2011/12/04/2275298.html Static基本规则: (1)一个类 ...
- 【 D3.js 入门系列 --- 4 】 如何使用scale(比例)
在上一节中使用了一个很重要的概念 — scale (这个不知道翻译成什么,暂且叫它比例).本节将重点介绍它的相关使用方法. 在介绍 scale 之前,先介绍两个经常和 scale 一起出现的函数,在上 ...
- Do It Wrong, Get It Right
Do It Wrong, Get It Right Time Limit: 5000ms, Special Time Limit:12500ms, Memory Limit:65536KB Total ...
- windows github 命令行使用
1.下载git客户端工具,以下2个网站一样的https://git-for-windows.github.io/https://git-scm.com/download/win/ 2.初始化ssh-k ...
- NeHe OpenGL教程 第四十六课:全屏反走样
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...