Monday, 29 January 2018

Back from Snowcamp 2018



This week, I'm recovering from the Snowcamp 2018 conference in Grenoble. I had an amazing time there, where I could hang-out with people from the french community, discussing tech, coding, non-blocking APIs, lifestyle and diversity!

My talk was on Thursday at 15:00. It was very exciting for me because I was live-coding in front of so many people for the first time! I got very valuable feedback from attendees and speakers to improve my content, live-coding skills and encouragements to submit this talk to other user groups and conferences this year.



This presentation focuses on the work we have been doing to provide a new API available in Infinispan 9.2 (final release coming very very soon!!!): Clustered Locks. These locks are distributed and non blocking, allowing us to synchronise protected code between different Infinispan nodes across a cluster.

It's a 45 minutes talk, so I'm not presenting the API just from the user point of view; instead I go deep into the actual Clustered Locks internals. We have built this first implementation on top of existing Infinispan's APIs, which proves that they can be used to do much more than just speeding your applications and caching!

The first user of these locks is the Vert.x-Infinispan Cluster Manager. Before going into the implementation details, I show how to create a cluster of Vert.x applications using Infinispan and a simple example of when and how to use a Vert.x Lock. Underneath Vert.x Locks, the next release of the cluster manager will be using the Clustered Locks API. I'm preparing a longer article on this matter, so stay tuned! Meanwhile, enjoy the presentation slides!

Wednesday, 24 January 2018

What happened to the replication queue?

Recently I saw an Infinispan user that was having issues using the replication queue, a clustering functionality that had been part of Infinispan since it's first release. Looking at the latest Infinispan codebase I realised it wasn't there any more, what happened to it?

The aim of the replication queue was to batch individual cache operations and send them as one to other nodes, rather than sending them each operation individually.

Over time we started considering whether the replication queue could be removed:

  1. The replication queue was duplicating functionality: JGroups, which manages the group communication layer, already bundles messages and the network stack can do it too.
  2. Using the replication queue was not more efficient because when the message is delivered in the remote node, the messages are processed sequentially. If processing first message blocks, the other commands are not processed until it finishes.
  3. It can add complexity if messages with different order requirements come in same batch, e.g. no order, FIFO or total.
In essence, Infinispan's replication queue was doing the same as JGroups' message bundler. Whereas JGroups' message bundler had been evolving and different options had been developed, Infinispan's replication queue was still using same algorithm as in its first release.

So in Infinispan 8.2 the replication queue was deprecated and in 9.0 it was finally removed. If you ever find the need to batch your changes, configure JGroups' message bundler.

Cheers,
Galder

Monday, 22 January 2018

Infinispan coming to Snowcamp 2018



This week, the 25th of January, I will be presenting a talk about Clustered Locks at the Snowcamp 2018 conference in Grenoble (France). During the live-coding talk, I will share the design and code I've been working on to create this first version of the clustered locks. These locks will be used by the Vert.x Cluster Manager, but they can be useful to any Infinispan user since version 9.2 (final release coming very soon!!). If you are planning to use this API, we would love to hear from you to give us some feedback and keep us posted on your use case!

If you are attending the conference, fell free to reach me to discuss about Infinispan+Vert.x, locks, Multimap, cute names or any other topic that you care about!

See you!

Katia

Friday, 19 January 2018

First candidate release for Infinispan 9.2.0 is out!

Infinispan 9.2.0.CR1 is out! The Infinispan team took time off over the festive period but in spite of that we managed to pack in quite a bit as we approach Infinispan 9.2.0 final release.

Here are the highlights:

  • Remove listener in embedded only fired when something is actually removed - ISPN-8585.
  • CacheNotFoundException ERROR message in server was deemed too noisy, so it was changed to DEBUG message. If RemoteCacheManager.getCache() returns null, the cache does not exist - ISPN-8579.
  • Infinispan is now compatible with JCache 1.1 - ISPN-8571.
  • Hibernate 5.2 compatible Infinispan cache provider (on top of Hibernate 5.1 compatible provider) - ISPN-8570.
  • Documentation added on how to use Hibernate 5.2 and 5.1 Infinispan cache providers shipped with Infinispan 9.2.
Full details of the new features and enhancements included in this release can be found here.
Thank you for following us and stay tuned!

Cheers,
Galder

Easier Infinispan clusters on same JVM with Infinispan 9.2

Since Infinispan 5.2.0, Infinispan registers JMX MBeans by default even if statistics are disabled. This was done so that management related operations could be called even if statistics were disabled.

This change resulted in a small usability problem for those users that wanted to create a cluster of Infinispan instances on the same JVM. This is a very common use case when first starting to use Infinispan or when trying to create some unit tests.

When multiple Infinispan instances run on same JVM, they would all try to register JMX MBeans but unless you explicitly gave each Infinispan instance a different CacheManager name, you'd see exceptions like this:

Caused by: org.infinispan.jmx.JmxDomainConflictException: ISPN000034: There's already a JMX MBean instance type=Cache,name="___defaultcache(repl_sync)",manager="DefaultCacheManager" already registered under 'org.infinispan' JMX domain...

Starting with Infinispan 9.2.0, duplicate JMX domains are allowed by default, so you won't need to fiddle with JMX domain settings any more to create an Infinispan cluster on the same JVM :)

Cheers,
Galder

Monday, 8 January 2018

Improving collect() for distributed Java Streams in Infinispan 9.2

As we progress with the release of Infinispan 9.2 pre-releases, it's important to highlight some of the more interesting improvements from an end-user perspective.

As mentioned before, Infinispan Distributed Java Streams can be used to calculate analytics over existing data. Through overloading of methods, Infinispan is able to offer a simple way of passing lambdas that are made to be Serializable without the need of explicit casting. Being able to produce binary formats for the lambdas is an important step for java streams executions to be distributed. In this example, the cached values are being filtered to find those that have a delay bigger than 0. This lambda can be safely distributed without the need to cast to Serializable because values().stream() returns org.infinispan.CacheStream that overloads filter to take a SerializablePredicate:

Cache<String, Stop> cache = ...
cache.values().stream()
  .filter(e -> e.delayMin > 0);

However, there was one area which was still a bit clunky to use: Java Collectors. When Java Streams came out, the JDK provided a class called java.util.stream.Collectors which includes a lot of helper methods for collecting results after stream processing. The problem with the Collector instances returned by the helper methods is that they're not Serializable.

Before Infinispan 9.2, we worked around this problem with the help of org.infinispan.stream.CacheCollectors which defined a serializableCollector method that took a SerializableSupplier<Collector<T, ?, R>>. The aim here was this: even if the Collector instance is not Serializable, the function that creates the Collector can be made to be Serializable. It could be used this way:

Cache<String, Stop> cache = ...
cache.values().stream().collect(
  CacheCollectors.serializableCollector(() -> Collectors.groupingBy(
      e -> getHourOfDay(e.departureTs),
      Collectors.counting()
)));

Although this worked, it was a clunky, so in Infinispan 9.2 we overloaded collect() in org.infinispan.CacheStream to take SerializableSupplier<Collector<T, ?, R>>. This means that in Infinispan 9.2, the code above can be written like this instead:

Cache<String, Stop> cache = ...
cache.values().stream().collect(
  () -> Collectors.groupingBy(
      e -> getHourOfDay(e.departureTs),
      Collectors.counting()
));

This is a cleaner way of making sure Collector instances returned by java.util.stream.Collectors can be distributed.

Cheers,
Galder