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:
🔹 Redis Client-Server Architecture
Redis follows a client-server model, where:
Spring Boot supports two major Redis clients:
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:
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..
Recommended by LinkedIn
@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
🔹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
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.
🔹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.