使用redis实现延迟通知功能(Redis过期键通知)

redis 过期监听场景

业务中有类似等待一定时间之后执行某种行为的需求 , 比如 30 分钟之后关闭订单 . 网上有很多使用 redis 过期监听的 demo

redis配置

 把notify-keyspace-events ex 这一行的注释打开

项目demo工程

项目结构如下图

maven依赖

<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/pom/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
         xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactid>kim-redis</artifactid>
        <groupid>com.kim</groupid>
        <version>1.0.0</version>
    </parent>
    <modelversion>4.0.0</modelversion>

    <artifactid>kim-redis-expiration-notice</artifactid>

    <dependencies>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-data-redis</artifactid>
        </dependency>

        <dependency>
            <groupid>org.projectlombok</groupid>
            <artifactid>lombok</artifactid>
        </dependency>
        <dependency>
            <groupid>org.apache.commons</groupid>
            <artifactid>commons-pool2</artifactid>
        </dependency>

    </dependencies>
</project>

配置文件

server:
  port: 20103

spring:
  redis:
    #数据库索引
    database: 0
    host: 127.0.0.1
    port: 6379
    password: 123456
    lettuce:
      pool:
        #最大连接数
        max-active: 8
        #最大阻塞等待时间(负数表示没限制)
        max-wait: -1
        #最大空闲
        max-idle: 8
        #最小空闲
        min-idle: 0
    #连接超时时间
    timeout: 10000

启动类

/**
 * @project: kim-redis
 * @packagename: com.kim.redis.expiration.notice
 * @filename: noticeapplication.java
 * @description: the noticeapplication is...
 * @author: kimwu
 * @time: 2020-12-19 14:01:56
 */
@springbootapplication
public class noticeapplication {

    public static void main(string[] args) {
        springapplication.run(noticeapplication.class, args);
    }

}

配置类

@configuration
public class redistimeoutconfiguration {

    @autowired
    private redisconnectionfactory redisconnectionfactory;

    @bean
    public redismessagelistenercontainer redismessagelistenercontainer() {
        redismessagelistenercontainer redismessagelistenercontainer = new redismessagelistenercontainer();
        redismessagelistenercontainer.setconnectionfactory(redisconnectionfactory);
        return redismessagelistenercontainer;
    }

    @bean
    public keyexpiredlistener keyexpiredlistener() {
        return new keyexpiredlistener(this.redismessagelistenercontainer());
    }
}

监听类

@slf4j
public class keyexpiredlistener extends keyexpirationeventmessagelistener {


    public keyexpiredlistener(redismessagelistenercontainer listenercontainer) {
        super(listenercontainer);
    }

    @override
    public void onmessage(message message, byte[] pattern) {
        string channel = new string(message.getchannel(), standardcharsets.utf_8);
        //过期的key
        string key = new string(message.getbody(), standardcharsets.utf_8);
        log.info("redis key 过期:pattern={},channel={},key={}", new string(pattern), channel, key);
    }
}

异常情况测试

当key过期时,项目宕机了
①写入redis的key
②手动关停服务,等待redis的key过期
③确认redis的key过期后,重启服务。服务不会收到通知

当key过期时,redis服务宕机了
①写入redis的key
②关停redis服务,等待redis的key过期
③启动redis服务,发现redis的过期key已经不存在了,服务没有收到通知

结论

redis的键过期本身不可靠,并不像rabbitmq一样保证了可靠性。
当服务本身宕机或者redis宕机时,将无法保证过期的key能够被消费。

当使用场景对数据完整性不那么精确时,可以使用redis的键过期策略。否则不太建议使用redis的键过期策略。

到此这篇关于使用redis实现延迟通知功能(redis过期键通知)的文章就介绍到这了,更多相关redis过期键通知内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

(0)
上一篇 2022年3月21日
下一篇 2022年3月21日

相关推荐