• SpringBoot整合redis实现过期Key监控处理(最简单模式)


    前言:写这篇文章的目的主要是这方面的知识我是第一次实际运用到,在项目里面有个功能,需要登录的时候根据手机号发送短信验证码,我看了公司的代码是用redis过期key监控实现的,由于之前没有接触过这类,现在写下来记一下,主要是简单的实现对redis过期key的监控。

    第一步:搭建springboot、redis

    为了避免redis与spring存在版本冲突导致的不必要的麻烦,我所使用的spring版本是 2.2.2.RELEASE版本,使用自带的redis-starter,pom依赖最简单化为:

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <parent>
    6. <groupId>org.springframework.bootgroupId>
    7. <artifactId>spring-boot-starter-parentartifactId>
    8. <version>2.2.2.RELEASEversion>
    9. <relativePath/>
    10. parent>
    11. <groupId>com.examplegroupId>
    12. <artifactId>demoartifactId>
    13. <version>0.0.1-SNAPSHOTversion>
    14. <name>domeOnename>
    15. <description>Demo project for Spring Bootdescription>
    16. <properties>
    17. <java.version>8java.version>
    18. properties>
    19. <dependencies>
    20. <dependency>
    21. <groupId>org.springframework.bootgroupId>
    22. <artifactId>spring-boot-starter-data-redisartifactId>
    23. dependency>
    24. <dependency>
    25. <groupId>org.springframework.bootgroupId>
    26. <artifactId>spring-boot-starter-webartifactId>
    27. dependency>
    28. <dependency>
    29. <groupId>org.springframework.bootgroupId>
    30. <artifactId>spring-boot-starter-testartifactId>
    31. <scope>testscope>
    32. dependency>
    33. <dependency>
    34. <groupId>org.projectlombokgroupId>
    35. <artifactId>lombokartifactId>
    36. <optional>trueoptional>
    37. dependency>
    38. dependencies>
    39. <build>
    40. <plugins>
    41. <plugin>
    42. <groupId>org.springframework.bootgroupId>
    43. <artifactId>spring-boot-maven-pluginartifactId>
    44. plugin>
    45. plugins>
    46. build>
    47. project>

    配置application.yml为:

    1. spring:
    2. redis:
    3. port: 6379
    4. host: 127.0.0.1
    5. password: redis
    6. database: 1
    7. timeout: 30000
    8. server:
    9. port: 8081

    第二步:简单测试springboot与redis是否连接成功

    1. @Slf4j
    2. @RestController
    3. public class Controller {
    4. @Autowired
    5. private RedisTemplate redisTemplate;
    6. @GetMapping("/test")
    7. public void test() {
    8. log.info("test方法运行了");
    9. redisTemplate.opsForValue().set("key","value112值");
    10. log.info("测试redis是否正常,取值key:{}", redisTemplate.opsForValue().get("key"));
    11. }
    12. }

    这些操作较为简单,一般不会出错,访问127.0.0.1:8081/test 正常打印日志则说明连接正常。

    第三步:新增RedisConfig.java配置类

    在该配置类里面添加监控Bean,设置监控topic(全部key过期皆会被监测到),这里写得简单了,正常还需要设置线程池以及封装RedisTemplate。

    1. @Configuration
    2. public class RedisConfig implements ApplicationContextAware {
    3. @Autowired
    4. private RedisTemplate redisTemplate;
    5. @Autowired
    6. private LettuceConnectionFactory connectionFactory;
    7. private ApplicationContext applicationContext;
    8. @Override
    9. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    10. this.applicationContext = applicationContext;
    11. }
    12. @Bean
    13. public RedisMessageListenerContainer configRedisMessageListenerContainer(Executor executor) {
    14. RedisMessageListenerContainer container = new RedisMessageListenerContainer();
    15. // 设置Redis的连接工厂
    16. container.setConnectionFactory(redisTemplate.getConnectionFactory());
    17. // 设置监听使用的线程池
    18. container.setTaskExecutor(executor);
    19. // 设置监听的Topic
    20. ChannelTopic channelTopic = new ChannelTopic("__keyevent@" + connectionFactory.getDatabase() + "__:expired");
    21. Map listeners = applicationContext.getBeansOfType(MessageListener.class);
    22. if (listeners != null && !listeners.isEmpty()) {
    23. for (String key : listeners.keySet()) {
    24. // 设置监听器
    25. container.addMessageListener(listeners.get(key), channelTopic);
    26. }
    27. }
    28. return container;
    29. }
    30. }

    第四步:自定义监控类MyMessageListener

    onMessage方法来自于MessageListener接口,主要就是对过期key进行监控

    1. @Slf4j
    2. @Component
    3. public class MyMessageListener implements MessageListener, ApplicationContextAware {
    4. private ApplicationContext applicationContext;
    5. @Autowired
    6. private IMessageHandler messageHandler;
    7. @Override
    8. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    9. this.applicationContext = applicationContext;
    10. }
    11. public MyMessageListener() {
    12. }
    13. @Override
    14. public void onMessage(Message message, byte[] bytes) {
    15. log.info("进入监控方法....");
    16. String body = new String(message.getBody());
    17. log.info("监控到的body为: {}", body);
    18. messageHandler.handleMessage(body);
    19. }
    20. }

    第五步:其他业务处理代码,根据业务进行逻辑处理:

    1. public interface IMessageHandler {
    2. /**
    3. * 处理redis的key值过期事件
    4. */
    5. void handleMessage(String body);
    6. }
    1. @Slf4j
    2. @Service
    3. public class MessageServiceImpl implements IMessageHandler {
    4. @Override
    5. public void handleMessage(String body) {
    6. log.info("开始处理消息");
    7. }
    8. }

    第六步:测试,修改controller类

    这里为了方便,将过期key设置为10秒过期,执行方法10秒后,代码能够自动处理消息则说明成功 

    1. @Slf4j
    2. @RestController
    3. public class Controller {
    4. @Autowired
    5. private RedisTemplate redisTemplate;
    6. @GetMapping("/test")
    7. public void test() {
    8. log.info("test方法运行了");
    9. // redisTemplate.opsForValue().set("key","value112值");
    10. // log.info("测试redis是否正常,取值key:{}", redisTemplate.opsForValue().get("key"));
    11. long expire = 10L;
    12. // 监控key_timeout过期
    13. setExpire("key_timeout","value", expire);
    14. }
    15. private RedisSerializer getRedisSerializer() {
    16. return redisTemplate.getStringSerializer();
    17. }
    18. private void setExpire(final String key, final String value, final long time) {
    19. redisTemplate.execute((RedisCallback) connection -> {
    20. RedisSerializer serializer = getRedisSerializer();
    21. byte[] keys = serializer.serialize(key);
    22. byte[] values = serializer.serialize(value);
    23. connection.set(keys, values);
    24. connection.expire(keys, time);
    25. return 1L;
    26. });
    27. }
    28. }

    注意!!!

    redis需要开启监控过期key需要修改redis.conf文件(windows的文件名叫做redis.windows.conf),修改后需重启redis,否则不生效。

    设置为 notify-keyspace-events "Ex"

  • 相关阅读:
    “世亚智博会,世亚软博会”双展联动,3月上海,4月杭州,6月北京
    算法 含有min函数的栈-(栈)
    Mysql常用命令详细大全
    基于springboot+vue实现乌鲁木齐南山冰雪旅游服务网管理系统项目【项目源码+论文说明】
    服务网格的面临挑战:探讨服务网格实施中可能遇到的问题和解决方案
    【精品】pinia详解
    华为OD机试 - 告警抑制 - 数据结构map(Java 2023 B卷 100分)
    Spring命名空间
    Ladder Side-Tuning:预训练模型的“过墙梯”
    Sentry 是一个开源的错误监控和日志聚合平台-- 通过docker-compose 安装Sentry
  • 原文地址:https://blog.csdn.net/qq_41831842/article/details/133993803