Non-Stop Client with Near Cache

Imagine a client-server system that involves reading values from a data store. In the event of a connection failure with the server, the system will not be reading values. The consequences of such an event might be quite significant, including potentially costing money for a financial institution or time for a time-critical operation. If a solution might be able to continue to supply data for read operations during such a period, the situation would have been handled comfortably. With Hazelcast’s new feature Non-Stop Client with Near Cache, a Hazelcast client can return data from its Near Cache even though it is disconnected from a cluster. In this post, we will go through the concept and look at some examples in Java. Please note that Hazelcast also has clients in C++, .NET, Python, Node.js, Go, and Scala.

Before jumping into the details of a Non-Stop Client, let’s step back and review what Near Cache in Hazelcast means.

What is Near Cache?

In distributed systems, local operations are less costly than remote ones. Therefore systems are designed to have a higher local/remote operations ratio. Near Cache is a feature that can increase this ratio.

Near Cache is a local cache that stores recently or frequently accessed data. It is closer to the application, hence a better alternative to read data.

If data is not present in the Near Cache, it will be populated. Next time the application retrieves data that has already been cached, the Near Cache will be the one that returns the result.

The main tradeoff with the Near Cache is that it carries the memory cost of updating the values of objects along with the cache invalidations. If the values of objects change more frequently, memory cost will be higher. Thus, if your application has a high read/write ratio, using Near Cache is advantageous.

You can check our Reference Manual for an example configuration of Near Cache for a client.

Setting Up a Non-stop Client with Near Cache

With the recent changes in Hazelcast IMDG 4.0, client-cluster connection and client ownership have a new design. Moving forward, clients are “ownerless” and their connection and authentication to the cluster will be easier.

In Hazelcast, when a client disconnects from a server, it has three options: on, off or async. On enables reconnection but blocks all waiting invocations during the phase of re-establishment. Off disables the reconnection. Async also enables the reconnection but it does not block the operations and sends an exception to the waiting invocations about the client being offline. More details and configuration can be found in the Java Client Connection Strategy.

Now let’s check out the code snippet below to see a basic example.

Configuration

It takes only a few lines of code for everything we need. First, we create a member and a client. Then, we adjust the configuration for reconnection and near-cache so that we can benefit from the non-stop client capabilities.

HazelcastInstance member = Hazelcast.newHazelcastInstance();

ClientConfig config = new ClientConfig();
config.getConnectionStrategyConfig().setReconnectMode(ClientConnectionStrategyConfig.ReconnectMode.ASYNC);
config.getConnectionStrategyConfig().getConnectionRetryConfig().setClusterConnectTimeoutMillis(Integer.MAX_VALUE);

NearCacheConfig nearCacheConfig = new NearCacheConfig("map");
config.addNearCacheConfig(nearCacheConfig);

HazelcastInstance client = HazelcastClient.newHazelcastClient(config);

In case of a shutdown of a server, crash or a disconnection issue with the cluster, the client with Near Cache will continue to serve with the latest version of values. The reconnection process will not be blocking applications to retrieve data if it is stored in the Near Cache. Isn’t it very cool? 🙂

As the last step, let’s verify together that our non-stop client works as we expected.

We’ll create and fill a map with values. After the map is ready, we’ll populate Near Cache by calling values from the map. Then, we’ll shut down the member and make our client disconnected. Even in this case, the non-stop client should allow us to continue reading data from the cache.

IMap<Object, Object> map = client.getMap("map");

for (int i = 0; i < 100; i++) {
    map.put(i, i);
}

//populate near cache
for (int i = 0; i < 100; i++) {
    map.get(i);
}

member.shutdown();

//verify the availability of Near Cache data while client is disconnected
for (int i = 0; i < 100; i++) {
    if (!map.get(i).equals(i)) {
        throw new IllegalStateException();
    }
    else{
        System.out.println("Reading from non-stop near cache: " + map.get(i));
    }
}

//verify that if client asks for an unavailable key, we get offline exception immediately
try {
    map.get(200);
} catch (HazelcastClientOfflineException offlineException) {
    System.out.println("EXPECTED exception");
}

// verify that if client tries to write, we get offline exception immediately
try {
    map.put(1, 2);
} catch (HazelcastClientOfflineException offlineException) {
    System.out.println("EXPECTED exception");
}

client.shutdown();

That’s it! We have reviewed how Hazelcast clients can continue reading data from the Near Cache even if the connection with the server is lost. Please don’t hesitate to reach out to us through Hazelcast Community channels if you have any feedback!