Spymemcached 是 Memcached 的一个流行的Java client库(另一个比较著名的是原淘宝的 伯岩/庄晓丹 开发的XMemcached, 他也开发另一个Taobao开源的项目 Metamorphosis),性能表现出色,广泛应用于Java + Memcached 项目中。
Spymemcached 最早由 Dustin Sallings 开发,Dustin 后来和别人一起创办了Couchbase (原NorthScale),职位为首席架构师。2014加入Google。
本身Memcached没有集群的功能,客户端可以根据不同的key值set/get到不同的Memcached的节点上。 一致性Hash算法可以将数据均衡地分配到各个节点,并且在节点加入和退出的时候可以很好地将失效节点上的数据均衡的分配给其它节点。 Spymemcached使用Ketama算法。
但是,当 memcached 集群的一个节点因为某种原因宕机的时候,spymemcached 并没有正确的选择到另外一个live的节点,而是直接失败:
|
|
如果使用XMemcached,则没有这种现象。
spymemcached已经设置为一致性Hash的模式:
|
|
原因在于当key对应的节点(称之为primary node宕机的时候),spymemcached会有限地选择另外一个节点:
|
|
其中locator.getSequence(key)
最多会提供7个备选虚拟节点。
|
|
但是,依照他的注释,在宕机的情况下,大约会有1/128的几率这七个虚拟节点都会指向这个宕机的primary node。
实际上,下面的代码百分百会选择不到那个live ("127.0.0.1:11211")的节点:
|
|
事实上,google groups上也有讨论, 原spymemcached的bug管理系统上也有相关的bug,但是问题并没有解决。
导致的问题是,某些缓存项在某个memcached节点宕机的时候,不能利用缓存系统,只能从其它持久化系统比如数据库中获取值。
问题找到,解决办法也就有了,修改getSequence方法,提供更多的节点共选择:
|
|
另外,如何在运行时动态地增加新的memcached节点? 这篇文章给出了一个解决方案
你不得不重载MemcachedClient, MemcachedConnection 和 DefaultConnectionFactory。作者未测试,不保证work。不管怎样,倒是一个思路。
ExtMemCachedConnection.java
|
|
ExtMemcachedClient.java
|
|
ExtMemcachedConnectionfactory.java
|
|