• 基于Redis队列实现《二》——点对点模式


    前言

           通过队列实功能之间的解耦,异步,是一个非常通用的功能。一般采用 请求——>异步处理——>异步通知的方式实现,比如支付宝支付,提交支付请求之后,直接跳转一个中间界面,过几秒钟后,才会提示支付成功。

           这里实现的场景是为了解耦,在提交商品购买请求之后,需要做很多事情,比如保存请购单数据,生成订单数据,减扣库存,提交OA审批,还有消息通知等等,如果采用传统的同步请求的方式,这个接口可能会需要

    等待比较长的时间才会返回结果,会给用户带来是不是很好的体验。这里在生成请购单和订单数据后,以消息的形式推送redis队列,异步减扣库存,提交OA审批等操作。

    队列基础

        这里可以参考前一篇 《基于Redis队列实现《一》——SUB/PUB模式》

    示例

    1. 实现说明:这里只是借签RedisTemplate实现redis队列的pub/sub模式的设计,基于spring 容器 linstener做的一个实现。这里实现的是点对点模式。

    2. 知识准备:

         2.1  这里基于spring boot 项目,通过ResdisTemplate客户端连接redis;

         2.2  该方案依赖于redis数据结构List,通过LPUSH(左侧插入)和BLPOP(阻塞出队)实现的点对点阻塞队列。

         2.3  spring容器自定义listener机制

    3.实现流程:

     

    4. 代码示例:

     1. RedisQuenueConfig配置类

    /**
     * Redis配置类
     * @version 1.0
     * @author liuyq
     * @date 2021-06-03 15:17:55
     */
    @Configuration
    public class RedisQuenueConfig {
    
        /**
         * 实例化listener
         * @return
         */
        @Bean
        public RecEventListener getEventListener(){
            return new RecEventListener();
        }
    }

    2.RecEventListener 事件监听器,当redis队列收到消息时,将消息出队

    /**
     * RecEvent事件监听器
     * @version 1.0
     * @author liuyq
     * @date 2021-06-03 14:26:22
     */
    @Component
    public class RecEventListener implements ApplicationListener<RecEvent> {
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        @Autowired
        private MessageService messageService;
    
        @Override
        public void onApplicationEvent(RecEvent recEvent) {
            ListOperations<String, String> stringStringListOperations = stringRedisTemplate.opsForList();
            String msg = stringStringListOperations.rightPop(recEvent.getQueue());
            if(msg == null){
                return;
            }
    //处理指定channel的消息 if(Constant.third_order_message_queue_prefix.equals(recEvent.getQueue())){
    messageService.handleMessage(msg);
    }
       }
    }

    3. RecEvent 接收消息事件

    /**
     * 接收消息事件
     * @version 1.0
     * @author liuyq
     * @date 2021-06-03 14:21:11
     */
    public class RecEvent extends ApplicationEvent {
    
        private String queue;
    
        private String msg;
    
        public RecEvent(Object source) {
            super(source);
        }
    
        public RecEvent(Object source, String queue, String msg) {
            super(source);
            this.queue = queue;
            this.msg = msg;
        }
    
        public String getQueue() {
            return queue;
        }
    
        public void setQueue(String queue) {
            this.queue = queue;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    

      

    4. PbulishMessageServiceImp 客户端发布消息

    /**
     * 发布消息
     * @version 1.0
     * @author liuyq
     * @date 2021-04-29 17:22:02
     */
    @Service
    public class PbulishMessageServiceImpl implements PbulishMessageService {
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        @Autowired
        private WebApplicationContext webapplicationcontext;
    
    
        /**
         * 保存消息到队列,基于点对点模式
         * @param queue 队列列
         * @param content 内容
         */
        public void saveMessageToQueueWithSingle(String queue, String content){
            ListOperations<String, String> listOperations = stringRedisTemplate.opsForList();
            Long result = listOperations.leftPush(queue, content);
            if(result > 0){
                RecEvent recEvent = new RecEvent("object", Constant.third_order_message_queue_prefix, "####监听第三方订单创建");
                //推送消息后,发布时间RecEvent,告知监听器处理消息
                webapplicationcontext.publishEvent(recEvent);
            }
        }
    
    }

    5. 调用示例

    @Service
    public class Demo{
    
        @Autowired
        private MessageService messageService;
    
        /**
        *   推送消息示例
        *  @param channel  消息队列名
        *  @param msg 推送消息
        */
        public void publishMessage(String channel, String msg){
           //推送到redis队列,之前由于1对多问题导致停滞     
    messageService.saveMessageToQueueWithSingle(Constant.third_order_message_queue_prefix, msg); } }

      

  • 相关阅读:
    【贪心】CodeForces-545C:Woodcutters
    【贪心】雷达问题
    【贪心】poj1328:雷达设置
    【最短路】HDU2680:Choose the best route
    2018年第四阶段组队训练赛第九场
    第四阶段组队训练赛第八场
    2018年第四阶段组队训练赛第七场
    第四阶段组队训练赛第六场( 题源:UKIEPC2017)
    Coins I
    2018年第四阶段组队训练赛第五场
  • 原文地址:https://www.cnblogs.com/liuyq/p/14860766.html
Copyright © 2020-2023  润新知