• Memcached常规应用与分布式部署方案


    1、Memcached常规应用

    $mc = new Memcache();
    $mc->conncet('127.0.0.1', 11211);
    $sql = sprintf("SELECT * FROM users WHERE uid = %d", $_GET['uid']);
    $key = md5($sql);
    //检测结果是否已经被缓存
    if( ! $data = $mc->get($key)){
        //没有缓存则直接从数据库读取
        mysql_conncet('localhost', 'test', 'test');
        mysql_select_db('test');
        while($row = mysql_fetch_object(mysql_query($sql))){
            $data[] = $row;
        }
        //并将查询结果缓存
        $mc->add($key, $data);
    }
    var_dump($data);

    说明:首先通过md5()将SQL语句转化成一个唯一的KEY,并用此KEY查询Memcached检测是否已经缓存,是的话在直接返回结果,否则先查询数据库再缓存,并返回结果。这样,下次使用此KEY就可以直接返回结果了。

    2、Memcached分布式部署方案,对于多台Memcached服务器,怎么确定一个数据应该保存到哪台服务器呢?有两种方案,一是普通Hash分布,二是一致性Hash分布。下面详细说明。

    方案一:简单的取模运算

    <?php
    
    //Hash函数
    function mHash($key){
        $md5 = substr(md5($key), 0, 8);
        $seed = 31;
        $hash = 0;
        for($i = 0; $i < 8; $i++){
            $hash = $hash * $seed + ord($md5{$i});
            $i++;
        }
        return $hash & 0x7FFFFFFF;
    }
    //假设有2台Memcached服务器
    $servers = array(
        array('host' => '192.168.1.1', 'port' => 11211),
        array('host' => '192.168.1.1', 'port' => 11211)
    );
    $key = 'MyBlog';
    $value = 'http://www.cnblogs.com/gide';
    $sc = $servers[mHash($key) % 2];
    $memcached = new Memcached($sc);
    $memcached->set($key, $value);

    说明:首先通过MD5函数把KEY处理成32位字符串,然后截取前8位,再经过Hash算法处理成一个整数并返回。利用这个整数与Memcached服务器数量取模,决定当前KEY存储于哪台Memcached服务器,就完成了Memcached的分布式部署。可想而知,当要读取KEY的值时,依然是先要通过Hash算法判断存储于哪台服务器

    方案二:一致性hash部署

    <?php
    
    class FlexiHash{
        //服务器列表
        private $serverList = array();
        //记录是否已经排序
        private $isSorted = FALSE;
        //添加一台服务器
        public function addServer($server){
            $hash = $this->mHash($server);
            if(!isset($this->serverList[$hash])){
                $this->serverList[$hash] = $server;
            }
            //需要重新排序
            $this->isSorted = FALSE;
            return TRUE;
        }
        //移除一台服务器
        public function removeServer($server){
            $hash = $this->mHash($server);
            if(isset($this->serverList[$hash])){
                unset($this->serverList[$hash]);
            }
            //需要重新排序
            $this->isSorted = FALSE;
            return TRUE;
        }
        //在当前服务器列表查找合适的服务器
        public function lookup($key){
            $hash = $this->mHash($key);
            //先进行倒序排序操作
            if(!$this->isSorted){
                krsort($this->serverList, SORT_NUMERIC);
                $this->isSorted = TRUE;
            }
            //圆环上顺时针方向查找当前KEY紧邻的一台服务器
            foreach($this->serverList as $pos => $server){
                if($hash >= $pos)    return $server;
            }
            //没有找到则返回顺时针方向最后一台服务器
            return $this->serverList[count($this->serverList) - 1];
        }
        //Hash函数
        private function mHash($key){
            $md5 = substr(md5($key), 0, 8);
            $seed = 31;
            $hash = 0;
            for($i = 0; $i < 8; $i++){
                $hash = $hash * $seed + ord($md5{$i});
                $i++;
            }
            return $hash & 0x7FFFFFFF;
        }
    }
    ?>

    说明:一致性Hash分布算法分4个步骤:
    步骤1:将一个32位整数[0 ~ (2^32-1)]想象成一个环,0 作为开头,(2^32-1) 作为结尾,当然这只是想象。
    步骤2:通过Hash函数把KEY处理成整数。这样就可以在环上找到一个位置与之对应。
    步骤3:把Memcached服务器群映射到环上,使用Hash函数处理服务器对应的IP地址即可。
    步骤4:把数据映射到Memcached服务器上。查找一个KEY对应的Memcached服务器位置的方法如下:从当前KEY的位置,沿着圆环顺时针方向出发,查找位置离得最近的一台Memcached服务器,并将KEY对应的数据保存在此服务器上。

    具体应用:

    <?php
    $hserver = new FlexiHash();
    //初始5台服务器
    $hserver->addServer("192.168.1.1");
    $hserver->addServer("192.168.1.2");
    $hserver->addServer("192.168.1.3");
    $hserver->addServer("192.168.1.4");
    $hserver->addServer("192.168.1.5");
    echo "save key1 in server: ", $hserver->lookup('key1'), "<br/>";
    echo "save key2 in server: ", $hserver->lookup('key2'), "<br/>";
    echo '===============================================<br/>';
    //移除1台服务器
    $hserver->removeServer("192.168.1.4");
    echo "save key1 in server: ", $hserver->lookup('key1'), "<br/>";
    echo "save key2 in server: ", $hserver->lookup('key2'), "<br/>";
    echo '===============================================<br/>';
    //添加1台服务器
    $hserver->addServer('192.168.1.6');
    echo "save key1 in server: ", $hserver->lookup('key1'), "<br/>";
    echo "save key2 in server: ", $hserver->lookup('key2');
    ?>
    //测试结果如下:
    save key1 in server: 192.168.1.4
    save key2 in server: 192.168.1.2
    ==================================
    save key1 in server: 192.168.1.3
    save key2 in server: 192.168.1.2
    ==================================
    save key1 in server: 192.168.1.3
    save key2 in server: 192.168.1.2

    不过Memcached自带了addServer

    Memcached::addServer — 向服务器池中增加一个服务器
    public bool Memcached::addServer ( string $host , int $port [, int $weight = 0 ] )
    host
    memcached服务端主机名。如果主机名无效,相关的数据操作的返回代码将被设置为Memcached::RES_HOST_LOOKUP_FAILURE。

    port
    memcached服务端端口号,通常是11211。

    weight
    此服务器相对于服务器池中所有服务器的权重。此参数用来控制服务器在操作时被选种的概率。这个仅用于一致性 分布选项,并且这个值通常是由服务端分配的内存来设置的。

    成功时返回 TRUE, 或者在失败时返回 FALSE。

    <?php
    $m = new Memcached();
    
    $m->addServer('mem1.domain.com', 11211, 33);
    $m->addServer('mem2.domain.com', 11211, 67);

    完毕!

  • 相关阅读:
    CSS基本相关内容中秋特别奉献
    JavaScript基础
    jQuery(内涵: jquery选择器)
    ADO.NET(内涵效率问题)
    三层实例(内涵Sql CRUD)
    数据库的应用详解二
    三层相关案例(及常见的错误)
    Java中生成唯一ID的方法
    Postgres 的 Array 类型
    java的错误和异常的区别
  • 原文地址:https://www.cnblogs.com/gide/p/5616429.html
Copyright © 2020-2023  润新知