分布式存储Memcache替代Session方案

PHP自带的Session实际是在服务器中为每个客户建立独立的文件存放各自的信息。

在不做处理的情况下,很容易被客户端伪造。并且由于采用文件形式,所以存在着IO

读写的瓶颈。一般当用户在线达到1000左右时,就会出现访问速度明显下降的问题。

Memcache是应用层级的缓存,它将数据存储内存中。内存的访问速度是可想而知的。

PHP在使用Memcache之前,需要做两件事。

1.安装PHP的memcache扩展。

2.下载Memcache文件。

以上两步很简单,去Google一下就可以了。

下面是memcache.class.php文件中MemcacheSession类

memcache.class.php

<?php

define('PREFIX', 'god');
define('SESS_LEFETIME', 3600);
define('ZIP_FLAG', 0);

class MemcacheSession {

    static $Memcache;
    /* 构造函数
     * @param string @login_user
     * @param int @login_type
     * @param string $login_sess
     */

    public function __construct($config) {
        if (!class_exists('Memcache') || !function_exists('memcache_connect')) {
            exit("Can't load Memcache Extendstion");
        }
        $this->Memcache = new Memcache;
        if (!@$this->Memcache->connect($config['host'], $config['port'])) {
            exit('连接失败');
        }
        $this->setCookie();
        return TRUE;
    }

    /* 增加键值
     * return bool
     */

    public function add($key, $data='empty') {
        if (!$this->Memcache->add($key, $data, ZIP_FLAG, SESS_LEFETIME)) {
            exit("此键名已经被使用");
        }
    }

    /* uniqueID
     * return string
     */

    public function uniqueID() {
        return PREFIX . md5(uniqid(rand(), true)) . $_SERVER['REMOTE_ADDR'];
        ;
    }

    /* 读取数据
     * @param string
     * return string/array
     */

    public function get($key='') {
        if ($key == '')
            exit('键名不能为空');
        $wData = $this->Memcache->get($key);
        if (!$wData)
            return FALSE;
        return $wData;
    }

    /* 重写数据
     * @param string $key
     * @param string $data
     * @return bool
     */

    public function set($key, $data='') {
        $ret = $this->Memcache->set($key, $data, ZIP_FLAG, SESS_LEFETIME);
        if (TRUE != $ret) {
            exit("存储数据失败");
        }
    }

    /* 注销数据
     * @param string $key
     * return bool
     */

    public function memDestory($key) {
        $this->Memcache->set($key);
    }

    /* Cookie验证,建立客户端与服务器端同步键名
     * return bool
     */

    public function setCookie() {
        if (empty($_COOKIE['sessionID'])) {
            $sessionID = md5(uniqid(rand(), true)) . $_SERVER['REMOTE_ADDR'];
            setcookie('sessionID', $sessionID, time() + SESS_LEFETIME);
            $this->set(PREFIX . $sessionID, 'empty');
        } else {
            setcookie('sessionID', $_COOKIE['sessionID'], time() + SESS_LEFETIME);
            if (!$this->Memcache->get(PREFIX . $_COOKIE['sessionID']))
                exit('处理异常'); //出现此错误是因为客户端伪造sessionID
        }
    }

}
?>

下面是简单的测试使用

ceshi.php

<?php

require_once "memcache.class.php";
$config['host'] = '127.0.0.1';
$config['port'] = 11211;
try {
    $session = new MemcacheSession($config);
} catch (Exception $e) {
    echo $e->getMessage();
}
$sessionID = PREFIX . $_COOKIE['sessionID'];
$data['userA'] = 1024;
$data['pointA'] = 100;
$data['introA'] = '你干嘛呢!干嘛呢!';
$session->set($sessionID, $data);
print_r($session->get($sessionID));
?>

这里仅仅是针对一台服务器的实现。

如果需要分布式存储只需在实例化类传递host时,进行一些扩展就可以实现了。

扩展方案:

1.地址轮询:假设有3台服务器A、B、C,那么当第一个用户访问时连接A,第二个访问时连接B,第三个访问时连接C,第四个访问时返回第一个重新开始计数,依次向下。

2.地址分配:设定三个段A:69.168.0.0-69.168.255.255;B:192.168.0.0-192.168.255.255;C:68.192.0.0-68.192.255.255

当用户访问时,根据IP给其分配对应的服务器。

这两种方法,各自有各自的优缺点。

地址轮询,可以很好的实现负载均衡。

地址分配,可以根据用户位置分配距离最近的服务器,从而提高访问速度。

原文地址:https://www.cnblogs.com/zhishan/p/3195632.html