Xmemcached 1.3预览:failure模式和standby节点

dennis_zane 2010-12-28


    Xmemcached 在元旦左右准备发1.3这个版本,这个版本新增加的一个关键特性就是所谓的failure模式。关于这个,可以看下memcached官方文档的解释《Failure,or Failover》

    展开来说,在某个memcached节点挂掉或者由于其他故障连接断开的时候,大部分客户端的默认策略都是failover的,也就是会查找下一个可用的 memcached节点继续使用,挂掉或者连接不上的节点的数据会转移到其他节点上,路由的策略可以是Round Robin,也可以是一致性哈希。这样的模式在节点意外故障挂掉的情况下运行的很好,但是memached节点也完全可能因为一个意外的事故而短暂 挂 掉,比如你不小心弄掉了网线又马上接上去,比如机房交换机突然停电又立即恢复了,假设在故障前,用户A正要更新数据到节点A,节点A意外断开,那么这些数 据就更新到下一个有效节点B,但是节点A又马上恢复,这时候用户又从节点A去读数据,读到却是更新前的老数据了(新数据更新到B节点去了),这种情况对用 户来说就非常困惑,你告诉我更新成功,但是看到却还是更新前的数据。

   怎么解决呢?一个简单的方案就是所谓failure模式,当某个节点挂掉的时候,不会从节点列表移除,请求也不会转移到下一个有效节点,而是直接将请求置 为失败,就刚才的场景来说,在用户更新数据到节点A的时候,节点A意外断开,那么用户的这次更新请求不会转移到节点B,而是直接告诉用户更新失败,用户再 次查询数据则绕过节点A直接查询后端存储。这种模式很适合这种节点短暂不可用的状况,请求会穿透缓存到后端,但是避免了新旧数据的问题。
    Xmemcached 1.3将支持failure模式,只要你设置下failureMode为true即可,简单示例:

           XMemcachedClientBuilder builder =……
               //设置使用failure模式
           builder.setFailureMode(true);
 

 

      在此模式下,某个节点挂掉的情况下,往这个节点的请求都将直接抛出MemcachedException的异常。

      不仅如此,xmemcached 1.3还将引入standby node的概念,你可以设置某个memached节点的备份节点,当这个节点挂掉的时候会将请求转发给这个备份节点,不会简单地抛出异常,也不会转发给其 他节点。要使用standby node,必须首先设置使用failure mode,一个例子:

XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil
                .getAddressMap("192.168.1.99:11211,192.168.1.100:11211 192.168.1.101:11211,192.168.1.102:11211"));
builder.setFailureMode(true);
 


     可以看到,新的服务器字符串格式变化为host:port,host:port host:port,host:port的格式,以空格隔开的是两个节点组成的一个分组,以逗号隔开的是主节点和备份节点,以上面的例子来说,我们设置客 户端使用的节点是192.168.1.99和192.168.1.101,其中99对应的备份节点是100,而101的备份节点是102。并且我们需要设 置使用failure mode为true。
   
     Failure mode加上standby节点可以比较好的解决新旧数据的问题,并且也可以防止请求穿透缓存到DB,但是主备两个节点之间的数据同步,xmemcached不准备帮你做,我的建议是可以使用repcached这个patch做复制。
    有的朋友可能希望,在使用备份节点之前先flush掉备份节点的数据,防止使用到老的数据,请求还是可以穿透缓存去DB查找,并存储到备份节点,我仔细考 虑了这个方案,衡量之下还是不准备做自动flush,主要是并发上很难处理,并且flush数据这个事情可以手工来搞,根据我的经验,做的太透明太自动不 一定是好事。你可以在主节点恢复之后,手工flush下备份节点的数据。


    目前,xmemcached 1.3已经整装待发,对这些特性有兴趣的朋友可以先从svn下载源 码尝鲜,有任何改进的建议请留言。

lovit 2010-12-28
lvbaosong 2011-01-27
按照你上面说的我做了standby 为了测试是否有效,我将主memecached服务给关了,
程序抛出异常没自动切换到备memecached。是不是我使用有问题?

另外请问
XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil .

[code="java"]getAddressMap("192.168.1.99:11211,192.168.1.100:11211 192.168.1.101:11211,192.168.1.102:11211"))
99和101两个主服务节点的数据是一样的对吧?这两个服务器的数据在插入缓存时候是xmemcached同步了数据,还是自己程序中实现数据的一致?
dennis_zane 2011-01-27
lvbaosong 写道
按照你上面说的我做了standby 为了测试是否有效,我将主memecached服务给关了,
程序抛出异常没自动切换到备memecached。是不是我使用有问题?

另外请问
XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil .

[code="java"]getAddressMap("192.168.1.99:11211,192.168.1.100:11211 192.168.1.101:11211,192.168.1.102:11211"))
99和101两个主服务节点的数据是一样的对吧?这两个服务器的数据在插入缓存时候是xmemcached同步了数据,还是自己程序中实现数据的一致?

文中已经提了,数据不会做同步。
lvbaosong 2011-01-27
dennis_zane 写道
lvbaosong 写道
按照你上面说的我做了standby 为了测试是否有效,我将主memecached服务给关了,
程序抛出异常没自动切换到备memecached。是不是我使用有问题?

另外请问
XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil .

[code="java"]getAddressMap("192.168.1.99:11211,192.168.1.100:11211 192.168.1.101:11211,192.168.1.102:11211"))
99和101两个主服务节点的数据是一样的对吧?这两个服务器的数据在插入缓存时候是xmemcached同步了数据,还是自己程序中实现数据的一致?

文中已经提了,数据不会做同步。

呵呵,谢谢回复,我看文章中说的是主备模式不做数据同步,以为每组节点中的 主缓存可以数据同步呢。这个问题算是清楚了。

  上面的standby没起作用请问可能是什么原因,能给解释下不?
dennis_zane 2011-01-27
lvbaosong 写道
dennis_zane 写道
lvbaosong 写道
按照你上面说的我做了standby 为了测试是否有效,我将主memecached服务给关了,
程序抛出异常没自动切换到备memecached。是不是我使用有问题?

另外请问
XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil .

[code="java"]getAddressMap("192.168.1.99:11211,192.168.1.100:11211 192.168.1.101:11211,192.168.1.102:11211"))
99和101两个主服务节点的数据是一样的对吧?这两个服务器的数据在插入缓存时候是xmemcached同步了数据,还是自己程序中实现数据的一致?

文中已经提了,数据不会做同步。

呵呵,谢谢回复,我看文章中说的是主备模式不做数据同步,以为每组节点中的 主缓存可以数据同步呢。这个问题算是清楚了。

  上面的standby没起作用请问可能是什么原因,能给解释下不?


在切换的瞬间是有可能抛出异常的,后续的请求会发给standby节点。
lvbaosong 2011-01-30
dennis_zane 写道
lvbaosong 写道
dennis_zane 写道
lvbaosong 写道
按照你上面说的我做了standby 为了测试是否有效,我将主memecached服务给关了,
程序抛出异常没自动切换到备memecached。是不是我使用有问题?

另外请问
XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil .

[code="java"]getAddressMap("192.168.1.99:11211,192.168.1.100:11211 192.168.1.101:11211,192.168.1.102:11211"))
99和101两个主服务节点的数据是一样的对吧?这两个服务器的数据在插入缓存时候是xmemcached同步了数据,还是自己程序中实现数据的一致?

文中已经提了,数据不会做同步。

呵呵,谢谢回复,我看文章中说的是主备模式不做数据同步,以为每组节点中的 主缓存可以数据同步呢。这个问题算是清楚了。

  上面的standby没起作用请问可能是什么原因,能给解释下不?


在切换的瞬间是有可能抛出异常的,后续的请求会发给standby节点。

哦,我在测试试试
evanz 2011-02-18
发现failure模式有点小问题,
MemcachedClientBuilder builder = new XMemcachedClientBuilder(
                AddrUtil.getAddresses("192.168.8.122:11211 192.168.8.141:11211"));
builder.setFailureMode(true);
memcachedClient.set("user", 0, "Hello,xmemcached");
假设key: user 经过hash后是分配到192.168.8.141上,但是在运行程序前,192.168.8.141上的memcached并没启动,此时,就算设置了setFailureMode(true),xmemcache不会抛个异常,而是将数据些到了192.168.8.122上了。。。这并不是期望的结果啊,因为当192.168.8.141的memcached启动后,后续对user这个key的操作又转到了192.168.8.141上,这样用户会比较困惑。。。
dennis_zane 2011-02-18
evanz 写道
发现failure模式有点小问题,
MemcachedClientBuilder builder = new XMemcachedClientBuilder(
                AddrUtil.getAddresses("192.168.8.122:11211 192.168.8.141:11211"));
builder.setFailureMode(true);
memcachedClient.set("user", 0, "Hello,xmemcached");
假设key: user 经过hash后是分配到192.168.8.141上,但是在运行程序前,192.168.8.141上的memcached并没启动,此时,就算设置了setFailureMode(true),xmemcache不会抛个异常,而是将数据些到了192.168.8.122上了。。。这并不是期望的结果啊,因为当192.168.8.141的memcached启动后,后续对user这个key的操作又转到了192.168.8.141上,这样用户会比较困惑。。。



这确实是个问题,没有考虑到在启动的时候,memcached故障的情况。我会尝试修正,感谢。
windflower_07 2011-06-13
   试了一下standby模式,发现如果开始主节点就是坏的,那么第一次还是去主节点取数据了,取出来为null了,第二次才去备节点。

  有个这样的需求,不知道dennis 觉得如何,我们这两个Memcached服务,数据一模一样,现在想用,主要指读的时候,各负担50%压力,但是一个挂了,全部压力到另一个server(即standby 模式了)。
   此外,有个地方文档有点小问题
   http://code.google.com/p/xmemcached/wiki/User_Guide_zh#Failure%E6%A8%A1%E5%BC%8F%E5%92%8Cstandby%E8%8A%82%E7%82%B9

  
Global site tag (gtag.js) - Google Analytics