Reputation: 139
I have a Spring boot application with Hibernate L2 cache enabled. I integrated Hazelcast as cache provider for Hibernate. My application runs on Kubernetes and deployed on 2 pods.I verified, that hibernate l2 cache successfully distributed between 2 pods, within 1 cluster.So if 1 entity was put in cache in one pod, I see that cache size increases equally in all pods.
Also ,I want to use Hazelcast with spring @Cacheable
But this cache is not distributed between 2 pods, and just works separately in each instance.
So ,If I trigger method with @Cacheable
in first pod, and it's result is cached, then if I try to execute the same method(it result must be already in cache, after execution on fist pod) on second pod, It will not take it's result from cache.
What I need to add to configuration to make this work as expected? Would be very grateful for any advice.Thanks.
deployment.yaml for Kubernetes
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: hazelcast-cluster-role
rules:
- apiGroups:
- ""
resources:
- endpoints
- pods
- nodes
- services
verbs:
- get
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: hazelcast-cluster-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: hazelcast-cluster-role
subjects:
- kind: ServiceAccount
name: default
namespace: default
Configuration for Hazelcast - hazelcast.yaml
hazelcast:
instance-name: my-instance
network:
join:
multicast:
enabled: false
kubernetes:
enabled: true
namespace: dev
Application properties
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.url=jdbc:postgresql://host.docker.internal/postgres
spring.datasource.username=postgres
spring.datasource.password=pass
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=com.hazelcast.hibernate.HazelcastCacheRegionFactory
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.show_sql=true
hibernate.cache.hazelcast.instance_name=my-instance
Service with @Cacheable
@Service
public class BookService {
@Autowired
private BookRepo bookRepo;
@Cacheable("books")
public Iterable<Book> getBooks() {
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
System.out.println("Book service triggered");
return bookRepo.findAll();
}
}
Upvotes: 0
Views: 4072
Reputation: 3150
If I understand correctly, the data that is to be shared does not use @Cacheable
, which makes it simpler, solution 1 below.
Solution 1 - Each pod/JVM contains 2 Hazelcast instances, one is a cache manager.
@Cacheable
data with.Solution 1 - Each pod/JVM contains 2 Hazelcast instances, both are cache managers.
@Cacheable(cacheManager = "first" ...)
or @Cacheable(cacheManager = "second" ...)
to select what is cached locally and what is cached across all pods.Example Hazelcast code for 2nd standalone instance in same JVM.
@Bean(name = "B")
public HazelcastInstance hazelcastInstanceB() {
Config config = new Config();
config.setClusterName(UUID.randomUUID().toString());
config.getNetworkConfig().setPort(6701);
config.getNetworkConfig().getJoin().getAutoDetectionConfig().setEnabled(false);
config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
return Hazelcast.newHazelcastInstance(config);
}
@Autowired
@Qualifier(value = "B")
private HazelcastInstance hazelcastInstanceB;
Upvotes: 1