Spring Boot Redis Cache

In this tutorial, we will be discussing the integration of Redis cache with Spring Boot by developing a CRUD operation example using Jedis and spring boot starter data redis. In the tutorial, we will explore 2 different ways to perform CRUD operations. First, we will be defining our custom RedisTemplate and use HashOperations to perform get and put operations on Redis server. Next, we will be using @Cacheable annotation to enable implicit caching mechanism by Spring Boot and upon cache miss, the lookup will be done in the DB with spring boot starter data jpa.

What is Redis

Redis is an in-memory data structure store implementing a distributed, in-memory key-value database with optional durability. It can be used as a database, cache or as a message broker. Redis supports different kinds of abstract data structures, such as strings, lists, maps, sets, sorted sets, HyperLogLogs, bitmaps, streams, and spatial indexes.

Redis is very fast as it is written in ANSI C and works in most POSIX systems like Linux, *BSD, OS X without external dependencies. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence.

Redis is best suited for caching in a distributed system and in this age of microservices Redis cache is very useful.

Setting up Redis Server Locally

First of all, we need to have Redis server running and we should have the connection properties such as host, port, password, etc. For this example, I have installed Redis server on my local machine. You can follow my Redis server installation on Windows and Mac tutorial to setup Redis server locally.

Once, the Redis server setup is done you can actually run below commands from the redis-cli.

Spring Boot Redis Cache Maven Configuration

We can use spring-boot-starter-data-redis maven artifact provided by Spring boot to integrate Redis with spring boot project. Below are the maven dependencies that we require for the integration.

This implementation is useful when we do not require any persistent storage of any object in DB. There are many use cases which requires in-memoery calculations and operations and store those results for specific period. We will discuss about the persistent stoarge and cache hit and cache miss related topics in later sections below.

Redis PUT Operation

Any insert operation such as put, putIfAbsent, and putAll requires 3 parameters. Below id a simple syntax for PUT operation.

void put(H key, HK hashKey, HV value);

You can assume key as a kind of partition in the Redis cache and this functionality is very handy in caching varities of data for quick operations. In our below examples, we are using the key as USER to save the user info.

Now, the hashKey is the unique queue that is used to save the value. In our case, the value is user info.

PUT operation sets the value of the supplied hash key. Below is the implementation that adds user object to the Redis cache with a unique hashkey of user id under the key USER.

Redis GET Operation

GET operation fetches the value for given hashKey (id) and key as USER. This operation returns a Java object. Hence, we need to expilicitly cast the object to user. Make sure, the User class implements Serializable

Redis DELETE Operation

DELETE operation removes the cached object with unique key(id) under the key USER. This operation can only delete the unique entries under the key USER. To delete the USER key itself, we need to use RedisTemplate which we will discuss later.

public void delete(String id){
hashOperations.delete("USER", id);
}

Redis VALUES Operation

VALUES operation retrieves all the values from the key. Below implementation returns a list object but there are operations to return key value pairs.

public List findAll(){
return hashOperations.values("USER");
}

Redis MultiGet Operation

With multiGet(), we can supply multiple keys at once and get the cached result. The point to remember here is that returned object by this operation is a list of list and hence while parsing the result to a meaningful collection, we need to follow the keys order that we supplied. The list will be returned in the same order.

Below is an example of parsing the result of multiGet() operation of HashOperation.

Redis GET Operation Test

Redis UPDATE Operation Test

Redis DELETE Operation Test

HTTP Method : DELETE
URL : http://localhost:8080/users/1234

Spring Boot Data Redis Implementation

In the above implementation, Redis itself is acting as a store house for our user entity. Above use case is useful when we don't require any persistent storage. For a persistent storage, we need to have a DB and upon a cache miss, our integration should perform a looup in the DB. For this we need to have spring-boot-starter-data-jpa module from spring boot.

Let us not discuss this integration here as it is a seperate topic of integration of spring data with spring boot. Here, we assume we have already spring data integrated and repository implementation is done. The complete implementation of spring boot data can be found here.

Hence, let us directly implement our service class that will have caching enabled with method level annotation @Caheable and upon cache miss a DB lookup is made.

Spring Boot Data Repository

Once, we have below dependencies added in the pom, we can define our repository.

@Cacheable in Spring Boot Data Redis

The @Cacheable annotation can be applied at method level. When applied at method level, then the annotated method’s return value is cached with key as the method parameter. You can use other params such as cacheName, cacheManager, conditions with it.

You need to annotate your spring boot main class with @EnableCaching to enable caching.

Below is an example of using @Cacheable. If the cache is missed then the method will be executed and it will fetch user from the repository and the same will be cached in Redis.