Split-Brain handling is internally supported as a service inside Hazelcast (see Network Partitioning for more details) and JCache
uses same infrastructure with IMap
to support Split-Brain. You can specify cache merge policy to determine which entry is used while merging. You can also provide your own cache merge policy implementations through CacheMergePolicyInterface
.
NOTE: Split-Brain is only supported for heap based JCache but not for HD-JCache since merging high volume of data in consistent way may cause significant performance loss on the system.
CacheMergePolicy
InterfaceAfter split clusters are joined again, they merge their entries with each other. This merge process is handled over the CacheMergePolicy
interface.
The CacheMergePolicy
instance takes two entries: the owned entry, and the merging entry which comes from the joined cluster. The CacheEntryView
instance wraps the key, value, and some metadata about the entry (such as creation time, expiration time and access hit). Then the CacheMergePolicy
instance selects one of the entries and returns it.
The returned entry is used as the stored cache entry.
CacheEntryView
Wraps key, value and some metadata (such as expiration time, last access time and access hit of cache entry) and exposes them to outside as read only.
CacheMergePolicy
Policy for merging cache entries. Entries from joined clusters are merged by using this policy to select one of them from source and target.
Passed CacheEntryView
instances wrap the key and value as their original types, with conversion to object from their storage types.
If the user doesn't need the original types of key and value, you should use StorageTypeAwareCacheMergePolicy
which is a sub-type of this interface.
StorageTypeAwareCacheMergePolicy
Marker interface indicating that the key and value wrapped by CacheEntryView
will be not converted to their original types.
The motivation of this interface is that while merging cache entries, actual key and value are not usually not checked. Therefore, there is no need to convert them to their original types.
At worst case, value is returned from the merge method as selected, meaning that in all cases, value is accessed. So even if the the conversion is done as lazy, it will be processed at this point. But by default, key and value are converted to their original types unless this StorageTypeAwareCacheMergePolicy
is used.
Another motivation for using this interface is that at the server side, there is no need to locate classes of stored entries. It means that entries can be put from the client with BINARY
in-memory format and the classpath of the client can be different from the server. So in this case, if entries try to convert to their original types while merging, ClassNotFoundException
is thrown here.
As a result, both for performance and for the ClassNotFoundException
mentioned above, it is strongly recommended that you use this interface if the original values of key and values are not needed.
There are four built-in cache merge policies:
com.hazelcast.cache.merge.PassThroughCacheMergePolicy
or with its constant name as PASS_THROUGH
.com.hazelcast.cache.merge.PutIfAbsentCacheMergePolicy
or with its constant name as PUT_IF_ABSENT
.com.hazelcast.cache.merge.HigherHitsCacheMergePolicy
or with its constant name as HIGHER_HITS
.com.hazelcast.cache.merge.LatestAccessCacheMergePolicy
or with its constant name as LATEST_ACCESS
.You can access full class names or constant names of all build-in cache merge policies over com.hazelcast.cache.BuiltInCacheMergePolicies
enum. You can specify merge policy configuration for cache declaratively or programmatically.
The following are example configurations for JCache Split-Brain.
Declarative:
<cache name="cacheWithBuiltInMergePolicyAsConstantName">
...
<merge-policy>HIGHER_HITS</merge-policy>
...
</cache><cache name="cacheWithBuiltInMergePolicyAsFullClassName">
...
<merge-policy>com.hazelcast.cache.merge.LatestAccessCacheMergePolicy</merge-policy>
...
</cache>
<cache name="cacheWithBuiltInMergePolicyAsCustomImpl">
...
<merge-policy>com.mycompany.cache.merge.MyCacheMergePolicy</merge-policy>
...
</cache>
Programmatic:
CacheConfig cacheConfigWithBuiltInMergePolicyAsConstantName = new CacheConfig();
cacheConfig.setMergePolicy(BuiltInCacheMergePolicies.HIGGER_HITS.name());
CacheConfig cacheConfigWithBuiltInMergePolicyAsFullClassName = new CacheConfig();
cacheConfig.setMergePolicy(BuiltInCacheMergePolicies.LATEST_ACCESS.getImplementationClassName());
CacheConfig cacheConfigWithBuiltInMergePolicyAsCustomImpl = new CacheConfig();
cacheConfig.setMergePolicy("com.mycompany.cache.merge.MyCacheMergePolicy");