
At work, we’re currently using the open source version of ehcache in our apps. In our next software stack refresh we’ve talked about investigating a distributed caching framework. I think that Hazelcast might be a contender. I like that it allows you to store date in simple Lists, Sets, Maps, and Queues and handles the distributed part for you. The question we’ll need to answer at work is “how tunable is Hazelcast?”
From the website:
- Distributed java.util.{Queue, Set, List, Map}
- Distributed java.util.concurrency.locks.Lock
- Distributed java.util.concurrent.ExecutorService
- Distributed MultiMap for one to many mapping
- Distributed Topic for publish/subscribe messaging
- Distributed Indexing and Query support
- Transaction support and J2EE container integration via JCA
- Socket level encryption for secure clusters
- Write-Through and Write-Behind persistence for maps
- Java Client for accessing the cluster remotely
- Dynamic HTTP session clustering
- Support for cluster info and membership events
- Dynamic discovery
- Dynamic scaling
- Dynamic partitioning with backups
- Dynamic fail-over
- Web-based cluster monitoring tool
Here are some code snippets from the website:
Map
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import java.util.concurrent.ConcurrentMap;
public class DistributedMap {
public static void main(String[] args) {
Config config = new Config();
HazelcastInstance h = Hazelcast.newHazelcastInstance(config);
ConcurrentMap<String, String> map = h.getMap("my-distributed-map");
map.put("key", "value");
map.get("key");
//Concurrent Map methods
map.putIfAbsent("somekey", "somevalue");
map.replace("key", "value", "newvalue");
}
}
MultiMap
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.MultiMap;
import java.util.Collection;
public class DistributedMultiMap {
public static void main(String[] args) {
Config config = new Config();
HazelcastInstance h = Hazelcast.newHazelcastInstance(config);
MultiMap<String, String> multiMap = h.getMultiMap("my-distributed-multimap");
multiMap.put("key", "value1");
multiMap.put("key", "value2");
multiMap.put("key", "value3");
Collection<String> values = multiMap.get("key");
// remove specific key/value pair
multiMap.remove("key", "value2");
}
}
Queue
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class DistributedQueue {
public static void main(String[] args) throws InterruptedException {
Config config = new Config();
HazelcastInstance h = Hazelcast.newHazelcastInstance(config);
BlockingQueue<String> queue = h.getQueue("my-distributed-queue");
queue.offer("item");
String item = queue.poll();
//Timed blocking Operations
queue.offer("anotheritem", 500, TimeUnit.MILLISECONDS);
String anotherItem = queue.poll(5, TimeUnit.SECONDS);
//Indefinitely blocking Operations
queue.put("yetanotheritem");
String yetanother = queue.take();
}
}
Topic
import com.hazelcast.config.Config;
import com.hazelcast.core.*;
public class DistributedTopic implements MessageListener<String> {
public static void main(String[] args) {
Config config = new Config();
HazelcastInstance h = Hazelcast.newHazelcastInstance(config);
ITopic<String> topic = h.getTopic("my-distributed-topic");
topic.addMessageListener(new DistributedTopic());
topic.publish("Hello to distributed world");
}
@Override
public void onMessage(Message<String> message) {
System.out.println("Got message " + message.getMessageObject());
}
}
Lock
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import java.util.concurrent.locks.Lock;
public class DistributedLock {
public static void main(String[] args) {
Config config = new Config();
HazelcastInstance h = Hazelcast.newHazelcastInstance(config);
Lock lock = h.getLock("my-distributed-lock");
lock.lock();
try {
//do something here
} finally {
lock.unlock();
}
}
}
Executor Service
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IExecutorService;
import com.hazelcast.core.Member;
import java.io.Serializable;
public class DistributedExecutorService {
public static void main(String[] args) {
Config config = new Config();
HazelcastInstance h = Hazelcast.newHazelcastInstance(config);
IExecutorService ex = h.getExecutorService("my-distributed-executor");
ex.submit(new MessagePrinter("message to any node"));
Member firstMember = h.getCluster().getMembers().iterator().next();
ex.executeOnMember(new MessagePrinter("message to very first member of the cluster"), firstMember);
ex.executeOnAllMembers(new MessagePrinter("message to all members in the cluster"));
ex.executeOnKeyOwner(new MessagePrinter("message to the member that owns the following key"), "key");
}
static class MessagePrinter implements Runnable, Serializable {
final String message;
MessagePrinter(String message) {
this.message = message;
}
@Override
public void run() {
System.out.println(message);
}
}
}