Hazelcast: Java Open Source In-Memory Data Grid

Hazelcast logo

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);
        }
    }
}