I took some time not that long ago to compare some distributed caching frameworks in Java. In this blog post I’d like to go over some of those findings. I compared different features and ran them through a set of tests against the records in Wombats test database. These are my own opinions.
Comparisons of different products
|Apache Ignite||- easy to set up - can specify which node to store data on - no custom marshaller needed||- no Hibernate 5 support yet - slower development|
|Redisson||- more configuration needed to get set up - Hibernate 5 support - Redis 3 cluster support||- very slow L2 Hibernate cache - no local cache support|
|Hazelcast||- easy to set up - Hibernate 5 support - distributed data structures||- need to write custom serializers for each cached class - only commercial support for off-heap storage|
|Terracota||- Hibernate 5 support||- not well documented - limited non-commercial functionality|
|Infinispan||- Hibernate 5 support - active development||- not as many features as Hazelcast|
I focused my testing around Hibernate L2 caching and Spring method level caching with JCache. For the tests, I ran a series of tests storing the cached data locally (embedded mode) and remotely on the cache server. Most of the products recommend local cache mode for Hibernate caching.
Hibernate L2 Caching
- similar to embedded mode where the data is stored locally on the JVM and isn’t distributed. Each server has it’s own copy of the data and isn’t shared.
- any updates to cached entries will send an invalidate message to other caches
- testing showed faster performance with local caches than remotely distributed.
Below is a list of the different tests that were run and a description.
|Test||Description||Hibernate L2 Test||Spring Method Test|
|FindRolePermissionNotInCache – QueryCache||Find Role by Name where its not already in the cache||x|
|FindRolePermissionInCache – QueryCache||Find Role by Name where its already in the cache||x|
|SaveUserMethodCache||Save a user||x|
|UpdateUserMethodCache||update a user||x|
|HibernateL2UserSave||save a user||x|
|HibernateL2UserUpdate||update a user||x|
|HibernateL2UserFind||find a user||x|
|HibernateRoleFindNotInCache||Find a User role by name not already in cache||x|
|HibernateRoleFindInCache||find role by name where in cache||x|
|GetAllUsersL2||get all users for company (query cache)||x|
|GetAllUsers||get all users for company||x|
|Distributed (2 client Test)||find 10,000 users across 2 distributed nodes|
|Distributed (4 client Test)||find 10,000 users across 4 distributed nodes|
|CompanyL2Find||find company by id||x|
|GetAllL2Find – 27k id lookup cached||find cached users by id||x|
The two caching frameworks that seemed to have the best performance for the types of scenarios they would be used for were Hazelcast and Infinispan. Both products were easy to set up and provide good documentation along with a nice set of features.