ITPub博客

首页 > IT职业 > IT生活 > 如何运用PHP+REDIS解决负载均衡后的session共享问题

如何运用PHP+REDIS解决负载均衡后的session共享问题

IT生活 作者:开发者学习指南 时间:2019-07-25 14:26:54 0 删除 编辑

稿件来源: https://developer.aliyun.com/article/709696


 

一、为什么要使用 Session 共享?

稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名、密码在整个网站的各个模块中都是可以登录使用的。各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可。但还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,仍然需要重新登录,这就是一次登录,全部通行的问题,映射到技术上,其实就是各个服务器之间如何实现共享 SESSION 数据的问题。

二、了解 session 工作原理

在解决问题之前,先来了解一下 PHP SESSION 的工作原理。在客户端(如浏览器)登录网站时,被访问的 PHP 页面可以使用 session_start() 打开 SESSION ,这样就会产生客户端的唯一标识 SESSION ID (此 ID 可通过函数 session_id() 获取 / 设置)。 SESSION ID 可以通过两种方式保留在客户端,使得请求不同的页面时, PHP 程序可以获知客户端的 SESSION ID ;一种是将 SESSION ID 自动加入到 GET URL 中,或者 POST 的表单中,默认情况下,变量名为 PHPSESSID ;另一种是通过 COOKIE ,将 SESSION ID 保存在 COOKIE 中,默认情况下,这个 COOKIE 的名字为 PHPSESSID 。这里我们主要以 COOKIE 方式进行说明,因为应用比较广泛。

服务端通过客户端传递的 session_id 区分用户,用来标记用户的登录状态。

用户再次发送请求的时候,把服务端返回的 session_id 通过 cookie[ 或者 URL 传参 ] 的形式传递到服务端,这样服务端就可以区分出来具体操作的用户。

三、如何解决负载均衡之后的 session 共享问题?

1 .不使用 session ,换作 cookie

session 改成 cookie ,就能避开 session 的一些弊端。【安全性较低】

2 .数据库记录下 session 信息

使用数据库记录 session 信息, session 的使用频率比较高,如果存在数据库中,频繁的读取会对数据库产生较大的压力,网站性能瓶颈一般都存在数据库 .

3 .负载均衡的时候使用 ip_hash 算法进行分发

使用 ip_hash 可能会导致某一台服务器负载较大。如果某段时间内服务器进入了很多固定 IP 代理的请求   ,如果代理 IP 的负载过高就会导致 ip_hash 对应的服务器负载压力过大,这样 ip_hash 就失去了负载均衡的作用了。

4 .对 session 文件进行同步

使用同步工具对 session 文件进行同步,保证负载服务器的 session 文件都是一致的,这种做法虽然可以解决 session 共享的问题,同样的内容会存在多个服务器上,而且部分服务器存在的 session 文件可能从开始到结束完全没有使用到,浪费了服务器的资源。 rsync inotify-tools 等】

5 .使用 memcache 或者 redis 保存 session 信息 [ 建议 ]

相比文件取信息,从内存取数据速度要快很多,而且在多个服务器需要共用 session 时会比较方便,将这些服务器都配置成使用同一组 memcached 服务器就可以,减少了额外的工作量。其缺点是 session 数据都保存在 memory 中,一旦宕机,数据将会丢失。但对 session 数据来说并不是严重的问题。

四、 PHP+REDIS 解决 session 共享问题

1 session 默认存储是 php.ini 中配置的

//session 存储方式

session .save_handler = files 

 

//session 保存路径   N 表示按照分级存储

session .save_path = "N;/path"

注: session.save_path = "2;/data/session_tmp" 代表将 session 文件分成两级存放,即 /data/session_tmp/4/b /sess_4b1e384ad74619bd212e236e52a5a174If ,取前两位字符,但是 php 并不生成目录,需要自己手工生成。

//session 保存的目录

session .save_path = "d:/wamp/tmp"     php 自带函数 session_save_path

// 是否自动开启 session

session .auto_start =

2 、设置 session 保存方式为 redis

(1) 修改完成之后重启 php-fpm nginx php.ini 配置文件

session .save_handler = redis

        session .save_path = “tcp: //127.0.0.1:6379″

(2) 通过 ini_set 设置

ini_set(“session.save_handler”,”redis”);

        ini_set(“session.save_path”,”tcp://127.0.0.1:6379″);

有密码设置

  ini_set(“session.save_path”,”tcp://127.0.0.1:6379?auth=redisauthkey″);

(3) 具体实现

<?php        

// 如果未修改 php.ini 下面两行注释去掉       

  //ini_set('session.save_handler', 'redis');      

  //ini_set('session.save_path', 'tcp://127.0.0.1:6379');     

    session_start();       

    $_SESSION[ 'sessionid' ] = 'this is session content!' ;       

    echo $_SESSION[ 'sessionid' ];      

     echo '<br/>' ;

        $redis = new redis();      

         $redis->connect( '127.0.0.1' , 6379 );      

          $redis->auth( ‘redisauthkey’ );

//redis session_id 作为 key 并且是以 string 的形式存储        

echo $redis->get( 'PHPREDIS_SESSION:' . session_id()); 

?>

3 、通过 session_id 建立自己的一套 session 机制

借助 session_id 建议一套自己的机制,原理可以参考 session 保存机制。

·          用户第一次请求时候,给用户下发 session_id

·          之后请求都要带上 session

·          用户登录之后把用户信息存在 redis ,借助 session_id 表示。

好处就是:把自己的一套 session 机制抽象为类,如果之后 session 不存在 redis ,后期可以直接通过修改类文件解决问题。

 


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69926013/viewspace-2651732/,如需转载,请注明出处,否则将追究法律责任。

下一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2019-05-28

  • 博文量
    34
  • 访问量
    23896