Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memcached用于PHP和故障切换_Php_Memcached - Fatal编程技术网

Memcached用于PHP和故障切换

Memcached用于PHP和故障切换,php,memcached,Php,Memcached,我们正在为我们的应用程序部署memcached,我想让它尽可能地抵抗 我们计划使用更新的扩展 我还没有完全弄清楚的一件事是,如果其中一台服务器死掉会发生什么。至少看起来memcached客户端只是“放弃”了该服务器,并且没有在其中存储任何内容 我对这种行为没意见。我们可以处理大量缓存未命中。然而,在其中一台服务器被认为“失败”之后,后续的服务器集将被重新分配到剩余的服务器上,这将是一件好事 因为这似乎不是自动发生的;我想解决这个问题的唯一方法是让外部系统对memcached系统进行运行状况检查,

我们正在为我们的应用程序部署memcached,我想让它尽可能地抵抗

我们计划使用更新的扩展

我还没有完全弄清楚的一件事是,如果其中一台服务器死掉会发生什么。至少看起来memcached客户端只是“放弃”了该服务器,并且没有在其中存储任何内容

我对这种行为没意见。我们可以处理大量缓存未命中。然而,在其中一台服务器被认为“失败”之后,后续的服务器集将被重新分配到剩余的服务器上,这将是一件好事

因为这似乎不是自动发生的;我想解决这个问题的唯一方法是让外部系统对memcached系统进行运行状况检查,并适当地更新服务器列表

但是如果有一个10台服务器的列表,比如说,第5台服务器就死了。。即使使用Ketama散列,这似乎也会触发密钥的大规模重新分配(这只是基于常识)

因此,理想情况下,我只希望PHP扩展能够判断服务器是否停机,并在指定的时间(10分钟)内将其标记为停机,然后在这10分钟内返回到其他服务器(很好地分布)进行设置和获取

其他人如何解决这个问题

编辑:澄清我的libketama观点

假设我们有10台服务器:

1,2,3,4,5,6,7,8,9,10
其中一人死亡。然后,Libketama将提供一个非常高的可能性,即丢失服务器的命中将平均分布到其余服务器:

1,2,3,4,inactive,6,7,8,9,10
但是:如果我们手动提供和管理此列表,则情况并非如此:

1,2,3,4,6,7,8,9,10 // There are now 9 servers!

6将获得5之前的密钥,7将获得6。8得7分,9得8分,10得9分。第10台服务器以前获得的所有命中率不会均匀分布在其余服务器中。导致几乎50%的密钥被发送到新服务器的可能性很高。

我通常将可用服务器列表存储在APC中,以便随时修改。您是正确的,系统将尝试在列出服务器时继续使用停机服务器,幸运的是,使用新的哈希方法,将其从循环中拉出来并不是什么大问题

我会避免使用全新的PHP扩展,或者尝试向部署堆栈中添加新软件。您可能已经在使用某些东西进行监视(nagios?)。让它在每个Web服务器上调用一个简单的PHP脚本来调整内存列表似乎是最好的选择

值得注意的是,在下,从循环中删除服务器将导致其密钥在环上的其他位置重新散列(连续体),其他服务器将看不到在其他位置分配的密钥。将其视为一个圆,每个服务器在圆上分配多个点(100-200)。键被散列到圆圈中并顺时针继续,直到找到服务器。从环中删除服务器只会导致这些值继续查找新服务器。幸运的是,值的分布将平等地影响其余的服务器

演示哈希系统:

<?php


$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);


$m->addServer('localhost', 11211);
$m->addServer('localhost', 11212);
$m->addServer('localhost', 11213);
$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11210);

$key = uniqid(); //You may change this to md5(uniqid()); if you'd like to see a greater variation in keys. I don't think it necessary.
$m->set($key, $key, 5);


var_dump($m->get($key));

unset($m);


$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
//one server removed. If assignment to the continuum is dependent based on add order, we would expect the get call here to fail 90% of the time, as there will only be a success if the value was stored on the first server. If the assignment is based on some hash of the server details we'd expect success 90% of the time. 
$m->addServer('localhost', 11211);
//$m->addServer('localhost', 11212);
$m->addServer('localhost', 11213);
$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11210);

var_dump($m->get($key));

unset($m);

$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
//2 servers removed
$m->addServer('localhost', 11211);
$m->addServer('localhost', 11212);
//$m->addServer('localhost', 11213);
//$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11210);

var_dump($m->get($key));

unset($m);

$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
//Out of order
$m->addServer('localhost', 11210);
$m->addServer('localhost', 11211);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11212);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11213);

var_dump($m->get($key));

unset($m);

您可能想尝试PHP的
Memcached::OPT_AUTO_EJECT_HOSTS
选项常量。它没有直接记录,但有一个注释命名它


(我没有试过,所以我不能告诉你它是否有效)

根据对评论的回答,我建议如下:

您需要构建一个缓存类

此类将包含以下信息:

  • 缓存服务器列表

    • 联机或脱机的状态
    • 对此服务器的请求计数
  • 当前存储的密钥列表及其所在的服务器

接下来,您需要使用标准函数来添加、更新和删除密钥

每次执行其中一个函数时,都需要检查密钥是否已在缓存中,以及它位于哪个服务器上

如果它不在服务器中,则在检索到实际的DB值后,选择请求最少的服务器保存它

如果其中任何函数从缓存服务器返回错误,我会将该服务器标记为脱机,重置计数,并从该服务器上的列表中删除所有密钥

此时,您可以轻松地将它们自动移动到新服务器或删除它们,以便再次查询它们。

我的2美分: 为Memcached开发一个健壮的HA模块并不容易。例如,考虑以下情况:

  • 您将如何确定哪个服务器处于活动状态,哪个服务器已死亡?您应该以某种方式在运行web/app服务器的所有HA模块之间进行同步
  • 如何在web/app服务器之间发布此信息
  • 你会有一个编曲吗
我建议您看看现在是Beta版,并且在过去几个月专门为解决Redis中的这些问题而开发和测试。在开始开发一行代码之前,您将发现许多您必须注意的角落案例

至于这里讨论的其他问题:

  • 当您丢失节点时,您将丢失1/N个密钥,其中N是您最初拥有的节点数,即包括故障节点。凯塔玛就是这样工作的
  • 使用新的Memcached类在Memcached客户端上存储密钥肯定不是一个好办法(IMO):(1_u您将在哪里保存所有这些密钥?(2)如何在web/app节点之间同步?(3)访问这些数据结构需要多长时间才能理解每个密钥驻留在哪个节点上?--这就是为什么Memcached完全基于散列函数,以使其快速简单
最后但并非最不重要的一点是,我建议您也检查Memcached as-a-service解决方案。例如,我们至少已经解决了Memcached的HA问题

披露:我是C