• RabbitMQ学习延时队列


    一.延时队列的定义

    延时队列,首先,它是一种队列,队列意味着内部的元素是有序的,元素出队和入队是有方向性的,元素从一端进入,从另一端取出。其次,延时队列最重要的特性就体现在它的延时属性上,跟普通的队列不一样的是,普通队列中的元素总是希望被早点取出处理,而延时队列中的元素则是希望在指定的时间得到取出和处理。所以延时队列中的元素是都是带时间属性的,通常来说是需要被处理的消息或者任务。简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列。

    二.延时队列的使用场景

    1.订单在十分钟之内未支付则自动取消。

    2.新创建的店铺,如果在十天内都没有上传过商品,则自动发送消息提醒。

    3.账单在一周内未支付,则自动结算。

    4.用户注册成功后,如果三天内没有登陆则进行短信提醒。

    5.用户发起退款,如果三天内没有得到处理则通知相关运营人员。

    6.预定会议后,需要在预定的时间点前十分钟通知各个与会人员参加会议。

           这些场景都有一个特点,需要在某个事件发生之后或者之前的指定时间点完成某一项任务,如:发生订单生成事件,在十分钟之后检查该订单支付状态,然后将未支付的订单进行关闭;发生店铺创建事件,十天后检查该店铺上新商品数,然后通知上新数为0的商户;发生账单生成事件,检查账单支付状态,然后自动结算未支付的账单;发生新用户注册事件,三天后检查新注册用户的活动数据,然后通知没有任何活动记录的用户;发生退款事件,在三天之后检查该订单是否已被处理,如仍未被处理,则发送消息给相关运营人员;发生预定会议事件,判断离会议开始是否只有十分钟了,如果是,则通知各个与会人员。

           看起来似乎使用定时任务,一直轮询数据,每秒查一次,取出需要被处理的数据,然后处理不就完事了吗?如果数据量比较少,确实可以这样做,比如:对于“如果账单一周内未支付则进行自动结算”这样的需求,如果对于时间不是严格限制,而是宽松意义上的一周,那么每天晚上跑个定时任务检查一下所有未支付的账单,确实也是一个可行的方案。但对于数据量比较大,并且时效性较强的场景,如:“订单十分钟内未支付则关闭“,短期内未支付的订单数据可能会有很多,活动期间甚至会达到百万甚至千万级别,对这么庞大的数据量仍旧使用轮询的方式显然是不可取的,很可能在一秒内无法完成所有订单的检查,同时会给数据库带来很大压力,无法满足业务要求而且性能低下。

    三.RabbitMQ的TTL(Time To Live)

    1. TTL定义

           TTL是RabbitMQ中一个消息或者队列的属性,表明一条消息或者该队列中的所有消息的最大存活时间,单位是毫秒。换句话说,如果一条消息设置了TTL属性或者进入了设置TTL属性的队列,那么这条消息如果在TTL设置的时间内没有被消费,则会成为“死信”。

    2.设置TTL的值

    (1)创建队列的时候设置

    var args = new Dictionary<string, object>();
    args.Add("x-message-ttl",60000);
    channel.QueueDeclare("myqueue", true, false, false, args);

    设置为60秒过期

    (2)对每条消息设置TTL

      string message = "零下10度";
      var body = Encoding.UTF8.GetBytes(message);
      IBasicProperties props = channel.CreateBasicProperties();
      props.ContentType = "text/plain";
      props.DeliveryMode = 2;
      props.Expiration = "60000";
      channel.BasicPublish(exchange: RabbitConstant.EXCHANGE_WEATHER,
                                             routingKey: "",
                                             basicProperties: props,
                                             body: body);

           但这两种方式是有区别的,如果设置了队列的TTL属性,那么一旦消息过期,就会被队列丢弃,而第二种方式,消息即使过期,也不一定会被马上丢弃,因为消息是否过期是在即将投递到消费者之前判定的,如果当前队列有严重的消息积压情况,则已过期的消息也许还能存活较长时间。

          另外,还需要注意的一点是,如果不设置TTL,表示消息永远不会过期,如果将TTL设置为0,则表示除非此时可以直接投递该消息到消费者,否则该消息将会被丢弃。

     参考链接:https://www.cnblogs.com/mfrank/p/11260355.html

  • 相关阅读:
    golang-switch结构辨析有话
    不用中间变量交换变量值-golang版
    vue element ui表单验证不通过,滚动到页面上第一个验证失败的输入框位置
    表单校验中使用v-if和v-else来判断是福哦要校验时的注意项
    如何修改本地项目关联的远程仓库地址
    vue-cli3如何访问public文件夹下的静态资源
    Git 命令行的各种退出方式
    elementui表格如何在表头每个列标题后面插入图片用于插入tooltip
    js 把一个二叉树类型的对象转化为普通对象
    element-ui树结构设置默认选中节点时改变传入的数组树结构没有变化
  • 原文地址:https://www.cnblogs.com/hobelee/p/15780572.html
Copyright © 2020-2023  润新知