Getting Started with Redis in Spring Boot

Getting Started with Redis in Spring Boot

In this article, we'll explore how to integrate Redis into a Spring Boot application for caching. We’ll cover Redis configuration, annotations, Jedis, and more.

🔹 Why Caching?

Caching is a technique used to store frequently accessed data in a fast, in-memory storage to reduce load on databases and improve application performance. Instead of repeatedly fetching data from a slow, persistent database, caching helps serve data quickly from memory.

🔹 Why Use Redis?

Redis (Remote Dictionary Server) is an open-source, in-memory key-value store that is widely used for caching. It offers:

  • High-speed data access (stored in RAM)
  • Persistence options (can write data to disk)
  • Support for various data structures (Strings, Hashes, Lists, Sets, Sorted Sets, etc.)
  • Scalability (supports clustering and replication)

🔹 Redis Client-Server Architecture

Redis follows a client-server model, where:

  • The Redis server runs as a separate process and manages data storage in memory.
  • The Redis client connects to the Redis server to send commands and retrieve cached data.
  • Communication happens over TCP/IP using the Redis protocol.

Spring Boot supports two major Redis clients:

  1. Lettuce (default) – Asynchronous, non-blocking, and more scalable.
  2. Jedis – Synchronous, simpler to use, and thread-safe for single connections.

We will explicitly use Jedis in our project.

🔹 Setting Up Redis in Spring Boot

Project Setup

Go to start.spring.io and create a new Spring Boot project with the following:

  • Build Tool: Maven
  • Java Version: Any compatible version
  • Spring Boot Version: 3.4.2
  • Dependencies: Spring Web, Spring Data JPA, Spring Data Redis, MySQL Driver, Spring Cache Abstraction

Additionally we need Jedis dependency which is not available in spring starter.

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>5.0.0</version>
</dependency>        

Lets prepare our application.properties file for Spring to work on. Apart from usual jpa settings, we will add Redis config. Default port is 6379 and host is localhost. and we will tell spring to enable caching mechanism

spring.application.name=redis-demo
server.port = 8082

#JPA
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

# Redis Configuration
spring.redis.host=localhost
spring.redis.port=6379

# Enable Caching
spring.cache.type=redis        

We will set up Redis config via java other than xml approach here. lets create a package and config file /src/main/java/<module>/config/RedisConfig.java

We are initializing our Redis client - Jedis here with default values (host/port etc)

@Bean
public JedisConnectionFactory jedisConnectionFactory(){
    return new JedisConnectionFactory();
}        

Next, lets create a RedisTemplate to tell to Redis server about our Jedis configuration we set early.

@Bean
public RedisTemplate<String, Object> redisTemplate(){
    RedisTemplate<String,Object> template = new RedisTemplate<>();
    template.setConnectionFactory(jedisConnectionFactory());
    return template;
}        

Lets include one additional settings here, By default Spring boot dose not set Time To Live for cached data. If you don't expire keys, Redis can be overloaded. below Bean will make sure, after 10 minutes, keys and values are destroyed also avoid caching null values.

@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){

    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(10)) //10 minutes of TTL
            .disableCachingNullValues(); //blocked null values

    return RedisCacheManager.builder(redisConnectionFactory)
            .cacheDefaults(config)
            .build();
}        

🔹 Student Model set up Service layer

We are done with our configurations, lets dive into real coding of our service layer and Model. Let me tell you what we are doing with our project. A Student data(Id, Name, Address) is going to be send to MySQL and also going to be stored in Redis cache.

Since Redis store key-value pairs, Student ID will be the key and a serialized name and address will be value. We will serialize our Student model as implements Serializable.

Our Student.java as below. I am making use of Lombok library for getters,setters,constructors etc..

@Data
@Entity
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "students")
public class Student implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String address;
}        

1) @CachePut in Service layer

The student object will be stored in MySQL as well as Redis cache by making use of this annotation. We are setting key as s.id and cache name as student. Whenever saveStudent() is called, Redis will store the same student details

@CachePut(value = "student", key = "#s.id")
public Student saveStudent(Student s){
    return myRepo.save(s);
}        

2) @CacheEvict in Service layer

Whenever a student is deleted by calling deleteStudent() we must remove this entry from cache, for that, we use CacheEvict annotation.

@CacheEvict(value = "student", key = "#id")
public void deleteStudent(Long id){
    myRepo.deleteById(id);
}        

3) @Cacheable in Service layer

The real fetching of data from Redis is happening here, when a getStudentById() is called, spring will pick up the student info from MySQL initially, then the subsequent call will bring the data from Redis cache rather than from database.

@Cacheable(value = "student", key = "#id")
public Optional<Student> getStudentById(Long id) {
    System.out.println("Fetching student from database...");
    return myRepo.findById(id);
}        

🔹 Out of scope controller and repo

We are not discussing about the controllers and repo, its as usual for a java project for crud operation from MySQL. I will provide the github url for the same

https://github.com/sonym3/redis-demo

🔹Redis in Local machine

In order to start our spring boot app, we need to start Redis server in our local. I am using Pod man here for Redis container. With below command, I can see Redis is up and running in default port

C:\Users\s.mathew>podman start redis-container
redis-container

C:\Users\s.mathew>podman ps
CONTAINER ID  IMAGE                           COMMAND       CREATED       STATUS        PORTS                   NAMES9abe1db4f542  docker.io/library/redis:latest  redis-server  22 hours ago  Up 5 seconds  0.0.0.0:6379->6379/tcp  redis-container

C:\Users\s.mathew>        

🔹Running spring boot app

Our Student spring boot app is ready, Redis client running in local machine, MySQL is exposed to default port. Lets run the spring boot app.

I am sending a student data with POST - /students

Article content

We will retrieve the same data with GET - /students/202. As soon as you hit the endpoint, data will be fetched from database. but the second time, you wont be seeing any updates in spring boot terminal because its coming from Redis. No JPA, MySQL involved.

Article content

🔹Redis cache verification

Lets proceed to Redis and verify the content stored.

C:\Users\s.mathew>podman exec -it redis-container redis-cli
127.0.0.1:6379>
127.0.0.1:6379> keys *
1) "student::152"
127.0.0.1:6379>
127.0.0.1:6379> get student::302
"\xac\xed\x00\x05sr\x00%com.letscode.redis_demo.model.Student\xce\xd3\x96\r\r\xc7f\xed\x02\x00\x03L\x00\aaddresst\x00\x12Ljava/lang/String;L\x00\x02idt\x00\x10Ljava/lang/Long;L\x00\x04nameq\x00~\x00\x01xpt\x00\x0e2 Lancaster drsr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x00\x00\x00\x01.t\x00\bJone Doe"
127.0.0.1:6379>        

What we see here is serialized object student.

🔹What's next?

I will come up with some edge case scenarios to understand more about Redis Caching and we will try to store de-serialized data in Redis.

See you soon.




To view or add a comment, sign in

Others also viewed

Explore content categories