继续上篇文章解决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":["rabbit@nodeA", "rabbit@nodeB"]}'

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

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

总结

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

后面计划更新文章如下:

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

推荐阅读

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

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

END

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

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

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

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

    原文链接(作者一个人):https://juejin.im/post/5d468591f265da03b810427e 工作中经常用到消息中间件来解决系统间的解耦问题或者高并发消峰问题,但是消息的可靠 ...

  2. RabbitMQ-消费者"未处理完的消息"丢失

    一个关于客户端(消费者)开启自动应答,重启后"未处理消息丢失"的小坑.(主要是对RabbitMQ理解不够) 首先,申明一下: 本文所谓的 "丢失消息" 不是指服 ...

  3. 如何保证mq不丢消息

    1.消息的发送流程 一条消息从生产到被消费,将会经历3个阶段 生产阶段,Producer 新建消息,然后通过网络将消息投递给MQ Broker 存储阶段,消息将会存储在Broker端磁盘中 消费阶段, ...

  4. MQ的消息丢失/重复/积压的问题解决

    在我们实际的开发过程中,我们肯定会用到MQ中间件,常见的MQ中间件有kafka,RabbitMQ,RocketMQ.在使用的过程中,我们必须要考虑这样一个问题,在使用MQ的时候,我们怎么确保消息100 ...

  5. kafka实现无消息丢失与精确一次语义(exactly once)处理

    在很多的流处理框架的介绍中,都会说kafka是一个可靠的数据源,并且推荐使用Kafka当作数据源来进行使用.这是因为与其他消息引擎系统相比,kafka提供了可靠的数据保存及备份机制.并且通过消费者位移 ...

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

    消息无序产生的原因 消息队列,既然是队列就能保证消息在进入队列,以及出队列的时候保证消息的有序性,显然这是在消息的生产端(Producer),但是往往在生产环境中有多个消息的消费端(Consumer) ...

  7. activemq热备与消息丢失

    1. 解压 tar -zxvf apache-activemq-5.12.0-bin.tar.gz2. 改名 mv apache-activemq-5.12.0 activemq3. cd activ ...

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

    因为在具体开发中某些环节考虑使用kafka却担心有消息丢失的风险,本周结合项目对kafka的消息可靠性做了一下调研和总结: 首先明确一下丢消息的定义.kafka集群中的部分或全部broker挂了,导致 ...

  9. 【Microsoft Azure学习之旅】测试消息队列(Service Bus Queue)是否会丢消息

    组里最近遇到一个问题,微软的Azure Service Bus Queue是否可靠?是否会出现丢失消息的情况? 具体缘由如下, 由于开发的产品是SaaS产品,为防止消息丢失,跨Module消息传递使用 ...

随机推荐

  1. python迭代器-迭代器取值-for循环-生成器-yield-生成器表达式-常用内置方法-面向过程编程-05

    迭代器 迭代器 迭代: # 更新换代(其实也是重复)的过程,每一次的迭代都必须基于上一次的结果(上一次与这一次之间必须是有关系的) 迭代器: # 迭代取值的工具 为什么用迭代器: # 迭代器提供了一种 ...

  2. 简单的JSP分页显示

    1.mysql的limit关键字 (DAO) select * from tablename limit startPoint, numberPerPage; tablename 就是要分页显示的那张 ...

  3. 【MySQL】

    org.springframework.dao.CannotAcquireLockException: PreparedStatementCallback; Lock wait timeout exc ...

  4. Android开发——通过wifi接收IPCamera视频流

    前面,我们已经了解了怎么在android app上打开关闭和扫描,搜索wifi,现在,我来写一下怎么通过连接wifi来使app获取到IPCamera摄像头的视频. 一.通过URL获取视频的地址 二.创 ...

  5. 浅析java中的语法糖

    概述 编译器是一种计算机程序, 它主要的目的是将便于人编写.阅读.维护的高级计算机语言所写的源代码程序, 翻译为计算机能解读.运行的低阶机器语言的程序, 即可执行文件.而 javac 就是java语言 ...

  6. 进军pc市场 华为剑走偏锋可有戏?

    尽管官方并未正式公布,但在前段时间,华为将要进军PC市场的消息在业内传得沸沸扬扬,据知情人士曝料,其第一款个人电脑将在今年4月上线.而华为将进军PC市场的消息,对其他智能手机厂商来说又意味着什么呢? ...

  7. ECharts图表插件(4.x版本)使用(一、关系图force节点显示为自定义图像/图片,带分类选择)

    导读 ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safar ...

  8. 夯实Java基础(一)——数组

    1.Java数组介绍 数组(Array):是多个相同类型元素按一定顺序排列的集合. 数组是编程中最常见的一种数据结构,可用于存储多个数据,每个数组元素存放一个数据,通常我们可以通过数组元素的索引来访问 ...

  9. win系统上Anaconda国内镜像配置

    清华镜像2019.6.15已恢复 中科大镜像2019.7.1停机维护后恢复 1.打开anaconda prompt 2.添加清华镜像1:https://mirrors.tuna.tsinghua.ed ...

  10. 制造资源计划(Manufacturing Resource Planning,Mrp II)

        制造资源计划(Manufacturing Resource Planning,Mrp II)       概括: 以物料需求计划(MRP)为核心的企业生产管理计划系统,MRP II 是以工业工 ...