使用AWS ElastiCache和Zend Cache跨多个服务器时,缓存值不一致。

31

我们正在使用Zend Cache,其后端为指向具有2个缓存节点的AWS ElastiCache集群的memcached。我们的缓存设置如下:

$frontend = array(
    'lifetime' => (60*60*48),
    'automatic_serialization' => true,
    'cache_id_prefix' => $prefix
);
$backend = array(
    'servers' => array(
        array( 'host' => $node1 ),
        array( 'host' => $node2 )
    )
);
$cache = Zend_Cache::factory('Output', 'memecached', $frontend, $backend);
我们以前在使用单个EC2服务器读写缓存时,没有注意到缓存方面的任何问题。然而,最近我们引入了第二个EC2服务器,并且当从一个服务器写入缓存并从另一个服务器读取时,我们突然遇到了问题。这两个服务器由同一个AWS账户管理,都没有问题,可以单独地从缓存中写入或读取数据。它们使用相同的缓存配置。 Server A 执行 $cache->save('hello', 'message'); 随后从 Server A 调用 $cache->load('message'); 会返回预期的结果hello
然而,当 Server B 执行 $cache->load('message'); 时,我们得到了false
就我对ElastiCache的理解而言,发出读取请求的服务器不应影响返回的缓存值。有人能对此进行解释吗?

我认为这可能是延迟问题,你尝试过使用sleep(xxxx)然后从B执行$cache->load吗? - Julius F
不幸的是,情况并非如此。即使几个小时后,从A设置的值也无法从B中读取。 - michaelxor
你使用的是哪个版本的PHP?我认为序列化是这里发挥作用的。尝试禁用自动序列化,看看会发生什么。不幸的副作用是,你必须手动序列化所有不是字符串的东西。 - Rich H.
1
另外,cache_id_prefix是相同的还是生成的值? - Rich H.
我会尝试使用PHP的Memcache编写一些测试代码,将Zend_Cache从方程式中移除。我从来不太喜欢Memcache扩展,总是更喜欢Memcached(但别让我开始谈为什么他们在客户端中添加了一个“d”)。首先,它支持比较和交换操作。 - ficuscr
大家好,感谢反馈。不幸的是,我们现在只有一台服务器(当时正在从A迁移到B),所以我在过去几天里没有机会进一步测试这个问题。我很快就会有更多信息。@Rich PHP 5.3.3,Zend 1.11.9,$prefix是我们用来“分区”缓存的预定值(两台服务器都是相同的)。ficuscr,我可能会采纳你的建议。我们正在使用ZendCache的Memcached后端,因为Elasticache与Memcached“协议兼容”。 - michaelxor
2个回答

1

0

使用普通的哈希算法,更改服务器数量可能会导致许多键被重新映射到不同的服务器,从而导致大量缓存未命中。

想象一下,您的缓存集群中有5个ElastiCache节点,添加第六个服务器可能会导致40%以上的键突然指向与正常情况不同的服务器。这种活动是不可取的,可能会导致缓存未命中,并最终淹没后端数据库的请求。为了最小化这种重新映射,建议在缓存客户端中遵循一致性哈希模型。

一致性哈希是一种模型,它允许在添加或删除服务器时更稳定地分配密钥。一致性哈希描述了将密钥映射到服务器列表的方法,其中添加或删除服务器会导致密钥映射的位置发生非常小的变化。使用这种方法,添加第11个服务器应该导致少于10%的密钥被重新分配。在此类弹性场景中,与普通哈希算法相比,这个百分比可能会有所变化,但效率要高得多。同时,在使用一致性哈希时,建议在所有客户端配置中保持memcached服务器的顺序和数量相同。Java应用程序可以通过spymemcached使用“Ketama库”将此算法集成到其系统中。有关一致性哈希的更多信息,请访问http://www.last.fm/user/RJ/journal/2007/04/10/rz_libketama_-_a_consistent_hashing_algo_for_memcache_clients


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接