首页 > 其他 > 详细

Mq消息的常见面试题

时间:2020-11-30 15:28:45      阅读:25      评论:0      收藏:0      [点我收藏+]

一、消息队列如何解决消息不会丢失问题

消息从生产到消费可以经历三个阶段:生产阶段、存储阶段和消费阶段。

  • 生产阶段:在这个阶段,从消息在Producer创建出来,经过网络传输发送到Broker端。
  • 存储阶段: 消息在Broker端存储,如果是集群,消息会在这个阶段被复制到其他的副本上。
  • 消费阶段:Consumer从Broker上拉取消息,经过网络 传输发送在Consumer上。
 
技术分享图片
 

 

在这三个阶段都存在消息可能丢失的情况。

  • 生产阶段:消息队列通常使用确认机制,来保证消息可靠传递:当你代码调用发送消息的方法,消息队列的客户端会把消息发送到Broker,Broker接受到消息会返回客户端一个确认。只要Producer收到了Broker的确认响应,就可以保证消息在生产阶段不会丢失。有些消息队列在长时间没收到发送的确认响应后,会自动重试,如果重试再失败,就会一返回值或者异常方式返回给客户端。所以在编写发送消息的代码,需要正确处理消息发送返回值或者异常,保证这个阶段消息不丢失。
  • 存储阶段:如果对消息可靠性要求非常高,可以通过配置Broker参数来避免因为宕机丢消息。对于单个节点Broker,需要配置Broker参数,在收到消息后,将消息写入磁盘再给Producer返回确认响应。如果是Broker集群,需要将Broker集群配置成:至少两个以上节点收到消息,再给客户端发送确认响应。
  • 消费阶段:消费阶段采用和生产阶段类似的确认机制来保证消息的可靠传递。Consumer收到消息后,需在执行消费逻辑后在发送确认消息。

总结:

  • 生产阶段,需要捕获消息发送错误,并重发消息
  • 存储阶段,通过配置刷盘和复制参数,让消息写入多个副本的磁盘上,来确保消息不会因为某个Broker宕机或者磁盘损坏而丢失。
  • 消费阶段:需要在处理完全部消费业务逻辑后,再发送确认消息。

 二、解决消息不会重复消费

  • 幂等性:一个请求,不管重复来多少次,结果是不会改变的。

  • RabbitMQ、RocketMQ、Kafka等任何队列不保证消息不重复,如果业务需要消息不重复消费,则需要消费端处理业务消息要保持幂等性

    • 方式一:Redis的setNX() , 做消息id去重 java版本目前不支持设置过期时间
    //Redis中操作,判断是否已经操作过 TODO
    boolean flag =  jedis.setNX(key);
    if(flag){
            //消费
    }else{
            //忽略,重复消费
    }
    • 方式二:redis的 Incr 原子操作:key自增,大于0 返回值大于0则说明消费过,(key可以是消息的md5取值, 或者如果消息id设计合理直接用id做key)
    int num =  jedis.incr(key);
    if(num == 1){
    	//消费
    }else{
    	//忽略,重复消费
    }
    • 方式三:数据库去重表

      • 设计一个去重表,某个字段使用Message的key做唯一索引,因为存在唯一索引,所以重复消费会失败

        CREATE TABLE message_record ( id int(11) unsigned NOT NULL AUTO_INCREMENT, key varchar(128) DEFAULT NULL, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY key (key) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Mq消息的常见面试题

原文:https://www.cnblogs.com/guanyuehao0107/p/14060611.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!