Blogs The Grouping API

The Grouping API

Infinispan 5 CR4 (and above) includes a new Grouping API. You can read more in the documentation, but I’ll introduce it quickly for you here.

In some cases you may wish to co-locate a group of entries onto a particular node. In this case, the group API will be useful for you.

How does it work?

Infinispan allocates each node a portion of the total hash space. Normally, when you store an entry, Infinispan will take a hash of the key, and store the entry on the node which owns that portion of the hash space. Infinispan always uses an algorithm to locate a key in the hash space, never allowing the node on which the entry is stored to be specified manually. This scheme allows any node to know which nodes owns a key, without having to distribute such ownership information. This reduces the overhead of Infinispan, but more importantly improves redundancy as there is no need to replicate the ownership information in case of node failure.

If you use the grouping API , then Infinispan will ignore the hash of the key when deciding which node to store the entry on, and instead use a hash of the group. Infinispan still uses the hash of the key to store the entry on a node. When the group API is in use, it is important that every node can still compute, using an algorithm, the owner of every key. For this reason, the group cannot be specified manually. The group can either be intrinsic to the entry (generated by the key class) or extrinsic (generated by an external function).

How can I use it?

If you can alter the key class, and the determination of the group is not an orthogonal concern to the key class, then you can simply annotate a method on the key class that will provide the group. For example

class User {

   ...
   String office;
   ...

   int hashCode() {
      // Defines the hash for the key, normally used to determine location
      ...
   }

   // Override the location by specifying a group, all keys in the same
   // group end up with the same owner
   @Group
   String getOffice() {
      return office;
   }

}

Of course, you need to make sure your algorithm for computing the key is consistent, and always returns the same group for a key!

Alternatively, if you can’t modify the key class, or determination of the group is an orthogonal concern, you can externalise computation of the group to an "interceptor style" class, called a "Grouper". Let’s take a look an example of a Grouper:

class KXGrouper implements Grouper {

    // A pattern that can extract from a "kX" (e.g. k1, k2) style key
   static Pattern kPattern = Pattern.compile("(^k)(\\d)$");

    String computeGroup(String key, String group) {
        Matcher matcher = kPattern.matcher(key);
        if (matcher.matches()) {
            String g = Integer.parseInt(matcher.group(2)) % 2 + "";
            return g;
        } else
            return null;
    }

    Class getKeyType() {
        return String.class;
    }

}

Here, we’ve had to use a grouper, as we cannot modify the key class (String). Our group is still based upon the key, and established by extracting a part of the key.

Of course, you need to enable grouping support in Infinispan, and configure any groupers. The reference documentation will help you here.

Get it, Use it, Ask us!

We’re hard at work on new features, improvements and fixes, so watch this space for more announcements!

Please, download and test the latest release.

The source code is hosted on GitHub. If you need to report a bug or request a new feature, look for a similar one on our JIRA issues tracker. If you don’t find any, create a new issue.

If you have questions, are experiencing a bug or want advice on using Infinispan, you can use GitHub discussions. We will do our best to answer you as soon as we can.

The Infinispan community uses Zulip for real-time communications. Join us using either a web-browser or a dedicated application on the Infinispan chat.