/** * 执行一次session gc操作 * * 算法: * 1、在线列表:将ZSet数据集中最后活跃(<time()-$life)所有垃圾销毁掉 * 2、保持登录:session到期后用户还没出来活动(>deadline) * * 1和2可能相交,保持登录用户超时后清除在线列表;销毁前调用session delete()函数 * * 原ylstu库操作条件: * (deadline>0 and deadline<timeNow) or (deadline=0 and ltime=timeNow-keepOline) * * @param string $sessionId session缓存键 */ public function gc($maxlifetime) { $gcTime = time(); /** * 获取超过在线时间允许的列表并清理之 limit => array($offset, $count) * * 取出来数据格式 array($sessionID=>score): * Array([yunk5y093qzlcoij5nhbz49ospyay4rp8yilbxli] => 1379425023) */ $endStamp = $gcTime - $this->sessionBase->getLife(); $kickOnline = $this->redis->zRangeByScore(self::MANAGER_DATALIST, 0, $endStamp, array('withscores' => TRUE, 'limit' => array(0, self::MAX_GC_PER_ACTION))); //print_r($kickOnline);die(); if (!empty($kickOnline)) { //这里不能使用redis multi,因为读session可能使用redis foreach ($kickOnline as $sessionId => $lastVisit) { //删除在线列表中数据 $this->redis->zDelete(self::MANAGER_DATALIST, $sessionId); //删除实体session数据 保持登录的除外 if (!intval($this->getDeadline($sessionId))) { $this->sessionBase->delete($sessionId); } } } /** * 处理保持登录过期列表 * * 超过一个月无活动的删除session */ $kickAutoLogin = $this->redis->zRangeByScore(self::MANAGER_DEADLINE, 0, $gcTime, array('withscores' => TRUE, 'limit' => array(0, self::MAX_GC_PER_ACTION))); //print_r($kickAutoLogin);die(); if (!empty($kickAutoLogin)) { $redisMulti = $this->redis->multi(); foreach ($kickOnline as $sessionId => $lastVisit) { //铁定不在线列表中 从保持登录列表删除 $redisMulti->zDelete(self::MANAGER_DEADLINE, $sessionId); //删除实体session数据,直接删除,从在线列表剔除时更新资料过 $this->sessionBase->delete($sessionId); } $redisMulti->exec(); } }