Search code examples
javaspring-bootcachingapache-kafkaspring-cache

Spring local cache for multiple app instances with invalidation through Kafka


I have a usual SpringBoot application, which executes tons of DB calls and for those I want to implement some Spring caching with normal @Cacheable / @CacheEvict and other annotations (by default I use CaffeineCache). There are several AKS nodes, on each of them one instance of my application is running. What I want to receive:

  • Local (in-memory) Spring cache. A distributed solution aka Redis-based or so is not suitable.
  • A cache should be invalidated for all running instances of the app after the update on one of them.
  • I have a global Kafka service, which registers every write/update request to my Cassandra DB

Now my question - is that possible to have a local, usual Spring cache with such an invalidation through Kafka resulting of course in synchronized cache version on all instances?


Solution

  • I would say it is possible in principle. You could build a naive solution, where

    • Read operations use @Cacheable
    • Write operations put a message to the Kafka bus, and each node has a listener that uses @CachePut to write it into the local cache.

    But such a naive solution will not have any strict synchronisation guarantees, it is only eventually consistent. It takes time to propagate updates to the other nodes and in between other nodes could still read the old value. Also you would have to think about error conditions where an update could get lost.

    If you want to have stricter guarantees, you need a multi-phase commit or a consensus protocol. Unless it is a research project I would highly discourage you from writing one yourself. These are not trivial because the problem is not trivial. Instead you should use existing implementations.

    So in summary: If you don't need consistency, you could do it like you suggest. If you need any level of consistency guarantee, you should use an existing distributed cache, which can still be integrated with @Cacheable.