Design and Implementation of a Like Feature Using Spring Cloud, Redis, and Quartz Scheduling

This article explains how to design a high‑frequency like/unlike feature by caching operations in Redis, persisting data to a relational database at regular intervals, and orchestrating the process with Spring Boot, Spring Cloud, and Quartz scheduled jobs, complete with code examples and schema design.

Top Architect
Top Architect
Top Architect
Design and Implementation of a Like Feature Using Spring Cloud, Redis, and Quartz Scheduling

The article describes a complete solution for implementing a like/unlike functionality in a Spring Cloud application, focusing on performance optimization through Redis caching and periodic persistence to a relational database.

Redis Cache Design and Implementation

Installation and Running Redis

Docker command to start Redis: docker run -d -p 6379:6379 redis:4.0.8 If Redis is already installed, start it with:

redis-server

Integrating Redis with Spring Boot

1. Add the dependency in pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. Enable caching in the main application class:

@SpringBootApplication
@EnableDiscoveryClient
@EnableSwagger2
@EnableFeignClients(basePackages = "com.solo.coderiver.project.client")
@EnableCaching
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

3. Create a Redis configuration class ( RedisConfig) that defines RedisTemplate and StringRedisTemplate beans with Jackson JSON serialization.

Redis Data Structures

Redis supports five data types: String, List, Set, Hash, and Zset. For the like feature, a Hash is chosen because it allows storing multiple fields (likedUserId, likedPostId, status) under a single key, making bulk retrieval easy.

Storing Like Data in Redis

The key format is likedUserId::likedPostId. The value is 1 for like and 0 for unlike. This enables quick lookup and aggregation by splitting the key on ::.

Database Design

The relational table user_like contains columns for the primary key, liked user ID, liked post ID, status, creation time, and update time. An example DDL:

create table `user_like`(
    `id` int not null auto_increment,
    `liked_user_id` varchar(32) not null comment '被点赞的用户id',
    `liked_post_id` varchar(32) not null comment '点赞的用户id',
    `status` tinyint(1) default '1' comment '点赞状态,0取消,1点赞',
    `create_time` timestamp not null default current_timestamp comment '创建时间',
    `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间',
    primary key(`id`),
    INDEX `liked_user_id`(`liked_user_id`),
    INDEX `liked_post_id`(`liked_post_id`)
) comment '用户点赞表';

The corresponding JPA entity UserLike maps these fields and uses LikedStatusEnum for the status values.

Database Operations

Service interfaces RedisService and LikedService define methods for saving, updating, and querying like records. Implementations ( RedisServiceImpl and LikedServiceImpl) use RedisTemplate to read/write hash entries and convert them to domain objects.

Scheduled Persistence with Quartz

A Quartz job runs every two hours to transfer data from Redis to the database:

@Configuration
public class QuartzConfig {
    private static final String LIKE_TASK_IDENTITY = "LikeTaskQuartz";
    @Bean
    public JobDetail quartzDetail(){
        return JobBuilder.newJob(LikeTask.class)
                .withIdentity(LIKE_TASK_IDENTITY)
                .storeDurably()
                .build();
    }
    @Bean
    public Trigger quartzTrigger(){
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInHours(2)
                .repeatForever();
        return TriggerBuilder.newTrigger()
                .forJob(quartzDetail())
                .withIdentity(LIKE_TASK_IDENTITY)
                .withSchedule(scheduleBuilder)
                .build();
    }
}

The job class LikeTask invokes likedService.transLikedFromRedis2DB() and likedService.transLikedCountFromRedis2DB() to synchronize both the like records and the like counts.

Conclusion

The solution demonstrates how to handle high‑frequency like operations efficiently by leveraging Redis as a write‑through cache, designing appropriate key/value structures, and using a Quartz‑driven batch job to persist data reliably, while providing full code snippets for each component.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javadatabaseSpring BootQuartz
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.