zoukankan      html  css  js  c++  java
  • 确保消息不会丢失

    现在主流的消息队列产品都提供了非常完善的消息可靠性保证机制,完全可以做到在消息传递过程中,即使发生网络中断或者硬件故障,也能确保消息的可靠传递,不丢消息。

    绝大部分丢消息的原因都是由于开发者不熟悉消息队列没有正确使用和配置消息队列导致的。虽然不同的消息队列提供的 API 不一样,相关的配置项也不同,但是在保证消息可靠传递这块儿,它们的实现原理是一样的。

    一、检测消息丢失的方法

    一般而言,一个新的系统刚刚上线,各方面都不太稳定,需要一个磨合期,这时候,特别需要监控到你的系统中是否有消息丢失的情况

    • 如果是 IT 基础设施比较完善的公司,一般都有分布式链路追踪系统,使用类似的追踪系统可以很方便地追踪每一条消息。
    • 如果没有这样的追踪系统,我们可以利用消息队列的有序性来验证是否有消息丢失。

    利用消息队列的有序性来验证是否有消息丢失的原理非常简单:

    在 Producer 端,我们给每个发出的消息附加一个连续递增的序号,然后在 Consumer 端来检查这个序号的连续性。如果没有消息丢失,Consumer 收到消息的序号必然是连续递增的,或者说收到的消息,其中的序号必然是上一条消息的序号 +1。如果检测到序号不连续,那就是丢消息了。还可以通过缺失的序号来确定丢失的是哪条消息,方便进一步排查原因。

    大多数消息队列的客户端都支持拦截器机制,你可以利用这个拦截器机制,在 Producer 发送消息之前的拦截器中将序号注入到消息中,在 Consumer 收到消息的拦截器中检测序号的连续性,这样实现的好处是消息检测的代码不会侵入到你的业务代码中,待你的系统稳定后,也方便将这部分检测的逻辑关闭或者删除。

    在一个分布式系统中实现这个检测方法,有几个问题需要你注意:

    • 像 Kafka 和 RocketMQ 这样的消息队列,它是不保证在 Topic 上的严格顺序的,只能保证分区上的消息是有序的,所以我们在发消息的时候必须要指定分区,并且,在每个分区单独检测消息序号的连续性
    • 如果你的系统中 Producer 是多实例的,由于并不好协调多个 Producer 之间的发送顺序,所以也需要每个 Producer 分别生成各自的消息序号,并且需要附加上 Producer 的标识,在 Consumer 端按照每个 Producer 分别来检测序号的连续性。
    • Consumer 实例的数量最好和分区数量一致,做到 Consumer 和分区一一对应,这样会比较方便地在 Consumer 内检测消息序号的连续性。

    二、确保消息可靠传递

    消息从生产到消费的过程中,可以划分三个阶段:

    1、生产阶段

    消息队列通过最常用的请求确认机制,来保证消息的可靠传递:当你代码调用发消息方法时,消息队列客户端会把消息发送到Broker,Broker收到消息后,会给客户端返回一个确认响应,表明消息已收到。客户端收到响应后,完成了一次正常消息的发送。

    有些消息队列在长时间没收到发送确认响应后,会自动重试,如果重试失败,就会以返回值或者异常的方式告知用户。在编写发送消息的代码时,需要注意,正确处理返回值或者捕获异常,就可以保证这个阶段的消息不会丢失。

    同步发送时,只要注意捕获异常即可。

    异步发送时,则需要在回调方法里进行检查。这个地方需要特别注意,很多丢消息的原因就是,我们使用了异步发送,却没有在回调中检查发送结果。

    2、存储阶段

    在存储阶段正常情况下,只要Broker在正常运行,就不会出现丢消息的问题;但是如果Broker出现故障,比如进程死掉或者服务器宕机,还是可能会丢失消息的。

    如果对消息的可靠性要求非常高,可以通过配置Broker参数来避免因为宕机丢消息:

    • 对于单个节点的 Broker,需要配置 Broker 参数,在收到消息后,将消息写入磁盘后再给 Producer 返回确认响应,这样即使发生宕机,由于消息已经被写入磁盘,就不会丢失消息,恢复后还可以继续消费。例如,在 RocketMQ 中,需要将刷盘方式 flushDiskType 配置为 SYNC_FLUSH 同步刷盘。
    • 对于 Broker 是由多个节点组成的集群,需要将 Broker 集群配置成:至少将消息发送到 2 个以上的节点,再给客户端回复发送确认响应。这样当某个 Broker 宕机时,其他的 Broker 可以替代宕机的 Broker,也不会发生消息丢失。

    3、消息阶段

    消费阶段采用和生产阶段类似的确认机制来保证消息的可靠传递,客户端从 Broker 拉取消息后,执行用户的消费业务逻辑,成功后,才会给 Broker 发送消费确认响应。如果 Broker 没有收到消费确认响应,下次拉消息的时候还会返回同一条消息,确保消息不会在网络传输过程中丢失,也不会因为客户端在执行消费逻辑中出错导致丢失。

    在编写消费代码时需要注意的是:不要在收到消息后就立即发送消费确认,而是应该在执行完所有消费业务逻辑之后,再发送消费确认

  • 相关阅读:
    Linux rcp命令详解
    Linux patch命令详解
    Linux paste命令详解
    linux od命令详解
    linux mv命令详解
    Linux more命令详解
    Linux mktemp命令
    MySQL状态变量详解
    mysql性能分析show profile/show profiles
    MySQL执行计划
  • 原文地址:https://www.cnblogs.com/chjxbt/p/11413993.html
Copyright © 2011-2022 走看看