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
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.