您的位置:首页 > 数据库 > Redis

解决WEB集群session同步的方案,Redis内存缓存

2015-08-12 14:17 696 查看
转自:http://www.sziwap.com/archives/75.html

最近公司WEB服务器换集群方式,集群所带来直接的问题就是session共享。

如果用PHP自带的session处理方式,又要达到一致性,我已知的解决方案是NFS方法,不过担心磁盘性能以及session的处理机制,决定放弃这种方法,最后决定用内存缓存服务器来实现。

公司目前主要缓存的使用已经全部转至Redis下面(主要因为我的极力推荐,呵呵)。所以几简单写了个类实现了对session的操作,后续还要进行优化和扩展,前期没办法呀,公司催得紧呀。。。。

下面把代码贴出来,大家也分享一下了。呵呵。有啥意见也可以提提,别拍砖。呵呵。

[php] view
plaincopyprint?

/** 

 * @author shenjun 

 * @Createdate 2010-10-14 

 * @todo session机制,存在redis内存中,解决web集群中session共享问题 

 */  

class Session{  

  

    static protected $connect = FALSE;  

    protected $redis = NULL;  

    protected $redis_host = '192.168.1.107';  

    protected $redis_port = '6379';  

    protected $sess_id = NULL ;  

    protected $sess_life = 300 ;  

    protected $sessions = array () ;  

    ##是否自动保存session,默认为自动保存  

    protected $auto_save = true ;  

    ##判断是否有修改过session 中的值  

    protected $changed = false;  

    /** 

     * @todo redis初始化方法,单例入口 

     * @desc 自动判断系统是否带redis,则是否有编译redis的客户端环境 

     */  

    static public function singleton()  

    {  

        if ( self::$connect == FALSE )  

        {  

            self::$connect = new Session();  

        }  

        return self::$connect;  

    }  

    /** 

     * @todo 构造函数 

     * @desc 建立redis连接,取得已有sessionID,并取得所有session的值 

     */  

    protected function __construct()  

    {  

        if ( class_exists( 'redis' ) )  

        {  

            $redis = new Redis (  );  

            $conn = $redis->connect( $this->redis_host  , $this->redis_port );  

        } else {  

            require_once dirname(__FILE__). DIRECTORY_SEPARATOR . 'PhpRedis.php';  

            $redis = new PhpRedis ( $this->redis_host  , $this->redis_port );  

            $conn = $redis->connect();  

        }  

        if ( $conn )  

        {  

            $this->redis = $redis ;  

        } else {  

            trigger_error( '无法正常连接缓存服务器!' , E_USER_ERROR );  

        }  

        $sess_name = $this->GetSessionName();  

        #取得session ID  

        if ( isset( $_COOKIE[ $sess_name ] ) && !empty( $_COOKIE[ $sess_name ] ) )  

        {  

            $this->sess_id = $_COOKIE[ $sess_name ] ;  

            ##如果已经有session ID则取出其中的值  

            $this->sessions = (array)json_decode( $this->redis->get( $this->sess_id ) );  

        } else {  

            $this->sess_id = $this->GetSessionID() ;  

            ##如果没有cookie则建立cookie  

            setcookie( $sess_name , $this->sess_id );  

        }  

        return $this;  

    }  

    /** 

     * @todo 取得session name 

     */  

    public function GetSessionName ()  

    {  

        //sessionname 的名称用客户端的IP加上浏览器的信息  

        $name = $_SERVER['REMOTE_ADDR'].$_SERVER['HTTP_USER_AGENT'];  

        return hash ( 'crc32' , $name );  

    }  

  

    /** 

     * @todo 取得sessionID 

     * @return string 返回sessionID 

     */  

    public function GetSessionID( )  

    {  

        if ( $this->sess_id == null )  

        {  

            $id = time().$_SERVER['HTTP_USER_AGENT'];  

            $this->sess_id = hash( 'md5' , $id  );  

        }  

        return $this->sess_id;  

    }  

    /** 

     * @todo 设置session 值 

     * @desc 每次设置的值不会马上写入缓存,不过会记录在内存中,所以写入的值在当次也会有效 

     * @param string $name 相当于$_SESSION[$name] 这中间的变量 

     * @param any $value Session的值 

     */  

    public function Set ( $name , $value )  

    {  

        $this->sessions[ $name ] = $value;  

        $this->changed = true ;  

    }  

  

    public function __call( $name , $param )  

    {  

        trigger_error( sprintf( '您调用了不存的session方法%s!' , $name ) , E_USER_ERROR );  

    }  

  

    public function info()  

    {  

        return $this->redis->info();  

    }  

    /** 

     * @todo 取得session中所有的字段 

     * @desc 私有方法,不供外部使用 

     * @return array session中的值,如果空session则为空数组 

     */  

    protected function GetAll(  )  

    {  

        return count( $this->sessions ) > 0 ? $this->sessions : json_decode( $this->redis->get( $this->sess_id ) );  

    }  

    /** 

     * @todo 取得session中的值 

     * @desc 如果$name 为空,则返回全部session,如果不为空则返回对应key的值,如果key不存在,则返回空 

     * @param string $name session中的key 

     * @return array or string Session的值 

     */  

    public function Get( $name = '' )  

    {  

        if ( empty( $name ) )  

            return $this->sessions;  

        if ( isset( $this->sessions[ $name ] ) )  

            return $this->sessions[ $name ];  

        return null ;  

    }  

    /** 

     * @todo 删除session中的值 

     * @param string $name session中的key 

     * @return 无返回值 

     */  

    public function Del( $name = '' )  

    {  

        if ( empty( $name ) )  

            $this->sessions = array();  

        if ( isset( $this->sessions[ $name ] ) )  

            unset ( $this->sessions[ $name ] );  

        return false ;  

    }  

    /** 

     * @todo 保存session数据至缓存中 

     * @return 无返回值 

     */  

    public function Save()  

    {  

        if ($this->changed === true)  

        {  

            $this->redis->set( $this->sess_id , json_encode( $this->sessions ) );  

            ##更新过期时间  

            $this->redis->expire( $this->sess_id , $this->sess_life );  

            ##当保存过以后,就设置修改标记为假  

            $this->changed = false;  

        }  

    }  

    protected function Expire()  

    {  

        $this->redis->expire( $this->sess_id , $this->sess_life );  

    }  

    /** 

     * @todo 取得session的生命周期 

     * @desc 如果已过期则返回-1 

     */  

    public function GetExpire()  

    {  

        return $this->redis->ttl( $this->sess_id );  

    }  

    /** 

     * @todo 方法结束时,将session值写入缓存 

     */  

    public function __destruct()  

    {  

        $this->auto_save && $this->Save();  

    }  

}  

[php] view
plaincopyprint?

Session::singleton()->Set('name','shenjun');  

echo Session::singleton()->Get() ;  

echo Session::singleton()->Get( 'name' ) ;  

echo Session::singleton()->GetExpire();
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cookie session 集群