RabbitMQ消息丢失问题和保证消息可靠性-消费端不丢消息和HA(二)

继续上篇文章解决RabbitMQ消息丢失问题和保证消息可靠性(一) 未完成部分,我们聊聊MQ Server端的高可用和消费端如何保证消息不丢的问题?

回归上篇的内容,我们知道消息从生产端到服务端,为了保证消息不丢,我们必须做哪些事情?

  • 发送端采用Confirm模式,注意Server端没成功通知发送端,需要重发操作需要额外处理
  • 消息的持久化处理

上面两个操作保证消息到服务端不丢,但是非高可用状态,如果节点挂掉,服务暂时不可用,需要重启后,消息恢复,消息不会丢失,因为有磁盘存储。

本文先从消费端讲起:

RabbitMQ Server到消费者消息如何不丢?

上面一篇文章也提到了,消费者获取到消息之后,没有来得及处理完毕,自己直接宕机了,因为消息者默认采用自动ack,此时RabbitMQ的自动ack机制会通知MQ Server这条消息已经处理好了,此时消息就丢了,并不是预期的。

那么我们采用手动ack机制来解决这个问题,消费端处理完逻辑之后再通知MQ Server,这样消费者没处理完消息不会发送ack,如果在消费者拿到消息,没来得及处理的情况下自己挂了,此时MQ集群会自动感知到,它就会自觉的重发消息给其他的消费者服务实例。

根据上面的思路你需要完成下面的两步操作:

第一:消费者监听设置手动ack

  1. this.channel = channelManager.getListenerChannel(namespace);
  2. this.queue = queue;
  3. this.channel.basicConsume(queue, false, consumerTag, this);
  4. this.disconnectedCallback.setChannel(channel);

核心代码: this.channel.basicConsume(queue, false, consumerTag, this); 第二个参数设置 false 代表不自动ack

第二:业务执行完成后手动ack

  1. public static void ack(MessageContext context) {
  2. long deliveryTag = context.getEnvelope().getDeliveryTag();
  3. try {
  4. context.getChannel().basicAck(deliveryTag, false);
  5. } catch (IOException e) {
  6. throw new MqAckException("消息ack出错:连接异常或远端关闭", context, e);
  7. }
  8. }

核心代码: context.getChannel().basicAck(deliveryTag, false);

这里封装来,需要业务在执行完自己的业务代码后,调用对象channel 的ack方法通知MQServer,说我这边执行完了,你可以删除了。

注意这里有个问题: 如果忘记调用这个 context.getChannel().basicAck(deliveryTag, false);

或者因为代码异常,这个代码没被执行,会怎么样?后面找时间再写一篇文章讲这个问题。

RabbitMQ Server中存储的消息高可用

当我们解决了,生产端和消费端的问题后,基本保证消息的不丢问题,但是还有一个是消息的高可用问题,单节点问题,普通节点的问题都会影响消息的临时不可用,这个时候要用上我们的HA 镜像集群模式来保证。

上一篇文章 解决RabbitMQ消息丢失问题和保证消息可靠性(一) 已经提到过,服务端消息部署的三种模式的区别,今天就专门讲镜像模式的介绍。

镜像模式至少采用3节点,2个磁盘节点和1个内存节点来保证,架构图:

设置镜像也有一些策略:

  • 同步至所有的,一般不这么做,性能会受到极大影响
  • 同步最多N个机器
  • 只同步至符合指定名称的nodes

命令处理HA策略模版:rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority]

  1. 为每个以“rock.wechat”开头的队列设置所有节点的镜像,并且设置为自动同步模式
  1. rabbitmqctl set_policy ha-all "^rock.wechat" ‘{"ha-mode":"all","ha-sync-mode":"automatic"}‘
  2. rabbitmqctl set_policy -p rock ha-all "^rock.wechat" ‘{"ha-mode":"all","ha-sync-mode":"automatic"}‘
  1. 为每个以“rock.wechat.”开头的队列设置两个节点的镜像,并且设置为自动同步模式
  1. rabbitmqctl set_policy -p rock ha-exacly "^rock.wechat" \
  2. ‘{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}‘
  1. 为每个以“node.”开头的队列分配指定的节点做镜像
  1. rabbitmqctl set_policy ha-nodes "^nodes\." \
  2. ‘{"ha-mode":"nodes","ha-params":["[email protected]", "[email protected]"]}‘

但是:HA 镜像队列有一个很大的缺点就是: 系统的吞吐量会有所下降

所以采用镜像模式,要根据具体的业务规则定制话处理,没那么重要的业务,消息丢了也没关系的场景,又要求必须高的性能的时候,镜像也可以不用设置。

总结

两篇文章的讲解,分析了消息中间件高可用问题的大概的思路,没有具体的代码详细,如有疑问可以下方留言评论,我会及时回复解答,后面我会逐步完善相关细节,欢迎多多关注。

后面计划更新文章如下:

  • 什么情况会导致重复消费并怎么解决?
  • 什么样的真实业务场景需要保障顺序性和如何保证消息的顺序性?
  • 如何通过消息队列优雅的解决微服务间接口失败的重试?

推荐阅读

解决RabbitMQ消息丢失问题和保证消息可靠性(一)

IntelliJ IDEA提升效率开发插件必备

END

如有收获,请帮忙转发,后续会有更好文章贡献,您的鼓励是作者最大的动力!

欢迎关注我的公众号:架构师的修炼,获得独家整理的学习资源和日常干货推送。

原文地址:https://www.cnblogs.com/flyrock/p/11437512.html

时间: 2024-10-28 22:01:37

RabbitMQ消息丢失问题和保证消息可靠性-消费端不丢消息和HA(二)的相关文章

解决RabbitMQ消息丢失问题和保证消息可靠性(一)

原文链接(作者一个人):https://juejin.im/post/5d468591f265da03b810427e 工作中经常用到消息中间件来解决系统间的解耦问题或者高并发消峰问题,但是消息的可靠性如何保证一直是个很大的问题,什么情况下消息就不见了?如何防止消息丢失?下面通过这篇文章,我们就聊聊RabbitMQ 消息可靠性如何解决的? 本文分三部分说明 RabbitMQ 消息丢失场景有哪些? 如何避免消息丢失? 如何设计部署消息中间件保证消息可靠性? RabbitMQ 消息丢失场景有哪些?

如何保证消息的可靠性传输?或者说,如何处理消息丢失的问题?

面试题 面试官心理分析 这个是肯定的,用 MQ 有个基本原则,就是数据不能多一条,也不能少一条,不能多,就是前面说的重复消费和幂等性问题.不能少,就是说这数据别搞丢了.那这个问题你必须得考虑一下. 如果说你这个是用 MQ 来传递非常核心的消息,比如说计费.扣费的一些消息,那必须确保这个 MQ 传递过程中绝对不会把计费消息给弄丢. 面试题剖析 数据的丢失问题,可能出现在生产者.MQ.消费者中,咱们从 RabbitMQ 和 Kafka 分别来分析一下吧. RabbitMQ 生产者弄丢了数据 生产者将

消费端如何保证消息队列MQ的有序消费

消息无序产生的原因 消息队列,既然是队列就能保证消息在进入队列,以及出队列的时候保证消息的有序性,显然这是在消息的生产端(Producer),但是往往在生产环境中有多个消息的消费端(Consumer),尽管消费端在拉取消息时是有序的,但各个消息由于网络等方面原因无法保证在各个消费端中处理时有序. 场景分析 先后两次修改了商品信息,消息A和消息B先后同步写入MySQL,接着异步写入消息队列中发送消息,此时消息队列生产端(Producer)按时序先后发出了A和B两条消息(消息A先发出,消息B后发出)

kafka什么时候会丢消息(转)

因为在具体开发中某些环节考虑使用kafka却担心有消息丢失的风险,本周结合项目对kafka的消息可靠性做了一下调研和总结: 首先明确一下丢消息的定义.kafka集群中的部分或全部broker挂了,导致consumer没有及时收到消息,这不属于丢消息.broker挂了,只要消息全部持久化到了硬盘上,重启broker集群之后,使消费者继续拉取消息,消息就没有丢失,仍然全量消费了. 以我的理解,所谓丢消息,意味着:开发人员未感知到哪些消息没有被消费. 我把消息的丢失归纳了以下几种情况: 1). pro

RabbitMQ,为应对消息从发送到消费,各个环节消息丢失的解决方案

1.发送方   为保证消息到达exchange,在这个过程中不丢失.  用事务或者发送方确认机制  见<RabbitMQ实战指南>4.8节 2.为保证消息不会因为到达exchange后,无法路由到任何一个队列而丢失 解决方案一:发送方发送消息时 令mandatory参数=true,用ReturnListener异步接收没有任何队列接收而返回给发送方的消息.  见<RabbitMQ实战指南>4.1.1节 解决方案二:给exchange指定一个备份交换器及对应队列,到达交换器的消息如何

Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性?

1.kafka在高并发的情况下,如何避免消息丢失和消息重复? 消息丢失解决方案: 首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的所有处于ISR的分区都确认收到该消息后,才算发送成功 消息重复解决方案: 消息可以使用唯一id标识 生产者(ack=all 代表至少成功发送一次) 消费者 (offset手动提交,业务逻辑成功处理后,提交offset) 落表(主键或者唯一索引的方式,避免重复数据) 业务逻辑处理(选择唯一主键存储到R

rabbitmq 重复ACK导致消息丢失

rabbitmq 重复确认导致消息丢失 背景 rabbitmq 在应用场景中,大多采用工作队列 work-queue的模式. 在一个常见的工作队列模式中,消费者 worker 将不断的轮询从队列中拉取最新消息,当队列负载压力增大时允许添加多个worker 进行处理.然而执行一个任务可能需要相当的时长,这是由业务特性所决定的:如果 worker执行任务过程中出现异常甚至宕机,此时消息便会丢失,这是简单消息队列难以解决的问题. rabbitmq 采用了消息确认机制来防止此类问题,在该机制中,work

RabbitMQ-从基础到实战(2)— 防止消息丢失

未经允许,禁止转载! 1.简介 RabbitMQ中,消息丢失可以简单的分为两种:客户端丢失和服务端丢失.针对这两种消息丢失,RabbitMQ都给出了相应的解决方案. 2.防止客户端丢失消息 如图,生产者P向队列中生产消息,C1和C2消费队列中的消息,默认情况下,RabbitMQ会平均的分发消费给C1C2(Round-robin dispatching),假设一个任务的执行时间非常长,在执行过程中,客户端挂了(连接断开),那么,该客户端正在处理且未完成的消息,以及分配给它还没来得及执行的消息,都将

im消息丢失插件

https://github.com/laughin/mocamsg mocamsg Moca message interceptor Openfire网络不好的情况下经常丢消息,一般情况都是服务器端路由到客户端的时候发生的,所以利用Openfire的插件机制,进行消息的拦截,对所有拦截到的消息进行缓存,保证消息在服务端一定不会丢失.增加Redis缓存层,把所有在线消息都保存至Redis,利用消息回执机制,Client收到消息会根据该条消息的messageId发出一个消息回执到Redis,Red