优化使用mysql存储session

日期:2008-07-05  作者:喜腾小二  来源:PHPChina


之前写过两篇文章《自定义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
);
    }
}
?>

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

<<<返回技术中心

技术文章

站内新闻

我要啦免费统计