huzhongx / memcache-client-forjava

Automatically exported from code.google.com/p/memcache-client-forjava
0 stars 1 forks source link

关于版本2.5.2集群数据同步问题 #29

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
在使用2.5.2的过程中,发现了一个设计上的问题(可能不一定
正确,望大家相互探讨)。
假设通过客户端使用两个memcached服务器实例A,B做集群,那么
客户端在第一次获取数据并放入服务器A的同时,也异步把相�
��的数据放入到服务器B,而如果在存入带有有效期的数据时��
�使用相对时间,假设有效期30分钟),那么相同的数据分别��
�放入A,B的失效时间点也将不同,因为是异步拷贝的,还不��
�证两台服务器的时钟总是一致的,假设这两种情况都会出现�
��那么存入服务器A,B的数据失效时间点差距就更大了,假设�
��5秒钟(即服务器A的数据失效5秒钟后,B的才达到失效时间��
�,而在这5秒钟之内,A是拿不到数据的了,结果客户端从B那�
��能拿到数据,可以看看这个类MemcachedCache的get方法都做了哪�
��事情:

public Object get(String key)
    {
        Object result = null;
        boolean isError = false;

        try
        {
            result = getCacheClient(key).get(key);  
        }
        catch(MemcachedException ex)
        {
            Logger.error(new StringBuilder(helper.getCacheName())
                .append(" cluster get error"),ex);

            isError = true;
        }

        if (result == null && helper.hasCluster())
            if (isError || helper.getClusterMode().equals
                    (MemcachedClientClusterConfig.CLUSTER_MODE_ACTIVE))
        {
            List<MemCachedClient> caches = helper.getClusterCache();

            for(MemCachedClient cache : caches)
            {
                if (getCacheClient(key).equals(cache))
                    continue;

                try
                {
                    try
                    {
                        result = cache.get(key);
                    }
                    catch(MemcachedException ex)
                    {
                        Logger.error(new StringBuilder(helper.getCacheName())
                            .append(" cluster get error"),ex);

                        continue;
                    }

                    //仅仅判断另一台备份机器,不多次判断,防止效率低下
                    if (helper.getClusterMode()
                            .equals(MemcachedClientClusterConfig.CLUSTER_MODE_ACTIVE) && result != null)
                    {
                        Object[] commands = new Object[]{CacheCommand.RECOVER,key,result};

                        addCommandToQueue(commands);
                    }

                    break;

                }
                catch(Exception e)
                {
                    Logger.error(new StringBuilder(helper.getCacheName())
                                .append(" cluster get error"),e);
                }

            }
        }

        return result;
    }

注意代码块:

//仅仅判断另一台备份机器,不多次判断,防止效率低下
if(helper.getClusterMode().equals(MemcachedClientClusterConfig.CLUSTER_MODE_ACTI
VE) && result != null)
    {
    Object[] commands = new Object[]{CacheCommand.RECOVER,key,result};

    addCommandToQueue(commands);
    }

这里的意思就是把从服务器B获取到的数据拷贝到服务器A,而
且是永久不过期的(命令数组中没有时间),而5秒钟过后,B
服务器中的数据将失效,重复前面所述的过程,把数据从服��
�器A拷贝到服务器B,同样变成永久不过期,最终的结果就是��
�置了有效期的数据,都有可能看起来永久无效一样杯具。

以上分析不知道是否存在,有点先斩后奏了,哥去验证一下��
�…

Original issue reported on code.google.com by dengq...@gmail.com on 24 Feb 2012 at 8:27