Memcached Notes: XMemcached&Spring Integration

Links to the original text: https://my.oschina.net/mohaiyong/blog/221285
Memcached Java Client, using XMemcached 1.3.5, does a simple test and describes how to integrate with Spring.

Related links:
Memcached Notes (1) Installation & Conventional Errors & Monitoring
Memcached Notes (2) XMemcached & Spring Integration
Memcached Notes (3) Summary of Memcached Use
Memcached Notes --(4) Dealing with High Concurrency Attacks


A Brief Introduction to Memcached Client
There are currently three types of Memcached Client:

These three Client s have been controversial:
  • Memcached Client for Java is more stable, earlier and wider than SpyMemcached.
  • SpyMemcached is more efficient than Memcached Client for Java.
  • XMemcached is better than SpyMemcache d for concurrency.


Speaking in terms of data, referring to official performance comparisons:
Memcached Client for Java: https://github.com/gwhalin/Memcached-Java-Client/wiki/PERFORMANCE
XMemcached: http://xmemcached.googlecode.com/svn/trunk/benchmark/benchmark.html

II. XMemcached Characteristics
XMemcached features:
  • High Performance
  • Support complete memcached text protocol, binary protocol.
  • JMX is supported by adjusting performance parameters through MBean, dynamically adding/removing server s, viewing statistics, etc.
  • Support client statistics
  • Support the dynamic increase and decrease of memcached nodes.
  • Support memcached distribution: residue distribution and consistent hash distribution.
  • More performance tuning options.

In addition, XMemcached is easier to integrate with Spring. What's more, it belongs to the originality of China!  

3. Simple Implementation of XMemcached

MemcachedClientBuilder is the core interface of MemcachedClient, which controls the construction (build() method) and shutdown() method of Client.
XMemcachedClientBuilder configures address lists by constructing methods, and usually configures weights. The code is as follows:
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;
	}

But if you use this(), you can save some code and add some comments.
In addition, you need to set the connection pool size, use binary protocol / text protocol and so on.
Obtained by the build() method MemcachedClient
Then you can set, get, replace, delete and other Memcached operations through Memcached!
Code:
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 });
		
		// Set the connection pool size, that is, the number of clients
		builder.setConnectionPoolSize(50);

		// Outage alarm
		builder.setFailureMode(true);

		// Using binary files
		builder.setCommandFactory(new BinaryCommandFactory());

		MemcachedClient memcachedClient = null;
		try {
			memcachedClient = builder.build();
			try {
				// Setting/Getting
				memcachedClient.set("zlex", 36000, "set/get");
				assertEquals("set/get", memcachedClient.get("zlex"));

				// replace
				memcachedClient.replace("zlex", 36000, "replace");
				assertEquals("replace", memcachedClient.get("zlex"));

				// remove
				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();
				}
			}
		}
	}
}

IV. Integration of XMemcached and Spring
The integration of XMemcached and Spring can be referred to. http://code.google.com/p/xmemcached/wiki/Spring_Integration Here we will only talk about the most commonly used methods.
memcached.properties do the basic configuration:
#Connection pool size is the number of clients
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 Profile:
<?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>


There memcachedClientBuilder node completion Memcached Client Builder, and then through memcachedClient node configuration factory-method, call Generation of build() method of MemcachedClientBuilder MemcachedClient, and configuration destroy-method closes.
But I still wonder, who will handle the anomalies here? Spring container? Or do you need another proxy Bean to wrap it?

With Spring container support, we do not need to configure in code, nor do we need to repeatedly call build() and shutdown() methods, which are handed over to Spring to complete.
The code is as follows:
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 {
			// Setting/Getting
			memcachedClient.set("zlex", 36000, "set/get");
			assertEquals("set/get", memcachedClient.get("zlex"));

			// replace
			memcachedClient.replace("zlex", 36000, "replace");
			assertEquals("replace", memcachedClient.get("zlex"));

			// remove
			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();
		}
	}
}


Related links:
Memcached Notes (1) Installation & Conventional Errors & Monitoring
Memcached Notes (2) XMemcached & Spring Integration
Memcached Notes (3) Summary of Memcached Use
Memcached Notes --(4) Dealing with High Concurrency Attacks


XMemcached User Guide

Reproduced in: https://my.oschina.net/mohaiyong/blog/221285

Keywords: Java Spring Junit xml

Added by ssmitra on Mon, 09 Sep 2019 08:31:52 +0300