配置Memcached服务
参考:https://www.runoob.com/memcached/memcached-connection.html
一致性哈希原理介绍
把个服务器节点映射放在钟表的各个时刻上,把key也映射到钟表的某个时刻上,这样实现节点的均匀分布。
定义接口
<?php
namespace CacheInterface;
interface Distribution
{
//获取服务名称所在的节点。
public function lookup($key);
}
interface Hash
{
//计算服务名称的节点名称
public function _hash($str);
}
实现Hash接口的逻辑
namespace CacheAlgo;
use CacheInterface\Distribution;
use CacheInterface\Hash;
class Consistent implements Hash,Distribution
{
//一致性哈希
protected $_nodes = [];
protected $_position = [];
protected $_mul = 64;
public function _hash($str)
{
return sprintf('%u', crc32($str));
}
public function lookup($key)
{
$point = $this->_hash($key);
$node = current($this->_position);
foreach ($this->_position as $k => $v) {
if ($point <= $k) {
$node = $v;
break;
}
}
return $node;
}
//添加一个节点,虚拟化64个虚拟节点
public function addNode($node)
{
for ($i = 0; $i < $this->_mul; $i++) {
$this->_position[$this->_hash($node . '-' . $i)] = $node;
}
$this->_sortPos();
}
//删除节点
public function delNode($node)
{
foreach ($this->_position as $key => $value) {
if ($value == $node) {
unset($this->_position[$key]);
}
}
}
//对节点进行排序
protected function _sortPos()
{
ksort($this->_position, SORT_REGULAR);
}
//调试节点
public function printPost()
{
dump($this->_position);
}
}
接入测试用例
准备Memcache服务器
<?php
#config.php
return [
'memcache_server' => [
'A' => [
'host' => '127.0.0.1',
'port' => 11211
],
'B' => [
'host' => '127.0.0.1',
'port' => 11212
],
'C' => [
'host' => '127.0.0.1',
'port' => 11213
],
'D' => [
'host' => '127.0.0.1',
'port' => 11214
],
'E' => [
'host' => '127.0.0.1',
'port' => 11215
],
],
'mamcache_dis' => \CacheAlgo\Consistent::class,
];
#启动服务:memcached.exe -m 64 -p 11211 -vvv
准备图形程序 index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Memcache的一致性哈希演示</title>
<style type="text/css">
#container {
min-width: 310px;
height: 400px;
margin: 0 auto;
}
</style>
</head>
<body>
<!----highcharts第三方js图库--->
<script src="/Public/js/Hicharts/code/highcharts.js"></script>
<script src="/Public/js/Hicharts/code/modules/exporting.js"></script>
<script src="/Public/js/Hicharts/code/modules/export-data.js"></script>
<script src="/Public/js/jquery-1.8.3.min.js"></script>
<div id="container"></div>
<script type="text/javascript">
Highcharts.chart('container', {
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 sto=parseFloat($.ajax({url:'<{:U("loadAjax")}>',async:false}).responseText);
var x = (new Date()).getTime(), // current time
y = parseFloat($.ajax({url:'数据加载URL',async:false}).responseText);
series.addPoint([x, y], true, true);
}, 3000);
}
}
},
time: {
useUTC: false
},
title: {
text: 'Memcache his'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
tooltip: {
headerFormat: '<b>{series.name}</b><br/>',
pointFormat: '{point.x:%Y-%m-%d %H:%M:%S}<br/>{point.y:.2f}'
},
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>
</body>
</html>
测试用例程序
<?php
//这里使用的是TP3程序,其他框架自己改写下,就行了
class IndexController
{
//初始化方法:初始化数据
public function initialData()
{
set_time_limit(0);
$memcache = new \Memcache();
$diser_server = C('mamcache_dis');
$host = C('memcache_server');
$diser = new $diser_server();
foreach ($host as $key => $vals) {
$diser->addNode($key);
}
for ($i = 0; $i < 100; $i++) {
$i = sprintf('%04d', $i);
$key = 'key' . $i;
$value = 'value' . $i;
$host_key = $diser->lookup($key);
dump($host_key);
$serv = $host[$host_key];
$memcache->connect($serv['host'], $serv['port'], 2);
$memcache->add($key, $value, 0, 0);
//usleep(3000);
}
echo '初始化完毕';
}
//展示方法
public function index()
{
$this->display();
}
//数据加载方法:数据实时加载...,即上面的index.html中数据加载URL
public function loadAjax()
{
$gets = 0;
$hits = 0;
$mem = new \Memcache();
$configMemserv = C('memcache_server');
foreach ($configMemserv as $k => $s) {
$res = $mem->connect($s['host'], $s['port'], 2);
// //dump($res);
// //echo $k,'号服务器的统计情况是';
// //dump($mem->getStats());
// //echo '<br />---------';
$res = $mem->getStats();
//dump($res);
// //dump($res);
$gets += $res['cmd_get'];
$hits += $res['get_hits'];
// //$mem->flush();
// //dump($res);
}
$rato = 1;
if ($gets > 0) {
$rato = $hits / $gets;
}
echo $rato;
}
//宕机方法:减少命中率,即模拟一台Memcache服务器宕机。
public function descHitRato()
{
set_time_limit(0);
$dis_server = C('mamcache_dis');
$diser = new $dis_server();
$server_maser = C('memcache_server');
foreach ($server_maser as $ks => $value) {
$diser->addNode($ks);
}
//减少一台服务器
$diser->delNode('D');
$mem = new \Memcache();
for ($i = 1; $i <= 100; $i++) {
$i = sprintf('%04d', $i);
$key = 'key' . $i;
$serv_key = $diser->lookup($key);
//dump($serv_key);
//echo $serv_key;continue;
$serv = $server_maser[$serv_key];
$res = $mem->connect($serv['host'], $serv['port'], 2);
if (!$mem->get($key)) {
$mem->add($key, 'value' . $i, 0, 0);
}
// usleep(3000);
}
}
}
详情介绍
整理中…