Memcached笔记——(二)XMemcached&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(); 
        } 
    } 

你可能感兴趣的:(xmemcached)