In a broad, distributed cluster of data storage, it is very useful to be able to know what is happening with our data, either to trigger an application-level response to an event, or to purely give us some visibility to the internal goings-on. In this chapter, we will learn about:
Creating and using collection listeners
Instance, lifecycle, and cluster membership listeners
Partition migration listener
Listening to the goings-on
One great feature of Hazelcast is its ability to notify us of the goings-on of our persisted data and the cluster as a whole. To allow us to register an interest in events, the listener concept is borrowed from Java. In that way, there are a number of listener interfaces that we can implement to receive, process, and handle different types of events; one of which we have previously encountered.
Collection listeners
EntryListener
for map-based (IMap
and MultiMap
) events
ItemListener
for flat collection-based (IList
, ISet
, and IQueue
) events
MessageListener
for receiving topic events, but as we've seen before, it is used as part of the standard operation of topics
Cluster listeners
InstanceListener
for collection, creation, and destruction events
MembershipListener
for cluster membership events
LifecycleListener
for local node state events
MigrationListener
for partition migration state events
The sound of our own data
Being notified as our data changes can be rather useful, so we can make an application-level decision on whether that change is important or not. The first interface we are going to look at is EntryListener
. This class will notify us when changes are made to the entries stored in a map collection. If we take a look at the interface, we can see four event types that we will be notified about.
Hopefully, the first three are pretty self-explanatory; however, the last is a little less clear and in fact, one of the most useful. The entryEvicted
method is invoked when an entry is removed from a map non-programmatically (that is, Hazelcast has done it all by itself). This instance will occur in one of two...
Programmatic configuration ahead of time
So far the extra configurations we have applied have either been by customizing the hazelcast.xml
file, or retrospectively modifying a collection in the code. But what if we want to programmatically configure Hazelcast, without the race condition we discovered earlier? Fortunately, there is such a way. By creating an instance of the Config
class, we can configure the appropriate behavior on it using a similar hierarchy to the XML configuration, but in code. Before passing this configuration object over to the instance creation method, the previous example could be reconfigured to do so.
Events unfolding in the wider world
Now that we can determine what is going on with our data within the cluster, we might wish to have a degree of visibility of the state of the cluster itself. We could use this to trigger application-level responses to cluster instability, or provide mechanisms to enable graceful scaling. We are provided with a number of interfaces for different types of cluster activity. All of these listeners can be configured retrospectively as we have seen in our previous examples; however, in production, it would be better to configure them in advance for the same race condition reasons as the collection listeners. We can either do this using the hazelcast.xml
configuration or by using the Config
class.
The first of these, InstanceListener
, simply notifies all the nodes in the cluster as to new collection instances...
Moving data around the place
The final listener is very useful as it lets our application know when Hazelcast is rebalancing the data within the cluster. This allows us the opportunity to prevent or even block the shutdown of a node as we might be in a period of increased data resilience risk. The interface used for this case is MigrationListener
and will notify our application as partitions are migrated from one node to another and when they have completed.
In registering this cluster listener in our example application...
Unlike some of its peers, Hazelcast allows us to witness first hand a lot of internal state information. By registering listeners to be notified as events occur, we can further enhance our application not only in terms of functionality but also in resilience. By allowing our application to know when and what events are unfolding underneath it, we can add defensiveness to it—embracing the dynamic and destroyable nature of modern agile approaches to applications and infrastructure.
In the next chapter, we will move a little away from just data, and look at the distributed execution and task processing capabilities on offer.