• rabbitMq消息持久化机制,和延时队列


    1、RabbitMQ的一大特色是消息的可靠性,那么它是如何保证消息可靠性的呢?

    消息持久化。可以将Queue,Exchange,Message都设置为可持久化的。为了保证RabbitMQ在退出,服务重启或者crash等异常情况下,也不会丢失消息。

    2、RabbitMQ服务异常,重启时候怎么保证消息不丢失,持久化的实现?

    1、Queue(消息队列)的持久化是通过durable=true来实现的。 

    Connection connection = connectionFactory.newConnection();
    Channel channel = connection.createChannel();
    //关键的是第二个参数设置为true,即durable=true.
    channel.queueDeclare("queue.persistent.name", true, false, false, null);
    /到这步仅仅是做到了消息队列的持久化,还没有做消息持久化。

    2、Message(消息)的持久化 ,通过设置消息是持久化的标识。

    //MessageProperties.PERSISTENT_TEXT_PLAIN 
    channel.basicPublish("exchange.persistent", "persistent", MessageProperties.PERSISTENT_TEXT_PLAIN, "persistent_test_message".getBytes());

    3、Exchange(交换机)的持久化 。

    //即在声明的时候讲durable字段设置为true即可。
    channel.exchangeDeclare(exchangeName, “direct/topic/header/fanout”, true);

    3、死信队列是什么?

    1、死信队列是一个普通的队列,它没有消费者,用来存储有超时时间信息的消息,并且可以设置当消息超时(ttl),等待消息超时,将消息转发到指定的Router队列。

    2、“死信”是RabbitMQ中的一种消息机制,当你在消费消息时,如果队列里的消息出现以下情况:

    1. 消息被否定确认,使用 channel.basicNack 或 channel.basicReject ,并且此时requeue 属性被设置为false
    2. 消息在队列的存活时间超过设置的TTL时间。
    3. 消息队列的消息数量已经超过最大队列长度。

    “死信”消息会被RabbitMQ进行特殊处理,如果配置了死信队列信息,那么该消息将会被丢进死信队列中,如果没有配置,则该消息将会被丢弃。

    3、延时队列和转发队列是什么?

    延时队列:就是用来存放需要在指定时间被处理的元素的队列。

    转发队列:用来接收死信队列超时消息,在接收到之后,消费者将消息解析,获取queueName,body,再向所获取的queueName队列发送一条消息,内容为body。

    分析:首先rabbitmq自己是不具备延时的功能的,除了使用官方提供的插件之外,我们还可以通过TTL(设置超时时间的方式)+ DLX(一个死信队列) + Router(转发队列)来实现。

    4、怎么设置消息超时时间ttl?

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

    1、设置在队列上:如果设置了队列的TTL属性,那么一旦消息过期,就会被队列丢弃。

    2、ttl可以设置在消息上:消息即使过期,也不一定会被马上丢弃,因为消息是否过期是在即将投递到消费者之前判定的,如果当前队列有严重的消息积压情况,则已过期的消息也许还能存活较长时间。

    设置这个TTL值呢?有两种方式,2种是在创建队列的时候设置队列的“x-message-ttl”属性,如下:

    //第一种这样所有被投递到该队列的消息都最多不会存活超过6s。
    Map<String, Object> args = new HashMap<String, Object>();
    args.put("x-message-ttl", 6000);
    channel.queueDeclare(queueName, durable, exclusive, autoDelete, args);
    //第二种针对每条消息设置TTL
    AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
    builder.expiration("6000");
    AMQP.BasicProperties properties = builder.build();
    channel.basicPublish(exchangeName, routingKey, mandatory, properties, "msg body".getBytes());

    4、延时队列如何通过rabbitmq来实现呢?

    第一种:

      原理:生产者生产一条延时消息,根据需要延时时间的不同,设置不同的延时队列,每个队列都设置了不同的TTL属性,并绑定在同一个死信交换机中,消息过期后,根据routingkey的不同,又会被路由到不同的死信队列中,再等待消息超时,将消息转发到指定的Router队列。消费者只需要监听对应的死信队列进行处理即可。

    第二种:使用rabbitmq插件实现。

    如果不能实现在消息粒度上添加TTL,并使其在设置的TTL时间及时死亡,就无法设计成一个通用的延时队列。

    https://www.cnblogs.com/shihaiming/p/11081948.html

    https://www.cnblogs.com/mfrank/p/11260355.html

    
    
  • 相关阅读:
    第一章:绪论
    第二章 算法入门
    java基本语法特殊点
    css学习の第六弹—样式设置小技巧
    122. Best Time to Buy and Sell Stock II--easy
    121. Best Time to Buy and Sell Stock--easy
    Weekly Contest 129--1023. Binary String With Substrings Representing 1 To N--Medium
    Weekly Contest 129--1021. Best Sightseeing Pair--Medium
    Weekly Contest 129--1022. Smallest Integer Divisible by K--Medium
    Weekly Contest 129--1020. Partition Array Into Three Parts With Equal Sum--easy
  • 原文地址:https://www.cnblogs.com/lgg20/p/12521256.html
Copyright © 2020-2023  润新知