优化使用mysql存储session

  •   2009-07-31/22:44
  • 之前写过两篇文章《自定义SESSION(二)——数据库保存》和《我为什么不使用session》
      但后来发现都有问题。前者处理在实际中几乎没什么用处,而且session回收还得自己另外处理。后者频繁的操作数据库,打来了很大的性能问题。

      这两天仔细考虑下,大致给出一个方案,但还没有具体详细的测试。
      1、session处理和统计结合起来。同时游客也都有记录。
      2、完全使用数据库和cookie来模拟session的功能。
      3、用户的对session的操作都尽量保证在一条sql语句完成。不用到session的时候,绝对不多一条查询。
      4、为了效率起见,session的回收没有集成进来,但提供了接口,可以调用实现。

    暂时给出代码,不具体解释。
    sql

     

    CREATE TABLE `*****_session` (
     `sid` char(32) NOT NULL,
     `uid` int(10) NOT NULL,
     `username` char(32) NOT NULL,
     `usertype` tinyint(1) NOT NULL,
     `activetime` int(10) NOT NULL,
     `expiry` int(10) NOT NULL,
     `ip` char(15) NOT NULL,
     `url` char(80) NOT NULL,
     `value` char(255) NOT NULL,
     PRIMARY KEY  (`sid`)
    ) ENGINE=MEMORY DEFAULT CHARSET=utf8;

     


    php代码


    <?
    class session{
       
        private $_sessionPrex= '';//session的前缀
       
        private $_time = '';//当前时间
       
        private $_model = null;//数据库操作模型
       
        private $_expiry = 1200;//session有效时间
       
        private $_domain = '';//session的作用域
       
        protected $isNew = 0;//判定操作动作 0 更新 1 增加
       
        protected $session = array();//对应的一条session记录
       
        public function __construct($options){
            $this->_setOptions($options);
            if(empty($this->_time))$this->_time = time();
            $this->session['activetime'] = $this->_time;
        }
       
        public function start(){
            $this->_getSid();
        }
       
        public function set($key,$value){
            if(in_array($key,array('uid','username','usertype','url','expiry'))){
                if($key == 'expiry'){
                    $this->_setCookie($this->_sessionPrex.'_sid',$this->session['sid'],$value);
                    $this->_setCookie($this->_sessionPrex.'_uid',$this->session['uid'],$value);
                }
                $this->session[$key] = $value;
            }else{
                $other = $this->session['value'];
                $other[$key] = $value;
                $this->session['value'] = $other;
            }
        }
       
        public function get($key){
            if(in_array($key,array('uid','username','usertype','url','expiry'))){
                return $this->session[$key];
            }else{
                if(isset($this->session['value'][$key])){
                    return $this->session['value'][$key];
                }
                return null;
            }
        }
       
        public function gc($file,$time = 1200){
            $lasttime = file_get_contents($file);
            if($lasttime + $time<$this->_time){
                file_put_contents($file,$this->_time);
                return $this->_model->delete('activetime+expiry<'.$this->_time);
            }
        }
       
        public function destroy(){
            $this->session['uid'] = 0;
            $this->session['username'] = '';
            $this->session['usertype'] = -1;
            $this->session['expiry'] = $this->_expiry;
            $this->session['value'] = array();
            $this->_setCookie($this->_sessionPrex.'_sid',$this->session['sid'],$this->_expiry);
            $this->_setCookie($this->_sessionPrex.'_uid',$this->session['uid'],$this->_expiry);
        }
       
        public function __destruct(){
            $this->_save();
        }
       
        private function _save(){
            $dbSession = $this->session;
            $dbSession['value'] = serialize($dbSession['value']);
            if(strlen($dbSession['value'])>255)$this->_error('session->value is too long!');
            if($this->isNew == 1){
                //增加
                $this->_model->insert($dbSession);
            }else{
                //更新
                $sid = $dbSession['sid'];
                $this->_model->update(array_slice($dbSession,1),'sid=\''.$sid.'\'');
            }
        }
       
        private function _getSession($sid){
            $dbSession = $this->_model->detail('sid = \''.$sid.'\'');
            if(!$dbSession)return false;
            $dbSession['value'] = unserialize($dbSession['value']);
            $this->session = array_merge($dbSession,$this->session);       
            return true;
        }
       
        private function _getSid(){
            $sid = strip_tags($_COOKIE[$this->_sessionPrex.'_sid']);
            if(strlen($sid)==32){
                if($this->_getSession($sid)){
                    return true;
                }
            }else{
                $sid = md5(time().mt_rand(1000,10000));
                $this->_setCookie($this->_sessionPrex.'_sid',$sid);
            }
            $this->_setCookie($this->_sessionPrex.'_uid',0);
            $this->session = array(
                    'uid' => 0,
                    'username' => '',
                    'usertype' => -1,
                    'activetime' => $this->_time,
                    'ip' => $this->_getip(),
                    'url' => strip_tags($_SERVER['REQUEST_URI']),
                    'expiry' =>$this->_expiry,
                    'value' => array()
            );
            $this->isNew = 1;
            $this->session['sid'] = $sid;
        }
       
        private function _setCookie($name,$value,$expiry=0){
            if(empty($expiry))$expiry = $this->_expiry;
            if(empty($this->_domain)){
                setcookie($name,$value,$this->_time + $expiry,'/');
            }else{
                setcookie($name,$value,$this->_time + $expiry,'/',$this->_domain);
            }
        }
       
        private function _getip(){
            return getip();
        }
       
        private function _setOptions($options){
            foreach ($options as $key=>$value){
                if(in_array($key,array('sessionPrex','time','model','expiry','domain'))){
                    $key = '_'.$key;
                    $this->$key = $value;
                }
            }
        }
       
        private function _error($msg){
            throw new Phpbean_Exception($msg);
        }
    }
    ?>


    (注意,该代码不能直接使用,本文主要是提供一种思路)


    评论 {{userinfo.comments}}

    {{money}}

    {{question.question}}

    A {{question.A}}
    B {{question.B}}
    C {{question.C}}
    D {{question.D}}
    提交

    驱动号 更多