memcached 分布式集群,该决定必须书面开发商自己。和redis 由分布式server决定。上 memcached 有两个选项用于分布式。第一个是:模运算

另一种是:一致性hash 分布式算法。以下我就这两种算法简介一下。


        一、取模算法:

        取模算法是不靠谱的算法,当有n 台server,突然一台server突然down 掉了。memcached 的命中率仅仅有1/n-1。结果是怎么来的,自己想想吧。比方有8台memchached 

server,0,1,2,3。4,5。6,7,8  这8个数字存入到memcached server,突然有一台memcached serverdown 掉了。

我们用取模法,从memcached server取值。

发现仅仅有0。1,2。3,4,5,6。56 这些数被7,8取模的值是一样的。也就是说这么写能被命中。

也就得出了结论 n/n(n-1) 个数可以被命中。相同也得出结论server集群越大,

命中率也就越低。

这中算法直接pass 掉。

并且命中率会无限趋进于0。


   二、一致性hash 分布式算法:

        介绍这样的算法。首先我引进一个概念是虚拟节点。虚拟节点也就是说在没台memcached server虚拟非常多节点。并算出每一个节点的hash 值。

存key 时,同一时候计算出key 的hash 

值,当key的hash 值,接近或等于某个节点的hash 值,就放到某个 memcached server。当某个memcached serverdown 掉后。其它server共同承担这台server的压力。

以下是我的一段代码:


<?php
   /*
    memcached 一致性hash分布式算法
   */
   interface hash{
	   public function _hash($str);   // hash 算法
   }

   interface distribution{
		public function _lookup($key);  
   }

   class contents implements hash,distribution{
		public $address_array=array();
		public function _hash($str){
			return sprintf("%u",crc32($str));
		}
		public function _lookup($key){   //通过key 找到server
			$look_key=$this->_hash($key);
			$current_key=current($this->address_array);
			foreach($this->address_array as $key=>$value){
				if($look_key<=$key){
					$current_key=$key;
					break;
				}
			}
			return $value;
		}
		public function _address($node){  // 虚拟节点
			for($i=0;$i<64;$i++){
				$key=$this->_hash($node.'_'.$i);
				$this->address_array[$key]=$node;	
			}
			$this->_sortkey();
		}
		public function _sortkey(){   // 对hash 后的值排序
		    ksort($this->address_array,SORT_REGULAR);
		}

		public function delnode($node){   // down 掉了某台server
		  $new_address=array_diff_key($this->address_array,array_flip(array_keys($this->address_array,$node)));
		  $this->address_array=$new_address;
		  return $new_address;
		}
   }

以下另一段模拟降低一台memcached server的代码:

 

<?php
     require_once 'config.php';      //载入配置文件
     require_once 'distribute.php';  //载入一致hash 
     $distribute=new contents();

	 //循环加入server
     foreach($mem_array as $key=>$value){
      $distribute->_address($key);
    }

	 //降低一台server
	 $distribute->delnode('B');


     for($i=0;$i<10000;$i++){
	   $key='key'.sprintf("%04d",$i);
       $memca_key=$distribute->_lookup($key);
	   $memca_party=$mem_array[$memca_key];
       $memcache = memcache_connect($memca_party['ip'],$memca_party['port']);
	   if(!$memcache->get($key)){
		   $memcache->add($key,'value'.$i,0,0);
	   }
	   $memcache->close();

    }

     以下是memcached server的配置文件

   

 /*
   memcached 的配置文件
 */
 $mem_array=array(
     'A'=>array('ip'=>'127.0.0.1','port'=>'11211'),
	 'B'=>array('ip'=>'127.0.0.1','port'=>'11212'),
	 'C'=>array('ip'=>'127.0.0.1','port'=>'11213'),
	 'D'=>array('ip'=>'127.0.0.1','port'=>'11214')
  );

以下是计算memcached 的命中率:

<?php 
   
   require_once 'config.php';  //载入配置文件
   $int_get=0;
   $int_hits=0;
   $rand=1;
   foreach($mem_array as $value){
	  $memcache = memcache_connect($value['ip'],$value['port']);
	  $statistics =$memcache->getStats();
	  $int_get += $statistics['cmd_get'];
	  $int_hits += $statistics['get_hits'];
   }
   if($int_get==0){
	  echo  $rand;
	  return true;
   }
   $rand=$int_hits/$int_get;
   echo $rand;

以下是highcharts 插件统计的 memcached 命中率


memcached  分布式聚类算法_配置文件

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Highcharts Example</title>

		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
		<style type="text/css">
       ${demo.css}
		</style>
		<script type="text/javascript">
$(function () {
    $(document).ready(function () {
        Highcharts.setOptions({
            global: {
                useUTC: false
            }
        });

        $('#container').highcharts({
            chart: {
                type: 'spline',
                animation: Highcharts.svg, // don't animate in old IE
                marginRight: 10,
                events: {
                    load: function () {

                        // set up the updating of the chart each second
                        var series = this.series[0];
                        setInterval(function () {
                            var x = (new Date()).getTime(), // current time
                                y = parseFloat($.ajax({url:'hit.php',async:false}).responseText);
                            series.addPoint([x, y], true, true);
                        }, 1000);
                    }
                }
            },
            title: {
                text: 'memcached 命中率'
            },
            xAxis: {
                type: 'datetime',
                tickPixelInterval: 150
            },
            yAxis: {
                title: {
                    text: 'Value'
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                formatter: function () {
                    return '<b>' + this.series.name + '</b><br/>' +
                        Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
                        Highcharts.numberFormat(this.y, 2);
                }
            },
            legend: {
                enabled: false
            },
            exporting: {
                enabled: false
            },
            series: [{
                name: 'Random data',
                data: (function () {
                    // generate an array of random data
                    var data = [],
                        time = (new Date()).getTime(),
                        i;

                    for (i = -19; i <= 0; i += 1) {
                        data.push({
                            x: time + i * 1000,
                            y: Math.random()
                        });
                    }
                    return data;
                }())
            }]
        });
    });
});
		</script>
	</head>
	<body>
<script src="js/highcharts.js"></script>
<script src="js/modules/exporting.js"></script>

<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>

	</body>
</html>