为什么要session共享
现在稍微大一点的网站基本上都有好几个子域名,比如www.feiniu.com, search.feiniu.com, http://member.feiniu.com,这些网站如果需要共用用户登录信息,那么就需要做到session共享,当然前提是有相同的主域。
PHP的session原理
客户端访问php页面,执行session_start,生成session_id,一般我们是把session_id存储到cookie上,session内容保存在服务端,客户端访问访问不同的页面都会把session_id传到服务端,通过session_id来获取session内容。
流程是这样,可是不同的服务器会对同一个客户端产生不同的session_id,这样的话不同服务器就不能得到相同的session内容了。而且PHP 默认的 SESSION 数据都是分别保存在本服务器的文件系统中。
所以我们要解决session共享,就必须解决两个问题:
1. 多台服务器用同一个session_id
这个比较容易解决,只要在php中设置存session_id的cookie域名
为网站主域就可以了
打开PHP.ini, 设置session.cookie_domain = .feiniu.com,
当然也可以在php代码当中
设置ini_set("session.cookie_domain","feiniu.com");
2. 多台服务器用同一个session_id访问到相同的session内容
要实现这点,就必须把session内容存储到让所有服务器都能访问到的地方,
php的session内容是默认存储到本服务器的文件中的,
一般的解决方案是存入数据库,memcache或者redis这种缓存服务器,
当然用默认的文件存储方式也可以,用NFS统一存储。
3. 如何选择存储引擎
默认文件存储:这种方式的session销毁依托于php垃圾收集器,在高并发或销毁时间较长的情况下,在SESSION目录下产生大量文件,当然可以设置分级目录进行 SESSION 文件的保存。
这会导致两个问题:第一、查找文件慢;第二,每个目录下可容纳的文件数是有限的,可能会导致新SESSION储存失败。
1) 设置Session存储的引擎,php.ini 文件
[Session]
session.save_handler = files
session.save_path = /data/SessionLogs
2)默认情况下的Session的使用
/*** session的使用* 默认情况(不更改session.save_handle参数时),是存储在文件file中的* 默认情况下使用session的情况(用户24分钟内没有刷新操作会过期)* 每个用户对应唯一session_id,每一个session_id对应服务器中存储的一个session文件,这个文件中存储了当前session_id的信息,比如下面,就存储了name和age的键值*/
session_start();
echo session_id();
echo "
";
$_SESSION['age'] = 26;
$_SESSION['name'] = 'xiaobudiu';
var_dump($_SESSION);
3)在服务器中存储的形式是这样的
数据库存储:把Session存储在数据库里可以防止Session数据被垃圾收集器删除,可以固化存储session数据。但是用数据库来同步session,会加大数据库的IO,增加数据库的负担。而且数据库读写速度较慢,不利于session的适时同步。
memcache存储:
以这种方式来同步session,不会加大数据库的负担,并且安全性比较高,把session放到内存里面,比从文件中读取要快很多。
但是memcache把内存分成很多种规格的存储块,有块就有大小,这种方式也就决定了,memcache不能完全利用内存,会产生内存碎片,如果存储块不足,还会产生内存溢出
那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用,memcached不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源。
Redis存储:
与memcache相比,redis访问稍稍慢一点点,好处是:redis支持的数据结构较多,可以存储数组或对象,而memcache只能存储字符串。
在session机器重启的情况下,memcache所有用户都必须重新获得 session,而redis不会在突然涌来大量用户产生了很多数据把存储 session 的机器内存占满了的情况下,memcache 会罢工,所有 key 都没过期的话就不停的覆盖最后写入的数据,而 redis 只是会变慢 ,不会影响程序的逻辑。
1)设置php.ini 文件中的session.save_handle 和session.save_path
session.save_handler = Redis
session.save_path = "tcp://localhost:6379"
注1:如果连接的是远程redis,需要将localhost换成对应的远程ip地址。像这样
session.save_handler = Redis
session.save_path = "tcp://47.94.203.119:6379"
注2:如果为redis已经添加了auth权限(requirpass),session.save_path项则应该这样写
session.save_handler = Redis
session.save_path = "tcp://47.94.203.119:6379?persistent=1&database=10&auth=myredisG506"
2)使用redis存储session信息
/*** 将session存储在redis中*/
session_start();
echo session_id();
echo "
";
$_SESSION['age'] = 26;
$_SESSION['name'] = 'xiaobudiu';
$_SESSION['sex'] = 'man';
var_dump($_SESSION);
在redis上是以这样的形式进行存储的
使用Redis存储Session,并设置Session会话存活时间以及Session中某一元素存活时间
封装session类 b.php
/*** session控制类**/
class Session
{
function __construct($lifetime = 3600)
{
//初始化设置session会话存活时间 ini_set('session.gc_maxlifetime',$lifetime);
}
/*** 设置当前会话session的key-value* @param String $name session name* @param Mixed $data session data* @param Int $expire 有效时间(秒)*/
function set($name, $data, $expire = 600)
{
$session_data = array();
$session_data['data'] = $data;
$session_data['expire'] = time()+$expire;
$_SESSION[$name] = $session_data;
}
/*** 读取当前会话session中的key-value* @param String $name session name* @return Mixed*/
function get($name)
{
if(isset($_SESSION[$name])) {
if($_SESSION[$name]['expire'] > time()) {
return $_SESSION[$name]['data'];
}else{
self::clear($name);
}
}
return false;
}
/*** 清除当前session会话中的某一key-value* @param String $name session name*/
function clear($name)
{
unset($_SESSION[$name]);
}
/*** 删除当前session_id对应的session文件(清空当前session会话存储)*/
function destroy()
{
session_destroy();
}
}
session类的使用:d.php
require_once 'b.php';
session_start();
$session = new Session();
$session->set('wan','kkkk',1966);
$session->set('name','xiaobudiu');
$session->set('age',26);
$session->set('sex','man');
//输出当前会话的session存储数据var_dump($_SESSION);
//unset掉某一个session属性//$session->clear('name');
//删除当前session_id对应session文件//$session->destroy();//echo $session->get('sex');
redis中显示:
以上内容希望帮助到大家,需要更多文章可以关注公众号:PHP从入门到精通,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些PHP高级、架构视频资料和大厂PHP面试PDF免费获取,