• 我的第一个开源项目:基于Redis的延迟队列


    redis-delay

    背景

    我们先看看以下业务场景:

    当订单一直处于未支付状态时,如何在半小时后自动取消?

    如何定期检查处于退款状态的订单是否已经退款成功?

    实现方案

    1. 定时任务扫表

    为了解决以上问题,最简单直接的办法就是定时去扫表。每个业务都要维护一个自己的扫表逻辑。

    • 优点:简单
    • 缺点:每分钟全局扫表,浪费资源,损耗数据库性能
    1. 消息中间件

    使用消息中间件可以实现延迟消息,像RocketMQ就自带这个功能

    • 优点:成熟稳定,使用方便
    • 缺点:针对那些项目里没有使用消息中间件的,需要额外部署,成本大。

    3.基于Redis

    根据Redis的zset、list的特性,我们可以利用Redis来实现一个延迟队列。

    • 优点:性能高,容易实现
    • 缺点:消息持久化依赖于redis

    方案参考有赞延迟队列:https://tech.youzan.com/queuing_delay/

    软件架构

    消息流程:

    • 用户对某个商品下单,系统创建订单成功,同时往延迟队列里put一个job。
    • 延迟队列收到该job后,先往job pool中存入job信息,然后根据delay计算出绝对执行时间,放入delay bucket.
    • 如果不是延迟job,直接放入ready set中。
    • DelayMoveToReadyTimer定时器循环取出delay中延迟时间达到的数据,放入ready set里
    • ReadyQueueTimer定时器循环取出消息消费

    接入流程

    在项目里的redis-delay-test测试项目中有完整的接入示例

    大概流程如下:

    1. 引入pom
            <dependency>
                <groupId>com.mmc</groupId>
                <artifactId>redis-delay-core</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
    
    1. 注入两个bean
    @Configuration
    public class DelayConfig {
    
        @Autowired
        private RedisTemplate redisTemplate;
    
        @Bean
        public Producer redisDelayService(){
            DelayProducer delayProducer = new DelayProducer(redisTemplate);
            delayProducer.setJobHandle("ORDER", new JobHandle() {
                @Override
                public boolean handle(Job job) {
                    System.out.println("收到消息:"+job);
                    return true;
                }
    
                @Override
                public boolean errorHandle(Job job) {
                    return false;
                }
            });
            return delayProducer;
        }
    }
    
    1. 建议创建一个topic枚举类
    public enum  TopicEnum {
    
        ORDER,
        LOG;
    }
    
    1. 使用api

    目前提供2个api:

    • asyncPutMessage 异步放入消息
    • syncPutMessage 同步放入消息
     JobParam param = JobParam.builder().topic(TopicEnum.ORDER.toString()).body("nihao").jobId("23111").build();
     boolean b = producer.syncPutMessage(param);
    

    接入后台管理界面

    1. 引入依赖
      <dependency>
        <groupId>com.mmc</groupId>
        <artifactId>redis-delay-ui</artifactId>
        <version>1.0-SNAPSHOT</version>
      </dependency>
    
    
    1. config类修改如下:
    
    @Configuration
    public class DelayUIConfig {
    
        @Autowired
        private RedisTemplate redisTemplate;
    
        @Bean
        public DelayFacade delayFacade(){
            return new DelayFacadeImpl(redisTemplate);
        }
    
        @Bean
        public Producer redisDelayService(){
            DelayProducer delayProducer = new DelayProducer(redisTemplate);
            delayProducer.setJobHandle("ORDER", new JobHandle() {
                @Override
                public boolean handle(Job job) {
                    System.out.println("收到消息:"+job);
                    return false;
                }
    
                @Override
                public boolean errorHandle(Job job) {
                    return false;
                }
            });
            return delayProducer;
        }
    
    }
    
    
    1. 配置页面路径或者将页面拷贝到你的项目

    spring.mvc.view.prefix=/pages/
    spring.mvc.view.suffix=.html

    1. 访问后台管理界面

    http://localhost:8080/redisDelay/admin/index

    项目地址

    https://gitee.com/mmcLine/redis-delay/

    只完成了第一版,需要优化的地方还很多。欢迎大家一起来完善。

    书山有路勤为径,学海无涯苦作舟
  • 相关阅读:
    2016 Multi-University Training Contest 3 部分题解
    STL漫谈
    ACM之路(18)—— 矩阵
    BestCoder Round #84
    HDU 2177 —— (威佐夫博弈)
    2016 Multi-University Training Contest 2 部分题解
    HDU 2176 取(m堆)石子游戏 —— (Nim博弈)
    心情--总结、反思与展望
    【Convert Sorted List to Binary Search Tree】cpp
    【Convert Sorted Array to Binary Search Tree】cpp
  • 原文地址:https://www.cnblogs.com/javammc/p/15113010.html
Copyright © 2020-2023  润新知