我们正在为我们的应用程序部署memcached,我想尽可能地让它变得耐用。
我们计划使用较新的memcacheD扩展程序。
我还没想到的一件事是,如果其中一台服务器死机会发生什么。至少看起来memcached客户端只是“放弃”在该服务器上,并且不会在其中存储任何内容。
这种行为我很好。我们可以处理一堆缓存未命中。但是,如果其中一台服务器被认为“失败”后续集合并被重新分配给剩余的服务器,那将是很好的。
因为这似乎不会自动发生;我想解决这个问题的唯一方法是让外部系统对memcached系统进行健康检查,并适当更新服务器列表。
但是,如果有一个包含10个服务器的列表,并且让我们说,第5个死了......即使使用Ketama-hashing,这似乎会触发重新分配密钥(这只是基于常识)。 / p>
理想情况下,我只是想让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%的密钥被发送到新服务器的可能性很高。
答案 0 :(得分:3)
我通常在APC中存储可用服务器列表,因此我可以动态修改它。你是正确的,因为系统会在列出它时尝试继续使用down服务器,幸运的是,使用新的散列方法从旋转中拉出它并不是什么大问题。
我会避免使用全新的PHP扩展,或尝试将新软件添加到您的部署堆栈中。您可能已经在使用某些东西进行监控(nagios?)。让它在你的每个web服务器上调用一个简单的PHP脚本来调整内存列表似乎是最好的选择。
值得注意的是,在Ketama hashing system下,从轮换中移除服务器将导致其密钥在环上的其他位置(连续)重新散列,其他服务器将无法看到别处分配的钥匙。将其可视化为圆形,为每个服务器分配圆上的多个点(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);
如果散列系统关心订单或省略服务器,我们希望在大多数辅助示例上获得bool(false)
,因为早期服务器已被删除等等。但是基于我快速,完全非科学的测试,我只在10中的任何一个特定插槽中得到一个bool false。我显然只是在我的测试盒上启动了10个服务器。给每个人只有4mb的公羊
答案 1 :(得分:2)
您可能想尝试PHP的Memcached::OPT_AUTO_EJECT_HOSTS
选项常量。它没有直接记录,但有一条评论here命名它。
(我没试过,所以我不能告诉你它是否有效)
答案 2 :(得分:0)
根据评论的答案,我会建议:
您需要构建一个缓存类。
此课程将包含以下信息:
缓存服务器列表
当前存储的密钥列表及其所在的服务器
接下来,您需要使用标准功能来添加,更新和删除密钥。
每次执行其中一个功能时,您都需要检查密钥是否已经在缓存中以及它所在的服务器上。
如果它不在服务器中,请在检索实际数据库值后选择保存最少请求的服务器。
如果这些函数中的任何一个从缓存服务器返回错误,我会将该服务器标记为脱机,重置计数,并从列表中删除此服务器上的所有密钥。
此时,您可以轻松地将它们自动移动到新服务器或只删除它们,以便再次查询它们。
答案 3 :(得分:0)
我的2美分: 为Memcached开发一个强大的HA模块并不容易。例如,考虑以下情况:
我建议您查看现在处于测试阶段的Redis Sentinel,并在过去几个月内开发并测试,专门用于解决Redis中的这些问题。在开始开发一行代码之前,你必须在那里找到许多必须注意的角落案例。
至于此处讨论的其他问题:
最后但同样重要的是,我建议你也检查一下Memcached作为服务解决方案。例如,我们Garantia Data已经解决了Memcached的HA问题。
披露:我是Garantia Data的联合创始人兼首席技术官。