Memcached笔记——(二)XMemcached&Spring集成




    博客分类:
    Server Architecture/Distributed
    Java/Cache
    Spring

MemcachedjavaXMemcached
今天研究Memcached的Java的Client,使用XMemcached 1.3.5,做个简单的测试,并介绍如何与Spring集成。



一、Memcached Client简要介绍
Memcached Client目前有3种:

    Memcached Client for Java
    SpyMemcached
    XMemcached


这三种Client一直存在各种争议:

    Memcached Client for Java 比 SpyMemcached更稳定、更早、更广泛;
    SpyMemcached 比 Memcached Client for Java更高效;
    XMemcached 比 SpyMemcache并发效果更好。



用数据来说话,参考官方性能对比:
Memcached Client for Java:https://github.com/gwhalin/Memcached-Java-Client/wiki/PERFORMANCE
XMemcached:http://xmemcached.googlecode.com/svn/trunk/benchmark/benchmark.html

二、XMemcached特性
XMemcached特性:

    高性能
    支持完整的memcached文本协议,二进制协议。
    支持JMX,可以通过MBean调整性能参数、动态添加/移除server、查看统计等。
    支持客户端统计
    支持memcached节点的动态增减。
    支持memcached分布:余数分布和一致性哈希分布。
    更多的性能调整选项。


此外,XMemcached更容易与Spring集成。而且,属于中国原创!

三、XMemcached简单实现

MemcachedClientBuilder是MemcachedClient核心接口,用来控制Client的构建(build()方法)和关闭(shutdown()方法)。
XMemcachedClientBuilder一般通过构造方法配置地址列表,通常还要配置权重,代码如下:
Java代码  收藏代码

    public XMemcachedClientBuilder(List<InetSocketAddress> addressList) { 
        if (addressList != null) { 
            for (InetSocketAddress addr : addressList) { 
                this.addressMap.put(addr, null); 
            } 
        } 
    } 
     
    public XMemcachedClientBuilder(List<InetSocketAddress> addressList, 
            int[] weights) { 
        if (addressList != null) { 
            for (InetSocketAddress addr : addressList) { 
                this.addressMap.put(addr, null); 
            } 
        } 
        this.weights = weights; 
    } 


不过这哥们如果用this()可以省点代码, 还有给加点注释吧!
此外,还需要设置连接池大小,使用二进制协议/文本协议等。
通过build()方法获得MemcachedClient
然后就可以通过Memcached进行set、get、replace、delete等Memcached操作了!
上代码:
Java代码  收藏代码

    import static junit.framework.Assert.*; 
     
    import java.io.IOException; 
    import java.util.concurrent.TimeoutException; 
     
    import net.rubyeye.xmemcached.MemcachedClient; 
    import net.rubyeye.xmemcached.MemcachedClientBuilder; 
    import net.rubyeye.xmemcached.XMemcachedClientBuilder; 
    import net.rubyeye.xmemcached.command.BinaryCommandFactory; 
    import net.rubyeye.xmemcached.exception.MemcachedException; 
    import net.rubyeye.xmemcached.utils.AddrUtil; 
     
    import org.junit.Test; 
     
    public class MemcachedClientTest { 
        @Test 
        public void test() { 
            MemcachedClientBuilder builder = new XMemcachedClientBuilder( 
                    AddrUtil.getAddresses("10.11.155.26:11211 10.11.155.41:11211 10.10.76.31:11211 10.10.76.35:11211"), 
                    new int[] { 1, 1, 1, 1 }); 
             
            // 设置连接池大小,即客户端个数 
            builder.setConnectionPoolSize(50); 
     
            // 宕机报警 
            builder.setFailureMode(true); 
     
            // 使用二进制文件 
            builder.setCommandFactory(new BinaryCommandFactory()); 
     
            MemcachedClient memcachedClient = null; 
            try { 
                memcachedClient = builder.build(); 
                try { 
                    // 设置/获取 
                    memcachedClient.set("zlex", 36000, "set/get"); 
                    assertEquals("set/get", memcachedClient.get("zlex")); 
     
                    // 替换 
                    memcachedClient.replace("zlex", 36000, "replace"); 
                    assertEquals("replace", memcachedClient.get("zlex")); 
     
                    // 移除 
                    memcachedClient.delete("zlex"); 
                    assertNull(memcachedClient.get("zlex")); 
                } catch (TimeoutException e) { 
                    // TODO Auto-generated catch block 
                    e.printStackTrace(); 
                } catch (InterruptedException e) { 
                    // TODO Auto-generated catch block 
                    e.printStackTrace(); 
                } catch (MemcachedException e) { 
                    // TODO Auto-generated catch block 
                    e.printStackTrace(); 
                } 
     
            } catch (IOException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            } finally { 
                if (memcachedClient != null) { 
                    try { 
                        memcachedClient.shutdown(); 
                    } catch (IOException e) { 
                        // TODO Auto-generated catch block 
                        e.printStackTrace(); 
                    } 
                } 
            } 
        } 
    } 


四、XMemcached与Spring集成
XMemcached与Spring集成可以参考http://code.google.com/p/xmemcached/wiki/Spring_Integration,这里只说最常用的方法。
memcached.properties做基本配置:
Properties代码  收藏代码

    #连接池大小即客户端个数 
    memcached.connectionPoolSize=50 
    memcached.failureMode=true 
    #server1 
    memcached.server1.host=10.11.155.26 
    memcached.server1.port=11211 
    memcached.server1.weight=4 
    #server2 
    memcached.server2.host=10.11.155.41 
    memcached.server2.port=11211 
    memcached.server2.weight=3               
    #server3 
    memcached.server3.host=10.10.76.31 
    memcached.server3.port=11211 
    memcached.server3.weight=2                   
    #server4 
    memcached.server4.host=10.10.76.35 
    memcached.server4.port=11211 
    memcached.server4.weight=1        
          


XML配置文件:
Xml代码  收藏代码

    <?xml version="1.0" encoding="UTF-8"?> 
    <beans 
        xmlns="http://www.springframework.org/schema/beans" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:context="http://www.springframework.org/schema/context" 
        xmlns:p="http://www.springframework.org/schema/p" 
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 
        <!-- http://code.google.com/p/xmemcached/wiki/Spring_Integration --> 
        <context:property-placeholder location="memcached.properties" /> 
        <bean 
            id="memcachedClientBuilder" 
            class="net.rubyeye.xmemcached.XMemcachedClientBuilder" 
            p:connectionPoolSize="${memcached.connectionPoolSize}" 
            p:failureMode="${memcached.failureMode}"> 
            <!-- XMemcachedClientBuilder have two arguments.First is server list,and  
                second is weights array. --> 
            <constructor-arg> 
                <list> 
                    <bean class="java.net.InetSocketAddress"> 
                        <constructor-arg> 
                            <value>${memcached.server1.host}</value> 
                        </constructor-arg> 
                        <constructor-arg> 
                            <value>${memcached.server1.port}</value> 
                        </constructor-arg> 
                    </bean> 
                    <bean class="java.net.InetSocketAddress"> 
                        <constructor-arg> 
                            <value>${memcached.server2.host}</value> 
                        </constructor-arg> 
                        <constructor-arg> 
                            <value>${memcached.server2.port}</value> 
                        </constructor-arg> 
                    </bean> 
                    <bean class="java.net.InetSocketAddress"> 
                        <constructor-arg> 
                            <value>${memcached.server3.host}</value> 
                        </constructor-arg> 
                        <constructor-arg> 
                            <value>${memcached.server3.port}</value> 
                        </constructor-arg> 
                    </bean> 
                    <bean class="java.net.InetSocketAddress"> 
                        <constructor-arg> 
                            <value>${memcached.server4.host}</value> 
                        </constructor-arg> 
                        <constructor-arg> 
                            <value>${memcached.server4.port}</value> 
                        </constructor-arg> 
                    </bean> 
                </list> 
            </constructor-arg> 
            <constructor-arg> 
                <list> 
                    <value>${memcached.server1.weight}</value> 
                    <value>${memcached.server2.weight}</value> 
                    <value>${memcached.server3.weight}</value> 
                    <value>${memcached.server4.weight}</value> 
                </list> 
            </constructor-arg> 
            <property name="commandFactory"> 
                <bean class="net.rubyeye.xmemcached.command.TextCommandFactory" /> 
            </property> 
            <property name="sessionLocator"> 
                <bean class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator" /> 
            </property> 
            <property name="transcoder"> 
                <bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" /> 
            </property> 
        </bean> 
        <!-- Use factory bean to build memcached client --> 
        <bean 
            id="memcachedClient" 
            factory-bean="memcachedClientBuilder" 
            factory-method="build" 
            destroy-method="shutdown" /> 
    </beans> 



这里的memcachedClientBuilder节点完成MemcachedClientBuilder,然后通过memcachedClient节点配置factory-method,调用MemcachedClientBuilder的build()方法产生MemcachedClient,并配置destroy-method进行关闭。
不过我还是疑惑,这里的异常由谁来处理?Spring容器吗? 或者需要另一个代理Bean包装一下?

有了Spring容器支持,我们不需要在代码中进行配置,也不需要重复调用build()跟shutdown()方法,这些操作交给Spring来完成。
代码如下:
Java代码  收藏代码

    import static junit.framework.Assert.*; 
     
    import java.util.concurrent.TimeoutException; 
     
    import net.rubyeye.xmemcached.MemcachedClient; 
    import net.rubyeye.xmemcached.exception.MemcachedException; 
     
    import org.junit.Before; 
    import org.junit.Test; 
    import org.springframework.context.ApplicationContext; 
    import org.springframework.context.support.ClassPathXmlApplicationContext; 
     
    public class MemcachedSpringTest { 
     
        private ApplicationContext app; 
        private MemcachedClient memcachedClient; 
     
        @Before 
        public void init() { 
            app = new ClassPathXmlApplicationContext("applicationContext.xml"); 
            memcachedClient = (MemcachedClient) app.getBean("memcachedClient"); 
        } 
     
        @Test 
        public void test() { 
            try { 
                // 设置/获取 
                memcachedClient.set("zlex", 36000, "set/get"); 
                assertEquals("set/get", memcachedClient.get("zlex")); 
     
                // 替换 
                memcachedClient.replace("zlex", 36000, "replace"); 
                assertEquals("replace", memcachedClient.get("zlex")); 
     
                // 移除 
                memcachedClient.delete("zlex"); 
                assertNull(memcachedClient.get("zlex")); 
            } catch (TimeoutException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            } catch (InterruptedException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            } catch (MemcachedException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            } 
        } 
    } 

猜你喜欢

转载自yao-wenjun.iteye.com/blog/2028114