When we tried to use Infinispan – an in-memory data grid often used as a caching solution – for a not-quite-so-small cache use case in our codebase, we stumbled more than strictly necessary. This was of course because of our own inexperience but also because the Infinispan documentation isn’t very good at explaining some of the very basic stuff, so I will try to summarize what little knowledge I gained there…
There are basically three modes you can run Infinispan in: Remote (also called “HotRod”, which is the name of the protocol used there, or “Server/Client”), embedded and local.
Local mode is the most easy to explain, here it basically works as a very powerful map with a load of nice features like write-through, write-behind, eviction or expiration. So, if you need a “real” local cache beyond a basic map, this might be a good solution.
Remote mode is still very simple: It uses a tcp connection to connect to a separate Infinispan server (using the so called Hot Rod protocol) and basically queries this server for all your caching needs. Of course it also offers a “near” cache, basically caching stuff locally on the client-side, too, to reduce the amount of requests over the network. This is a very common use case, but, as we found out, provides only very limited features.
Embedded mode then means adding a whole Infinispan server/node into your application as a library, which then can become a part of an Infinispan cluster to share data, if needed. This is the most powerful mode to run in with the most features.
So, what cache mode do we need for a specific use case? That’s as much an architectural question as a technical one – we should also take data ownership and similar concepts into account – but let’s start with the more easy technical considerations:
If you only need a simple local cache with no connection to another application, obviously a simple map is most likely the way to go. If you need a few more features, for example you want to give a TTL (time-to-live) for your cache elements (without having to code it yourself) then a local Infinispan is definitely worth a look – but of course, let’s face it, there are a lot of other simple solutions that provide that, for example by using Google Guava’s CacheBuilder. So if you need that and already have something like this on your classpath, adding another dependency might be a bit overkill.
If you need to share a cache between multiple applications (including, but not limited to, instances of the same application), Infinispan in remote or embedded mode is a possible solution.
If your shared cache has a very basic use case, sharing the same elements between all applications, remote mode is totally fine: Start an Infinispan server, for example via docker, and connect to it via a Hot Rod client. You can also add near caching to this solution to optimize a bit between memory and network usage.
If your data sharing gets more complicated – for example a distributed cache where you want to decide which node has the ownership for a certain key – or you want to tie your cache deeper into the application – for example with listeners that are called as a part of the cache’s synchronous writes – then embedded mode is the solution for you, basically making a node of infinispan a part of your application.
When we get further, I will probably add more postings with basic stuff about Infinispan. I can also recommend the Live Online Training “Microservice Caching Strategies” by Mark Richards over at O’Reilly (if you already have an account) which provides some basic information about caching in general (though nothing Infinispan specific, since there are of course other solutions as well).