Question

I add to servers to xmemcached and try to set a few items. I get this exception

bar
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:371)
at java.util.ArrayList.get(ArrayList.java:384)
at net.rubyeye.xmemcached.impl.ArrayMemcachedSessionLocator.getSessionByKey(ArrayMemcachedSessionLocator.java:67)
at net.rubyeye.xmemcached.impl.MemcachedConnector.findSessionByKey(MemcachedConnector.java:570)
at net.rubyeye.xmemcached.impl.MemcachedConnector.send(MemcachedConnector.java:487)
at net.rubyeye.xmemcached.XMemcachedClient.sendCommand(XMemcachedClient.java:288)
at net.rubyeye.xmemcached.XMemcachedClient.fetch0(XMemcachedClient.java:617)
at net.rubyeye.xmemcached.XMemcachedClient.get0(XMemcachedClient.java:1030)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:988)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:999)
at net.rubyeye.xmemcached.XMemcachedClient.get(XMemcachedClient.java:1021)
at AxCacheEngine.Libs.AxMemcached.main(AxMemcached.java:33)

Here's the code:

MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(
            "127.0.0.1:11211 127.0.0.1:11311"
    ));
builder.setSessionLocator(new ArrayMemcachedSessionLocator(HashAlgorithm.ONE_AT_A_TIME));

MemcachedClient memcachedClient = builder.build();
System.out.println("Trying to get 1 milllion items");

int hugeItems = 0;
int normalItems = 0;
int totalCount = 0;

System.out.println(memcachedClient.set("foo",0,"bar"));
System.out.println(memcachedClient.set("bar",0,"baz"));
System.out.println(memcachedClient.set("yin",0,"yang"));

What could be the problem? Is there some issue with distribution strategy? I get this error when I try to get the items set from php-memcached. Please help

Was it helpful?

Solution

I replicated your issue and I think that you cannot use the ArrayMemcachedSessionAllocator with the One at a Time hashing algorithm for 2 or more sessions.

According to the documentation the ArrayMemcachedSessionAllocator class locates Sessions as hash(key) mod sessions.size().

And this number will be an index of an Arraylist in the code. In particular, this is the guilty line:

long start = this.getHash(size, key); //gets computed by ONE_AT_A_TIME hash % number of sessions
List<Session> sessions = sessionList.get((int) start); //this is where you get out of bounds

The problem is that ONE_AT_A_TIME hash can be negative. It is negative for bar (the source of the problem).

So if you have a negative hash value modulo 2 (number of servers), start is a negative value too.

On the other hand, foo has a positive hash value for One_At_a_Time and modulo 2 remains a positive value!

Note: The algorithm works perfectly fine if you have one server (as any number % 1 is positive).

So, I think you just can't use this hashing algorithm with the ArrayMemcachedSessionAllocator class for 2 or more servers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top