2

我的问题与 PHP Memcache 扩展的 addServer 函数中的“权重”参数有关。
在过去的几个月里,我一直在为所有服务器使用“weight = 1”。我现在正在尝试应用以下配置以最终从轮换中删除“10.10.10.3”并最大限度地减少数据丢失。
有了新的权重值,我的 PHP 客户端无法检索它曾经能够获取的键的值。如果我恢复为“weight = 1”,则可以毫无问题地获取所有键。

为了在“Memcache::addServer”中正确使用“权重”选项,是否有任何配置或任何我遗漏的东西?

感谢您的帮助。

 $hosts = array(
      array('ip' => '10.10.10.1', 'port' => 11211, 'weight' => 100),
      array('ip' => '10.10.10.2', 'port' => 11211, 'weight' => 100),
      array('ip' => '10.10.10.3', 'port' => 11211, 'weight' => 1),
      array('ip' => '10.10.10.4', 'port' => 11211, 'weight' => 100),
 );

 $memcache = new Memcache();
 foreach($hosts as $host) {
    $host['port'] = isset($host['port']) ? (int) $host['port'] : 11211;
    $host['weight'] = isset($host['weight']) ? (int) $host['weight'] : 1;
    $memcache->addserver($host['ip'], $host['port'], false, $host['weight'], 1, 15);
 }

PHP 版本= 5.3.10

Memcache PHP 变量
- memcache 支持 => 启用
- memcache.allow_failover => 1 => 1
- memcache.chunk_size => 32768 => 32768
- memcache.compress_threshold => 20000 => 20000
- memcache.default_port => 11211 => 11211
- memcache.hash_function => crc32 => crc32
- memcache.hash_strategy => 一致 => 一致
- memcache.lock_timeout => 15 => 15
- memcache.max_failover_attempts => 20 => 20
- memcache.protocol => ascii => ascii
- memcache.redundancy => 1 => 1
- memcache.session_redundancy => 2 => 2

Memcached 版本
10.10.10.1 / 10.10.10.2 / 10.10.10.3 正在运行 1.4.5
10.10.10.4 正在运行 1.4.4

4

2 回答 2

11

weight 参数影响用于确定从哪个服务器读取/写入密钥的一致散列。更改池中任何 1 台服务器的权重将导致一些缓存未命中。池中的服务器数量以及您更改权重的程度将影响您可能遇到的未命中次数。

您需要了解的是 memcached 是分布式的,这意味着由于您有 4 个服务器,因此密钥分布在每个服务器之间(尽可能接近均匀[权重会影响均匀分布])。如果一台服务器出现故障,则无法再访问存储在该服务器上的数据,并且必须从数据库中获取数据,因为它在任何其他服务器上都不可用。*请注意,PHP 扩展memcachememcached只是访问memcached集群的客户端(memcached 是两者中较新的,支持更多功能,但两者都与 memcached 集群中的服务器通信)。

当您想从缓存中存储或检索值时,会计算一个哈希值,该哈希值确定应该从集群中的哪个位置放置或读取数据。说明这一点的常用方法是使用 360 度圆,如下所示。您计算一个哈希,并使用它在圆圈中“最接近”的节点。添加或删除服务器,或更改任何一台服务器的权重都会影响散列的结果并导致未命中。

在此处输入图像描述
资料来源:http ://alpha.mixi.co.jp/blog/?p=158

如果您想慢慢地将服务器从集群中移出,我建议逐渐降低其权重,直到它为 0,然后您可以将服务器从列表中完全删除。请记住,权重的任何微小变化都可能/将导致缓存未命中,但是权重变化的幅度(以及您拥有的服务器数量)会影响您将经历的未命中次数。

这是Memcached 教程故事中的一个片段,它也可能有助于解释其中的一些内容。

前言是两个系统管理员建立了一个有 3 台服务器的 memcached 集群,并告诉 memcached 在每台服务器上使用 1GB...

因此,他再次获取程序员使用的密钥并在他的 memcached 服务器上查找它们。'get this_key' 'get that_key' 但每次他这样做时,他只能在一个 memcached 上找到每个键!现在你为什么要这样做,他想?他整晚都在困惑。这太傻了!您不希望密钥位于所有 memcached 上吗?

“但是等等”,他想“我给每个 memcached 1 GB 的内存,这意味着我总共可以缓存 3 GB 的数据库,而不仅仅是一个!哦,伙计,这太棒了,”他想。“这将为我节省大量现金。布拉德·菲茨帕特里克,我爱你的屁股!”

“但是,嗯,下一个问题,这是一个令人困惑的问题,这个网络服务器就在这里,这个运行 memcached 它很旧,它有病,需要升级。但为了做到这一点,我必须让它离线!会发生什么到我可怜的内存缓存集群?嗯,让我们找出答案,”他说,然后关闭了盒子。现在他看着他的图表。“哦,不,DB 负载,它已经大步向前了!负载不是一个,现在是两个。嗯,但仍然可以忍受。所有其他 memcached 仍在获得流量。这还不错。只是一个几次缓存未命中,我的工作几乎完成了。所以他重新打开机器,让 memcached 恢复工作。几分钟后,数据库负载再次下降到 1,它应该一直在这个位置。

“缓存自己恢复了!我现在明白了。如果它不可用,那只是意味着我的一些请求被遗漏了。但这还不足以杀死我。这很甜蜜。”

道德是存储在 memcached 中的值仅存储在一台服务器上(即密钥分布在所有服务器中),如果其中任何一台服务器不可用,则数据无法从缓存中获取,必须从源中获取.

为了从集群中的正确节点正确存储和检索数据,密钥必须一致地散列,以便客户端知道哪个服务器是池中该特定密钥的正确服务器。

正如您可能猜到的那样,不同的客户端使用不同的散列技术,因此使用 Perl 客户端和 PHP 客户端来存储/检索值将无法按预期工作,因为它们的散列方式不同。例外情况是任何使用libmemcached的客户端,从那时起它们都将使用相同的散列算法。PHP 的memcached扩展使用libmemcached,而memcache没有使用它自己的散列算法(据我所知)。

进一步阅读:
- memcached wiki学习 memcached 的冒险
-一致哈希
-分布式哈希表

于 2012-06-05T21:10:10.763 回答
1

问题是您使用的是memcachememcached。Memcached 是分布式的,这意味着添加到池中的所有服务器都充当一个缓存服务器。因此,如果 server1 已关闭,您仍然可以检索键/值,因为它们分布在其他三个服务器上。而使用 memcache (no d),每个服务器基本上都是一个孤岛,这意味着存储在 server1 上的键/值不能保证出现在任何其他缓存服务器上。

如果您想弃用有问题的缓存服务器,我建议在您的 api 调用中添加一些额外的逻辑以从持久存储中提取值,然后将其存储在至少两个其他有效缓存服务器中。我见过一些项目,其中缓存值将保存在两台缓存服务器之间,以确保一台服务器不再响应,另一台服务器可以弥补这一不足。

- 更新 -

无论使用哪个 PHP 内存缓存 API,如果从池中删除服务器,将导致缓存未命中驻留在现在丢失的服务器上的键。当$cache->get()失败并进入持久存储并被$cache->set()调用时,缓存现在将存储在不同的活动服务器上。感谢 Drew010 对此的澄清。

如果您绝对不能承受任何缓存未命中,您仍然可以编写您的应用程序以将相同的缓存值写入多个服务器。

于 2012-06-05T18:10:05.073 回答