Redis | 使用 Redisson的RMapCache实现用户消息定时自动发送功能

关注:CodingTechWork

引言

  在现代应用中,消息推送是一项常见需求,尤其是在定时通知、过期提醒等场景中。我们通常会依赖定时任务来实现这一类功能,但在使用 Redis 作为缓存时,可以利用 Redis 自身的过期事件机制,自动触发相关操作,从而避免了依赖定时任务的麻烦。
  本文将通过 Redisson 实现基于 Redis 缓存过期事件的自动消息推送功能,并将消息的过期时间与推送事件的触发通过 Date 类型的入参进行配置,帮助开发者更高效地管理缓存与触发推送。

项目背景与需求

我们希望在 Redis 中存储一些定时消息,并在消息过期时自动触发推送操作。例如:

  • 用户设定了某个事件的提醒时间,并将相关数据存储到 Redis 中,定时缓存过期。
  • 当缓存过期时,自动触发推送操作,例如发送邮件、短信等。

通过 Redis 的过期事件机制,我们可以在缓存过期时自动触发推送操作,而不需要依赖额外的定时任务。

技术栈

  • Redis:用于存储消息数据,并通过过期事件机制触发监听。
  • Redisson:Java 客户端,用于操作 Redis,并支持缓存过期事件的监听。
  • Spring Boot:作为应用框架,提供快速开发和集成能力。

实现思路

Redis 配置与 Redisson 设置

首先需要配置 Redis,确保启用缓存的过期事件通知。这可以通过修改 Redis 的配置来实现。

application.properties 中配置 Redis 连接:

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=yourpassword
spring.redis.listener-expiration=true

启用 Redis 过期事件通知

Redis 默认并不会发布过期事件通知,我们需要在 Redis 配置中启用键过期事件通知:

redis-cli CONFIG SET notify-keyspace-events Ex

Ex 参数表示启用键过期事件的发布通知,其中 E 表示过期事件,x 表示触发的时间事件。

Redisson 实现 Redis 过期事件监听

Redisson 提供了方便的 API 来连接 Redis 并进行事件监听。我们将使用 RedissonClient 来订阅 Redis 的过期事件频道,从而触发消息推送操作。

Redis 过期事件监听器

我们创建一个 Redis 过期事件监听器,它会监听 Redis 键的过期事件。当某个缓存过期时,自动触发推送逻辑。

import org.redisson.api.RedissonClient;
import org.redisson.api.listener.MessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RedisExpirationListener {

    @Autowired
    private RedissonClient redissonClient;

    // 初始化监听器,监听 Redis 的过期事件
    public void init() {
        // 订阅 Redis 过期事件频道
        redissonClient.getTopic("__keyevent@0__:expired").addListener(String.class, new MessageListener<String>() {
            @Override
            public void onMessage(CharSequence channel, String expiredMessageKey) {
                // 当某个缓存的消息过期时,触发消息推送
                System.out.println("Cache key expired: " + expiredMessageKey);
                handleExpiredMessage(expiredMessageKey);
            }
        });
    }

    // 处理过期消息,进行推送
    private void handleExpiredMessage(String expiredMessageKey) {
        // 处理过期消息的推送逻辑,例如发送邮件、短信等
        System.out.println("Push message related to expired key: " + expiredMessageKey);
        // 在这里你可以根据业务需求,调用外部服务发送推送通知
    }
}

存储消息到 RMapCache

  我们将消息存储到 Redis 中,并设置过期时间。这里使用 RMapCache,它是 Redisson 提供的支持过期时间和容量限制的缓存类型。
  为了接受 Date 类型作为过期时间,我们需要将其转换为毫秒时间戳(Date 对象的 getTime() 方法)。具体实现如下:

import org.redisson.api.RedissonClient;
import org.redisson.api.RMapCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class MessageService {

    @Autowired
    private RedissonClient redissonClient;

    // 将消息存储到 RMapCache,并设置过期时间(使用 Date 类型的入参)
    public void storeMessage(String userId, String messageId, String messageContent, Date expirationTime) {
        long expirationTimeMillis = expirationTime.getTime() - System.currentTimeMillis(); // 计算相对过期时间
        if (expirationTimeMillis > 0) {
            RMapCache<String, String> messageCache = redissonClient.getMapCache("userMessages:" + userId);
            messageCache.put(messageId, messageContent, expirationTimeMillis, TimeUnit.MILLISECONDS);
            System.out.println("Message stored with expiration time: " + expirationTimeMillis + "ms");
        } else {
            System.out.println("Expiration time must be in the future.");
        }
    }
}

启动 Redis 过期事件监听

在 Spring Boot 应用启动时,我们初始化 Redis 过期事件监听器:

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public CommandLineRunner init(RedisExpirationListener redisExpirationListener) {
        return args -> {
            // 初始化 Redis 过期事件监听器
            redisExpirationListener.init();
        };
    }
}

存储消息 API

  为了测试,我们创建一个简单的 RESTful API,用来存储消息并设置过期时间(Date 类型)。用户可以通过接口传递消息内容以及过期时间。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;

@RestController
@RequestMapping("/message")
public class MessageController {

    @Autowired
    private MessageService messageService;

    // 接收消息存储请求
    @PostMapping("/store")
    public String storeMessage(@RequestParam String userId, 
                               @RequestParam String messageId, 
                               @RequestParam String messageContent, 
                               @RequestParam String expirationTime) {
        try {
            Date expirationDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(expirationTime);
            messageService.storeMessage(userId, messageId, messageContent, expirationDate);
            return "Message stored with expiration time: " + expirationDate;
        } catch (ParseException e) {
            return "Invalid expiration date format. Please use 'yyyy-MM-dd HH:mm:ss'.";
        }
    }
}

测试与验证

  1. 启动 Spring Boot 应用。
  2. 通过 HTTP 请求模拟发送消息:
POST http://localhost:8080/message/store?userId=user123&messageId=msg001&messageContent=Hello%20World&expirationTime=2025-04-25%2010:30:00

这会将消息存储到 Redis 中,并在指定的时间后过期。

  1. 当过期事件触发时,监听器会接收到过期事件并自动触发 handleExpiredMessage 方法,输出消息过期并进行推送。

消息推送

  在 handleExpiredMessage 方法中,可以根据需求实现真正的消息推送逻辑(例如通过邮件、短信、微信等方式推送通知)。

总结

  本文介绍了如何通过 Redisson 实现基于 Redis 缓存过期事件的消息自动推送机制,并且通过 Date 类型入参来设定消息过期时间。通过 Redis 的过期事件通知,我们可以高效地管理缓存和触发自动操作,从而减少系统的复杂度并提高响应速度。这种方式特别适用于消息通知、定时提醒等场景。
  在实际应用中,可以根据需求集成不同的消息推送方式(如邮件、短信、微信等),实现更加灵活的业务逻辑。

你可能感兴趣的:(中间件,&,工具类,#,Redis,JAVA核心技术,缓存,redis,bootstrap)