Memcached 一致性哈希在 4 台服务器中的 3 台宕机时不起作用

2024-01-29

Story

我有 3 个 memcached 服务器正在运行,我关闭其中一个或另一个来调查 PHP-memcached 在无法访问的服务器上的行为。

我在 PHP 中定义了 4 个服务器,其中 1 个用于模拟大部分离线的服务器(备用服务器)。当我关闭 1 台服务器(=> 2 台仍然在线)时,第三台服务器->get()给我一个结果。

当我关闭另一台服务器(=> 1 仍然在线)时,它不会找到推送到最后一台服务器的对象。

样本输出

首次运行,4 台服务器中的 3 台启动:

Entity not found in cache on 1st try: NOT FOUND
Entity not found in cache on 2nd try: NOT FOUND
Entity not found in cache on 3rd try: NOT FOUND
Entity not found in cache on 4th try: NOT FOUND

第二次运行,4 台服务器中的 3 台启动:

Entity found in Cache: SUCCESS

第三次运行,4 台服务器中的 2 台启动:

Entity not found in cache on 1st try: CONNECTION FAILURE
Entity not found in cache on 2nd try: SERVER IS MARKED DEAD
Entity not found in cache on 3rd try: NOT FOUND
Entity not found in cache on 4th try: NOT FOUND

第四次运行,4 台服务器中的 1 台启动:

Entity not found in cache on 1st try: CONNECTION FAILURE
Entity not found in cache on 2nd try: SERVER IS MARKED DEAD
Entity not found in cache on 3rd try: CONNECTION FAILURE
Entity not found in cache on 4th try: SERVER IS MARKED DEAD

尽管有一台服务器保持在线状态,并且每次在缓存中找不到任何对象时,我都会将对象推送到 memcached,但它无法再找到密钥了。

我认为它也应该在只剩下一台服务器的情况下工作。

你能向我解释一下这种行为吗?

看起来不可能实现一些东西即使我关闭 20 台服务器中的 19 台也是安全的.

附带问题:libketama 不再真正维护了,使用它还好吗?该库背后的逻辑相当不错,也用于 varnish 缓存服务器。

Appendix

我的脚本:

<?php
require_once 'CachableEntity.php';
require_once 'TestEntity.php';

echo PHP_EOL;

$cache = new Memcached();
$cache->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
$cache->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
$cache->setOption(Memcached::OPT_SERVER_FAILURE_LIMIT, 1);
$cache->setOption(Memcached::OPT_REMOVE_FAILED_SERVERS, true);
$cache->setOption(Memcached::OPT_AUTO_EJECT_HOSTS, true);

$cache->setOption(Memcached::OPT_TCP_NODELAY, true);
//$cache->setOption(Memcached::OPT_RETRY_TIMEOUT, 10);

$cache->addServers([
    ['localhost', '11212'],
    ['localhost', '11213'],
    ['localhost', '11214'],
    ['localhost', '11215'], // always offline
]);


$entityId = '/test/test/article_123456789.test';

$entity = new TestEntity($entityId);

$found = false;

$cacheKey = $entity->getCacheKey();

$cacheResult = $cache->get($cacheKey);
if (empty($cacheResult)) {
    echo 'Entity not found in cache on 1st try: ' . $cache->getResultMessage(), PHP_EOL;
    
    $cacheResult = $cache->get($cacheKey);
    if (empty($cacheResult)) {
        echo 'Entity not found in cache on 2nd try: ' . $cache->getResultMessage(), PHP_EOL;
        
        $cacheResult = $cache->get($cacheKey);
        if (empty($cacheResult)) {
            echo 'Entity not found in cache on 3rd try: ' . $cache->getResultMessage(), PHP_EOL;
            
            $cacheResult = $cache->get($cacheKey);
            if (empty($cacheResult)) {
                echo 'Entity not found in cache on 4th try: ' . $cache->getResultMessage(), PHP_EOL;
                
                $entity
                    ->setTitle('TEST')
                    ->setText('Hellow w0rld. Lorem Orem Rem Em M IpsuM')
                    ->setUrl('http://www.google.com/content-123456789.html');
                
                $cache->set($cacheKey, $entity->serialize(), 120);
            }
        }
        else { $found = true; }
    }
    else { $found = true; }
}
else { $found = true; }


if ($found === true) {
    echo 'Entity found in Cache: ' . $cache->getResultMessage(), PHP_EOL;
    $entity->unserialize($cacheResult);
    echo 'Title: ' . $entity->getTitle(), PHP_EOL;
}

echo PHP_EOL;

  • 您所经历的行为是一致的。当服务器不可用时,它首先被标记为故障,然后被标记为死亡。

问题是,如果你设置了,显然它才会连贯Memcached::OPT_SERVER_FAILURE_LIMIT当您将其设置为 1 时,将值设置为 2。这可以解释为什么每个无法访问的服务器都有两个错误行(CONNECTION FAILURE, SERVER IS MARKED AS DEAD)

这似乎与超时有关。添加一个usleep()匹配失败后OPT_RETRY_TIMEOUT值将使服务器从列表中删除(请参阅以下错误评论 https://bugs.launchpad.net/libmemcached/+bug/1158676/comments/4)

  • 该值不会复制到下一个服务器,因为仅分发密钥。

  • 注意OPT_LIBKETAMA_COMPATIBLE不使用 libketama,但仅重现相同的算法,这意味着 libketama 不再处于活动状态并不重要,而这是推荐的配置在 PHP 文档中 http://php.net/manual/en/memcached.constants.php:

如果您想使用一致性哈希,强烈建议启用此选项,并且在未来版本中可能会默认启用此选项。

EDIT:根据我对您的帖子的理解,消息“在缓存中找到实体:成功”仅出现在第二次运行(1 个服务器离线)时,因为上一个命令没有更改,并且托管此密钥的服务器仍然可用(因此 memcached 考虑从值存储在第一、第二或第三服务器上的键)。我们将这些服务器称为 John、George、Ringo 和 Paul。

在第三次运行中,在启动时,memcached 根据密钥推断出四台服务器中的哪一台拥有该值(例如 John)。它在放弃之前询问了约翰两次,因为它现在已经关闭了。然后它的算法只考虑 3 个服务器(不知道 Paul 已经死了)并推断出 George 应该包含该值。

乔治两次回答它不包含该值,然后存储它。

但在第四轮比赛中,约翰、乔治和保罗出局了。 Memcached 尝试了 John 两次,然后尝试了 George 两次。然后它存储在 Ringo 中。

这里的问题是,在不同的运行之间不会记住不可用的服务器,并且在同一次运行中,您必须在删除服务器之前询问两次服务器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Memcached 一致性哈希在 4 台服务器中的 3 台宕机时不起作用 的相关文章

  • Laravel 集成测试:如何断言一个 URL 已被调用但另一个 URL 没有

    我想测试一个向某个 URL 发出请求的控制器 例如 http example com api say hello 但它不会向另一个 URL 发出请求 例如 http example com api say bye bye 我想测试的控制器功
  • 是否必须配置 PHP 才能通过 PHP 扫描每个目录的配置 INI 文件(即我的情况下的 .htaccess 文件)?

    我在用着Windows 10 家庭单语言 64 位操作系统在我的机器上 我已经安装了最新的副本XAMPP服务器在我的机器上附带PHP 7 2 7 我从 PHP 手册中阅读了以下页面 扫描目录 https secure php net man
  • 按通用值对值进行分组:userid 和 ipaddress

    我正在解决数据库中的一个问题 我正在尝试查找使用多个帐户的用户 我有一个用户 ID 和使用的 IP 地址的列表 如下所示 用户 ID IP 地址 1 IP 地址 13 2 IP 地址 23 1 IP 地址 12 4 IP地址56 9 IP
  • PHP - Filter_var 替代方案?

    我构建了一个 php 脚本来输出以表单形式发布的数据 但遇到了问题 网站将运行的服务器运行 PHP 5 1 6 此版本的 PHP 不支持 filter var 我需要知道短期内的替代方案 最好是昨天 但在 Google 或 Stack Ov
  • 如何复制 ArrayIterator 以保留其当前迭代位置?

    因为这似乎是我必须做的才能达到这种效果 arr a gt first b gt second iter new ArrayIterator arr Do a bunch of iterations iter gt next new iter
  • 如何将 HTML 转换为 Markdown?

    我有一个类似 stackoverflow 的网站 有一个文本区域 人们可以在其中写答案 我用这个 PHP 库 http parsedown org 转换降价 我的意思是我使用该函数来转换 italic to i italic i inclu
  • 负载平衡集群中的 PHP 会话 - 如何?

    好的 我得到了这个完全罕见的负载平衡 PHP 网站的独特场景 令人遗憾的是 它过去没有进行负载平衡 现在我们开始遇到问题 目前唯一的问题是 PHP 会话 当然 一开始没有人想到这个问题 因此 PHP 会话配置保留为默认值 因此 两台服务器都
  • 使用 php 在多维数组中按键排序[重复]

    这个问题在这里已经有答案了 可能的重复 在 PHP 中对多维数组进行排序 https stackoverflow com questions 2059255 sorting multidimensional array in php 如何在
  • 使用先前的反向引用作为命名捕获组的名称

    有没有办法使用对先前捕获组的反向引用作为捕获组的名称命名捕获组 这可能不可能 如果不可能 那么这就是一个有效的答案 下列 data description some description preg match data matches p
  • Magento - 检查 cms 页面

    我想通过 php 检查页面是否是 Magento 中的 cms page 我需要不同的 cms 页面面包屑 所以我尝试在一个条件下做到这一点 但我不知道如何或在哪里查看 到目前为止 这是我的 breadcrumbs phtml p some
  • WordPress 分页自定义帖子类型

    我有一个名为 新闻 的页面 使用页面模板page newslist php 它应该显示来自自定义帖子类型 也称为新闻 的帖子 我意识到两者具有相同的名称会导致问题 因此在注册自定义帖子类型时 我进行了重写以将其与页面区分开来 rewrite
  • 为什么我的 if 语句没有按我预期的方式工作?

    我正在尝试实现以下目标 我向我的 SQL 数据库询问使用SELECT FROM subjects 这样做之后我要求使用数组mysqli fetch assoc 在那之前一切都很好 现在的问题是 当我尝试在每个循环中修改 genero 的值
  • MySQL PHP邮政编码比较具体距离

    我试图找出比较一个邮政编码 用户提供的 和一大堆其他邮政编码 现在大约有 200 个邮政编码 之间的距离的最有效方法 相对于加载时间 但它会随着时间的推移而增加 我不需要任何精确的东西 只是在球场上 我下载了整个美国的邮政编码 csv 文件
  • Joomla 页面中的自定义 php 代码

    我正在尝试将 Joomla 1 5 9 页面中的表源从页面中的硬编码 html 更改为从 SQL 数据库获取信息 执行此操作的正确方法是什么 创建一个新的模型或组件并以某种方式在页面中使用它 我找到了这些 http docs joomla
  • 如何仅使用 PHP5 RecursiveDirectoryIterator 类递归显示具有特定文件类型的文件夹和子文件夹

    您好 我正在尝试使用 FilterIterator 上的扩展来获取 RecursiveDirectoryIterator 类 但由于某种原因 它仅在根目录上进行迭代 我的代码是这样的 class fileTypeFilter extends
  • WordPress 插件中的类自动加载器

    我想编写一个类自动加载器以在 WordPress 插件中使用 该插件将安装在多个站点上 我想尽量减少与其他插件发生冲突的机会 自动加载器将是这样的 function autoload name some code here 我的主要问题是
  • suhosin.mt_srand.ignore 在 PHP 中一致洗牌数组的解决方法?

    我有一个 PHP 脚本 需要随机化一个具有一致结果的数组 这样它就可以向用户呈现前几个项目 然后如果他们愿意 他们可以从同一个打乱的集合中提取更多结果 我目前使用的是这个 基于我相信的 Fisher Yates 算法 function sh
  • Laravel leftJoin 仅右表的最后一条记录

    我是 Laravel 的新手 我有两张桌子 1 产品 2 价格 products id product int p key name varchar prices id price int p key id product int
  • 如何使用 PHP 对字符串进行 rot13 处理?

    我有一个很大的 php 代码 我想手动对其进行编码和解码 我的问题是 php 代码里面有很多单引号和双引号 因此我在使用时出现错误str rot13 功能如下 那么正确的语法是什么以及如何使用下面的函数进行编码 str rot13 That
  • 使用 php-ews(Exchange Web 服务)在特定日期后获取电子邮件

    在我的 PHP 脚本中 我需要弄清楚如何检索指定消息 ID 之后或特定日期之后的所有电子邮件 两者都可以 我只需要检索自上次抓取收件箱以来的新电子邮件 这个收件箱每天收到数千封电子邮件 而且我在 30 天内无法删除任何电子邮件 对于初始导入

随机推荐