消息队列高手课
李玥
美团高级技术专家
52199 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 42 讲
进阶篇 (21讲)
消息队列高手课
15
15
1.0x
00:00/00:00
登录|注册

05 | 如何确保消息不会丢失?

在处理完全部消费业务逻辑后发送消费确认
使用确认机制保证消息的可靠传递
集群模式下通过消息复制确保消息的可靠性
配置Broker参数来避免因宕机丢失消息
处理返回值或捕获异常来保证消息不会丢失
请求确认机制保证消息的可靠传递
如何处理重复消息以不影响业务逻辑的正确性
消费阶段
存储阶段
生产阶段
拦截器机制实现消息序号注入和连续性检测
利用消息队列的有序性验证消息是否丢失
思考题
确保消息可靠传递
检测消息丢失的方法
如何确保消息不会丢失

该思维导图由 AI 生成,仅供参考

你好,我是李玥。这节课我们来聊聊丢消息的事儿。
对于刚刚接触消息队列的同学,最常遇到的问题,也是最头痛的问题就是丢消息了。对于大部分业务系统来说,丢消息意味着数据丢失,是完全无法接受的。
其实,现在主流的消息队列产品都提供了非常完善的消息可靠性保证机制,完全可以做到在消息传递过程中,即使发生网络中断或者硬件故障,也能确保消息的可靠传递,不丢消息。
绝大部分丢消息的原因都是由于开发者不熟悉消息队列,没有正确使用和配置消息队列导致的。虽然不同的消息队列提供的 API 不一样,相关的配置项也不同,但是在保证消息可靠传递这块儿,它们的实现原理是一样的。
这节课我们就来讲一下,消息队列是怎么保证消息可靠传递的,这里面的实现原理是怎么样的。当你熟知原理以后,无论你使用任何一种消息队列,再简单看一下它的 API 和相关配置项,就能很快知道该如何配置消息队列,写出可靠的代码,避免消息丢失。

检测消息丢失的方法

我们说,用消息队列最尴尬的情况不是丢消息,而是消息丢了还不知道。一般而言,一个新的系统刚刚上线,各方面都不太稳定,需要一个磨合期,这个时候,特别需要监控到你的系统中是否有消息丢失的情况。
如果是 IT 基础设施比较完善的公司,一般都有分布式链路追踪系统,使用类似的追踪系统可以很方便地追踪每一条消息。如果没有这样的追踪系统,这里我提供一个比较简单的方法,来检查是否有消息丢失的情况。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了确保消息不丢失的方法,重点介绍了消息队列的可靠性保证机制。作者首先强调了正确使用和配置消息队列的重要性,然后详细介绍了检测消息丢失的方法,包括利用消息队列的有序性来验证是否有消息丢失。此外,文章还讨论了消息从生产到消费过程中可能导致消息丢失的地方,以及如何避免消息丢失。最后,总结了在生产、存储和消费阶段需要注意的事项,以确保消息的可靠传递。整体而言,本文为读者提供了实用的技术指导,帮助他们更好地理解消息队列的可靠性保证机制。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《消息队列高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(143)

  • 最新
  • 精选
  • 如何确保消息不会丢失 1:WAL 2:分布式WAL 除非地球爆炸,否则问题不大。 猜测各种消息队列或者数据库,确保消息不丢只能这么玩,就连人也一样,脑袋记不住那就写下来,怕本子弄潮啦!那就光盘、U盘、磁盘、布头、木头、石头北京、上海、深圳都各写一份。 consumer接到重复消息,那就业务去重,怎么去? 1:业务处理逻辑本身就是幂等的,那天然就去掉了 2:业务处理逻辑非幂等,那就消息先去重,根据业务ID(标识消息唯一性的就行),去查询是否消费过此消息了,消费了,则抛弃,否则就消费

    作者回复: 没毛病,很多底层的方法和技术就是通用的

    2019-08-20
    4
    117
  • ly
    老师,我有几个理解: 当produer发送消息给blocker的时候(send方法),此方法会在blocker收到消息并正常储存后才返回,此期间应该会阻塞,也就是如果blocker配置同步刷盘,可能会增加调用时间(只能出现对消息敏感的场景)。 另外拉消息的时候,消费者A进行pull后,没有返回确认给blocker就挂了(或者因代码问题导致一直阻塞),这时消息应该还在blocker的,消费者B如果此时pull消息,是否会拉取到刚刚那条给消费者A的消息?衍生的疑问就是两个消费者先后去拉消息是否能拉到同一条消息(在前者未给blocker发确认的前提下)。 对于消费者处理重复消息的问题:一般消息中都会存在一个唯一性的东西,不管是消息队列本身的msgId还是业务订单号之类的,可以在db中存在一个消费表,对这个唯一性东西建立唯一索引,每次处理消费者逻辑之前先insert进去,让数据库来帮我们排重我觉得是最保险的。

    作者回复: 两个消费者先后去拉消息是否能拉到同一条消息? 首先,消息队列一般都会有协调机制,不会让这种情况出现,但是由于网络不确定性,这种情况还是在极小概率下会出现的。 在同一个消费组内,A消费者拉走了index=10的这条消息,还没返回确认,这时候这个分区的消费位置还是10,B消费者来拉消息,可能有2种情况: 1. 超时前,Broker认为这个分区还被A占用着,会拒绝B的请求。 2. 超时后,Broker认为A已经超时没返回,这次消费失败,当前消费位置还是10,B再来拉消息,会给它返回10这条消息。

    2019-08-02
    5
    71
  • 王立光
    假如消费时由于某种原因,一直没发ack。rocketmq是不是会一直发这条消息,这样导致下面消息都无法被消费?

    作者回复: 是的。 rocketmq为了解决这个问题,增加了一个死信队列,对于这种反复投递都无法成功的消息,会被移动到死信队列中,避免卡住其他消息。

    2019-08-15
    5
    61
  • 南山
    老师,再看一次这个的时候有个疑问: 1,broker给producer发送ack,网络原因或者其他原因producer没收到,这种情况broker这条消息怎么办? 2,broker给producer发送ack,broker怎么知道producer有没有成功收到这条ack信息呢?

    作者回复: Broker不知道ack有没有送达到producer,它也不管是不是送达了。 因为,这个阶段的消息可靠性是由producer来保证的,它发了消息,收到了ack,那消息就一定送达了。如果没收到ack,那消息有可能送达了(ack丢失),也有可能没送达(消息丢失),对于这种情况,producer一般会重发消息,确保消息送达。这也就是为什么消息会有重复的原因之一。

    2019-10-19
    2
    34
  • 陈天柱
    老师您好,我最近处理一个分布式事务场景,就是支付成功以后回调处理刷新订单状态和刷新优惠券状态的分布式事务问题。我有一个疑问就是,假如刷新订单状态失败,就没有发消息到队列中,而是在刷新订单状态成功了以后,再发消息到队列中,只要保证消息不丢的前提下,分布式事务能得到保证吗?换言之,就是消息不丢的话,可以保证最终一致性,事务消息的回查也能保证最终一致性,两者的概念感觉有一些交集。所以希望老师能抽空帮忙分析一下,万分感谢🙏

    作者回复: 你这个例子中,最终一致性应该是指:“经过一段时间后,订单状态和优惠券状态最终会保持一致。” 但是,你这个场景不太适合使用事务消息来解决,虽然和我们上节课中的例子相比,只是把购物车换成了优惠券。但你有没有考虑到,有人会恶意利用这个短暂的不一致时间来刷优惠券?比如,利用下单成功,但优惠券还没来得及扣减这个时间差,一个优惠券反复下单?

    2019-10-19
    4
    27
  • QQ怪
    建议老师加餐如何做幂等性

    作者回复: 不用加餐,这是教学大纲内的内容,下节课就会讲到滴。

    2019-08-01
    15
  • angel😇txy🤓
    思考题,从两个环节展开,生产端到broker,MQ系统内部必须生成一个inner-msg-id,作为去重和幂等的依据,这个内部消息ID的特性是: (1)全局唯一 (2)MQ生成,具备业务无关性,对消息发送方和消息接收方屏蔽 有了这个inner-msg-id,就能保证上半场重发,也只有1条消息落到MQ-server的DB中,实现上半场幂等。 broker到consumer,由消费端做好幂等性,比如根据业务流水号去重

    作者回复: 这个总结非常到位!

    2019-08-20
    7
    14
  • 皮蛋
    rocketmq默认失败重试次数是2,如果2次均失败,或者说重试次数都失败了,这种情况一般在实际生产中是怎么处理的?

    作者回复: 放到私信队列中,人工处理。

    2019-08-04
    4
    14
  • 游弋云端
    1、消费端支持幂等操作,业务上一般有难度; 2、消费端增加去冗余机制,例如缓存最新消费成功的N条消息的SN,收到消息后,先确认是否是消费过的消息,如果是,直接应该ACK,并放弃消费。

    作者回复: 思路是没问题的。

    2019-08-01
    11
  • TH
    幂等性是一种办法,如果做不到幂等性,那么在消费端需要存储消费的消息ID,关键这个ID什么时候存?如果是消费前就存,那么消费失败了,下次消费同样的消息,是否会认为上次已经成功了?如果在消费成功后再存,那么消费会不会出现部分成功的情况?除非满足事务ACID特性。 关于消息丢失检查还有一点疑问:如果靠ID连续性来检查,是不是说一个producer只能对应一个consumer?

    作者回复: 不用,Producer发消息的时候带着ProducerId并要指定分区发送,Consumer消费的时候,需要按照每个Producer来检查序号的连续性。

    2019-08-01
    10
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部