Memcached之客户端-xmemcached(5)

高性能Java memcached客户端——Xmemcached发布2.0.0版本,主要改进如下:

  1. 性能优化,在测试中文本协议实现有接近10%的性能提升。
  2. 批量获取key如果包含相同的key,会缓存反序列化后的对象,减少重复反序列化的CPU开销。
  3. 修复getStats没办法获取cache dump的Bug,感谢machao9email。
  4. 修复ONE_AT_A_TIME没有正确处理无符号数的Bug,感谢spudone。
  5. 使用纳秒时间戳作为namespace值,避免高并发下的namespace值冲突。


Maven依赖:

<dependency>
	<groupId>com.googlecode.xmemcached</groupId>
	<artifactId>xmemcached</artifactId>
	<version>2.0.0</version>
</dependency>
Spring + Xmemcached
<pre name="code" class="java">	<bean name="memcachedClient"
		class="net.rubyeye.xmemcached.utils.XMemcachedClientFactoryBean">
		<property name="servers">
			<!-- 服务器列表,格式:(ip:端口 ip:端口),多个以空格分割 -->
			<value>10.0.1.75:12000 10.0.1.76:12000 10.0.1.77:12000</value>
		</property>
		<!-- 和servers对应的节点的权重,weights是用来调节Memcached的负载,设置的权重越高,该Memcached节点存储的数据将越多,所承受的负载越大。 -->
		<property name="weights">
			<list>
				<value>1</value>
				<value>2</value>
				<value>3</value>
			</list>
		</property>

		<!-- nio连接池大小,默认一个Memcached节点只有一个连接池,通常条件是没有问题的。但是在典型的高并发环境下,nio的单连接也会遇到性能瓶颈。可通过调整连接池数量,<br> 
			当建立了多个连接到同一个Memcached节点,由于连接之间是不同步的,因此你的应用需要自己保证数据更新的同步 -->
		<property name="connectionPoolSize">
			<value>1</value>
		</property>

		<!-- 与服务器节点个数一致,密码不允许有空格 -->
		<property name="authInfoMap">
			<map>
				<entry key-ref="serverA">
					<bean class="net.rubyeye.xmemcached.auth.AuthInfo"
						factory-method="typical">
						<constructor-arg index="0">
							<value>memcached</value>
						</constructor-arg>
						<constructor-arg index="1">
							<value>123456</value>
						</constructor-arg>
					</bean>
				</entry>
				<entry key-ref="serverB">
					<bean class="net.rubyeye.xmemcached.auth.AuthInfo"
						factory-method="typical">
						<constructor-arg index="0">
							<value>memcached</value>
						</constructor-arg>
						<constructor-arg index="1">
							<value>123456</value>
						</constructor-arg>
					</bean>
				</entry>
				<entry key-ref="serverC">
					<bean class="net.rubyeye.xmemcached.auth.AuthInfo"
						factory-method="typical">
						<constructor-arg index="0">
							<value>memcached</value>
						</constructor-arg>
						<constructor-arg index="1">
							<value>123456</value>
						</constructor-arg>
					</bean>
				</entry>
			</map>
		</property>

		<!-- 分布策略,KetamaMemcachedSessionLocator(一致性哈希,增加主机时降低未命中率问题的解决); 
		还有实现了:ArrayMemcachedSessionLocator;ElectionMemcachedSessionLocator;
		LibmemcachedMemcachedSessionLocator;PHPMemcacheSessionLocator -->
		<property name="sessionLocator">
			<bean class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator" />
		</property>
		<!-- 序列化转换器 -->
		<property name="transcoder">
			<bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
		</property>
		<!-- IoBuffer分配器(内容写入memcached时的内存控制策略) -->
		<property name="bufferAllocator">
			<bean class="net.rubyeye.xmemcached.buffer.SimpleBufferAllocator" />
		</property>
		<!-- 协议工厂net.rubyeye.xmemcached.command.BinaryCommandFactory(二进制),TextCommandFactory(文本),KestrelCommandFactory(可靠获取),本应用配置二进制方式 -->
		<property name="commandFactory">
			<bean class="net.rubyeye.xmemcached.command.BinaryCommandFactory" />
		</property>
	</bean>

	<bean name="serverA" class="java.net.InetSocketAddress">
		<constructor-arg>
			<value>10.0.1.75</value>
		</constructor-arg>
		<constructor-arg>
			<value>12000</value>
		</constructor-arg>
	</bean>

	<bean name="serverB" class="java.net.InetSocketAddress">
		<constructor-arg>
			<value>10.0.1.76</value>
		</constructor-arg>
		<constructor-arg>
			<value>12000</value>
		</constructor-arg>
	</bean>

	<bean name="serverC" class="java.net.InetSocketAddress">
		<constructor-arg>
			<value>10.0.1.77</value>
		</constructor-arg>
		<constructor-arg>
			<value>12000</value>
		</constructor-arg>
	</bean>

 调用 

@Resource
public MemcachedClient memcachedClient;

 public void testString() {
  try {
   for (int i = 1024; i < 1024 * 2; i++) {
    memcachedClient.set("zy" + i, 0, i);
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

更多Memcached操作,请查看Memcached之存储命令(2),然后在Xmemcached客户端找对应的方法。

Java API调用

查看:https://github.com/killme2008/xmemcached

        @Test
	public void javaExample() throws MemcachedException, InterruptedException, TimeoutException, IOException {
		XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses("localhost:11211"));
		builder.setCommandFactory(new BinaryCommandFactory());
		builder.setCommandFactory(new KestrelCommandFactory());
		XMemcachedClient client = (XMemcachedClient) builder.build();

		client.setPrimitiveAsString(true);

		client.addServer("10.0.1.75:12000 10.0.1.76:12000");
		client.removeServer("10.0.1.75:12000 10.0.1.76:12000");

		// get operation
		String name = client.get("test");

		// set add replace append prepend gets
		client.add("hello", 0, "dennis");
		client.replace("hello", 0, "dennis");
		client.append("hello", " good");
		client.prepend("hello", "hello ");
		GetsResponse response = client.gets("hello");
		long cas = response.getCas();
		Object value = response.getValue();

		// incr decr
		client.set("a", 0, "1");
		client.incr("a", 4);
		client.decr("a", 4);

		// cas
		client.cas("a", 0, new CASOperation() {
			@Override
			public int getMaxTries() {
				return 1; // max try times
			}

			@Override
			public Object getNewValue(long currentCAS, Object currentValue) {
				System.out.println("current value " + currentValue);
				return 3; // return new value to update
			}
		});

		// flush_all
		client.flushAll();

		// stats
		Map<InetSocketAddress, Map<String, String>> result = client.getStats();

		// get server versions
		Map<InetSocketAddress, String> version = client.getVersions();

		// bulk get
		List<String> keys = new ArrayList<String>();
		keys.add("hello");
		keys.add("test");
		Map<String, Object> map = client.get(keys);
	}
常见问题

如果启动的协议是二进制的,必须在Spring配置文件指定(xmemcached默认的协议是:net.rubyeye.xmemcached.command.TextCommandFactory),不然会打印如下异常:

net.rubyeye.xmemcached.exception.MemcachedException: Session has been closed
    at net.rubyeye.xmemcached.impl.MemcachedTCPSession.destroy(MemcachedTCPSession.java:111)
    at net.rubyeye.xmemcached.impl.MemcachedHandler.onSessionClosed(MemcachedHandler.java:164)
    at com.google.code.yanf4j.core.impl.AbstractSession.onClosed(AbstractSession.java:306)
    at com.google.code.yanf4j.core.impl.AbstractSession.close(AbstractSession.java:294)
    at com.google.code.yanf4j.nio.impl.NioTCPSession.decode(NioTCPSession.java:311)
    at com.google.code.yanf4j.nio.impl.NioTCPSession.decodeAndDispatch(NioTCPSession.java:237)
    at com.google.code.yanf4j.nio.impl.NioTCPSession.readFromBuffer(NioTCPSession.java:207)
    at com.google.code.yanf4j.nio.impl.AbstractNioSession.onRead(AbstractNioSession.java:196)
    at com.google.code.yanf4j.nio.impl.AbstractNioSession.onEvent(AbstractNioSession.java:341)
    at com.google.code.yanf4j.nio.impl.SocketChannelController.dispatchReadEvent(SocketChannelController.java:56)
    at com.google.code.yanf4j.nio.impl.NioController.onRead(NioController.java:157)
    at com.google.code.yanf4j.nio.impl.Reactor.dispatchEvent(Reactor.java:323)
    at com.google.code.yanf4j.nio.impl.Reactor.run(Reactor.java:180)
常见问题会持续更新。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值