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

来源:互联网 发布:html5 书籍 知乎 编辑:程序博客网 时间:2024/06/06 01:44

转自:http://www.sziwap.com/archives/75.html

最近公司WEB服务器换集群方式,集群所带来直接的问题就是session共享。
如果用PHP自带的session处理方式,又要达到一致性,我已知的解决方案是NFS方法,不过担心磁盘性能以及session的处理机制,决定放弃这种方法,最后决定用内存缓存服务器来实现。

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

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

/** * @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();    }}

其实用方法也很简单了。

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


原创粉丝点击