MemCachier Now Recommends XMemcached for Java
If you’re using Memcache in Java, chances are you’re using the SpyMemcached client. It has been the most popular Java client for years. Unfortunately, at MemCachier we have had a lot of customer reports about problems with SpyMemcached. For this reason we now recommend to use XMemcached with Java.
What’s wrong with SpyMemcached?
The short answer is, we don’t really know. We got a lot of reports that hint at a race condition but we were never able to reproduce the problems consistently. The only reproducible issue we found was that SpyMemcached does not attempt to reconnect if a connection was terminated remotely. Sometimes we need to move customers to a different server (e.g., when a machine fails). In such cases SpyMemcached would not reconnect until the application was restarted. This issue definitely warrants a bug report and a fix. However, by the time we discovered it we already decided to switch to XMemcached due to the number of problem reports we have been getting.
How do I use XMemcached?
To use XMemcached with Maven you need to add the xmemcached
library to
your dependencies in your pom.xml
file:
dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.4.3</version>
<dependency> </
If you’re using Gradle then add the following to build.gradle
:
repositories {
mavenCentral()
}
dependencies {
implementation 'com.googlecode.xmemcached:xmemcached:2.4.3'
}
Once your build system is configured, you can start adding caching to your Java app:
import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
import net.rubyeye.xmemcached.auth.AuthInfo;
import net.rubyeye.xmemcached.command.BinaryCommandFactory;
import net.rubyeye.xmemcached.exception.MemcachedException;
import net.rubyeye.xmemcached.utils.AddrUtil;
import java.lang.InterruptedException;
import java.net.InetSocketAddress;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeoutException;
public class App {
public static void main( String[] args ) {
List<InetSocketAddress> servers =
.getAddresses(System.getenv("MEMCACHED_SERVERS").replace(",", " "));
AddrUtil=
AuthInfo authInfo .plain(System.getenv("MEMCACHED_USERNAME"),
AuthInfoSystem.getenv("MEMCACHED_PASSWORD"));
= new XMemcachedClientBuilder(servers);
MemcachedClientBuilder builder
// Configure SASL auth for each server
for(InetSocketAddress server : servers) {
.addAuthInfo(server, authInfo);
builder}
// Use binary protocol
.setCommandFactory(new BinaryCommandFactory());
builder// Connection timeout in milliseconds (default: )
.setConnectTimeout(1000);
builder// Reconnect to servers (default: true)
.setEnableHealSession(true);
builder// Delay until reconnect attempt in milliseconds (default: 2000)
.setHealSessionInterval(2000);
builder
try {
= builder.build();
MemcachedClient mc try {
.set("foo", 0, "bar");
mcString val = mc.get("foo");
System.out.println(val);
} catch (TimeoutException te) {
System.err.println("Timeout during set or get: " +
.getMessage());
te} catch (InterruptedException ie) {
System.err.println("Interrupt during set or get: " +
.getMessage());
ie} catch (MemcachedException me) {
System.err.println("Memcached error during get or set: " +
.getMessage());
me}
} catch (IOException ioe) {
System.err.println("Couldn't create a connection to Memcached server: " +
.getMessage());
ioe}
}
}
The environment variables MEMCACHED_SERVERS
, MEMCACHED_USERNAME
, and
MEMCACHED_PASSWORD
contain a list of comma separated server addresses, your
username, and password. If you use MemCachier as
your memcached provider you can find these values in the cache overview page.
For more information such as how to use XMemcached with Spring Boot please consult our documentation.