消息队列的可靠性

作者: Tim在路上 | 来源:发表于2019-05-10 12:00 被阅读3次

RabbitMQ可能存在的数据丢失问题

数据丢失分为三类:

  1. 生产者:生产者写消息存在丢失或者MQ接受存在问题

  2. MQ : MQ接受到数据先暂存在内存中,消费者还没有消费,MQ挂掉,缓存丢失。

  3. 消费者:消费拉取到消息还没处理直接挂掉,但MQ以为对方收到消息。

解决方法

生产者: rabbitMQ支持事务,可以在发送中进行捕获异常,如果出现未接受异常进行回滚操作。

但是rabbitMQ事务操作太耗费性能,因为为了保证可靠性,需要同步等待机制,等待你成功。

confirm机制,先设置 channel 为confirm,如果接受到消息,回调这个接口,接受成功。如果没接收,调用回调接口,接收失败。

MQ : 防止MQ突然挂掉内存数据丢失,就需要将MQ持久化到磁盘。第一个是创建queue的时候将其设置为持久化的,这样就可以保证rabbitmq持久化queue的元数据,但是不会持久化queue里的数据;第二个是发送消息的时候将消息的deliveryMode设置为2,就是将消息设置为持久化的,此时rabbitmq就会将消息持久化到磁盘上去。

消费者 : rabbitmq如果丢失了数据,主要是因为你消费的时候,刚消费到,还没处理,结果进程挂了,比如重启了,那么就尴尬了,rabbitmq认为你都消费了,这数据就丢了。

这个时候得用rabbitmq提供的ack机制,简单来说,就是你关闭rabbitmq自动ack,可以通过一个api来调用就行,然后每次你自己代码里确保处理完的时候,再程序里ack一把。这样的话,如果你还没处理完,不就没有ack?那rabbitmq就认为你还没处理完,这个时候rabbitmq会把这个消费分配给别的consumer去处理,消息是不会丢的。

Kafka可能存在的数据丢失问题

消费者 : 唯一可能导致消费者弄丢数据的情况,就是说,你那个消费到了这个消息,然后消费者那边自动提交了offset。关闭自动提交offset,在处理完之后自己手动提交offset,就可以保证数据不会丢。同时自己要用程序保证幂等性。

kafka : kafka某个broker宕机,然后重新选举partiton的leader时。大家想想,要是此时其他的follower刚好还有些数据没有同步,结果此时leader挂了,然后选举某个follower成leader之后,他不就少了一些数据.

所以此时一般是要求起码设置如下4个参数:

给这个topic设置replication.factor参数:这个值必须大于1,要求每个partition必须有至少2个副本

在kafka服务端设置min.insync.replicas参数:这个值必须大于1,这个是要求一个leader至少感知到有至少一个follower还跟自己保持联系,没掉队,这样才能确保leader挂了还有一个follower吧

在producer端设置acks=all:这个是要求每条数据,必须是写入所有replica之后,才能认为是写成功了

在producer端设置retries=MAX(很大很大很大的一个值,无限次重试的意思):这个是要求一旦写入失败,就无限重试,卡在这里了

我们生产环境就是按照上述要求配置的,这样配置之后,至少在kafka broker端就可以保证在leader所在broker发生故障,进行leader切换时,数据不会丢失

生成者 : 如果按照上述的思路设置了ack=all,一定不会丢,要求是,你的leader接收到消息,所有的follower都同步到了消息之后,才认为本次写成功了。如果没满足这个条件,生产者会自动不断的重试,重试无限次。

保证消息队列顺序性

rabbitmq:一个queue,多个consumer。因为多个 消费者是并行运行,最后的结果可能会乱序。

解决办法: 就是为每一个机器设置一个queue,然后如果要求有序的数据必须确保发到同一个queue中,那么数据的接受就不会乱序。

kafka:一个topic,一个partition,一个consumer,内部多线程.

kafka写到一个partition中的数据一定是有数据的。

解决办法: 一个topic,一个partition,一个consumer,内部单线程消费,写N个内存queue,然后N个线程分别消费一个内存queue即可,既消费者不要使用多线程进行处理。或者你想多线程进行处理,你可以建立一个内存队列,通过hash进任务id相同分到一个内存队列,每一个内存队列对应一个线程。

相关文章

  • 消息队列,你应该注意什么

    提到消息队列,相信大家都不陌生,本文主要在于抛砖引玉,简要介绍一下消息队列的几个问题 1.可靠性 消息队列的可靠性...

  • 消息队列的可靠性

    RabbitMQ可能存在的数据丢失问题 数据丢失分为三类: 生产者:生产者写消息存在丢失或者MQ接受存在问题 MQ...

  • 如何避免消息队列的重复消费

    消息队列在数据传输的过程中,为了保证消息传递的可靠性,一般会对消息采用ack确认机制,如果消息传递失败,消息队列会...

  • win10使用RabbitMQ实现消息队列

    第三方消息队列服务RabbitMQ RabbitMQ简介 可靠性(Reliability):RabbitMQ 使用...

  • 消息队列常见问题

    如何保证消息队列的高可用? 如何保证消息不被重复消费(幂等性问题)? 如何保证消息的可靠性传输(消息丢失问题)? ...

  • 高级功能

    消息存储 分布式队列因为有高可靠性的要求,所以数据要进行持久化存储。 消息生成者发送消息 MQ收到消息,将消息进行...

  • 5、RocketMQ高级功能-消息存储

    RocketMQ高级功能 消息存储 分布式队列因为有高可靠性的要求,所以数据要进行持久化存储。 消息生成者发送消息...

  • rabbitmq的特点

    可靠性∶RabbitMQ使用一些机制来保证可靠性,如持久化、传输确认及发布确认等。 灵活的路由∶在消息进入队列之前...

  • 第6章 可靠性优先的使用场景

    本章的重点是可靠性,解决如何让消息队列满足业务逻辑需求,同时稳定、可靠地长期运行。 6.1 顺序消息 顺序消息是指...

  • 高级功能

    1. 高级功能 1.1 消息存储 分布式队列因为有高可靠性的要求,所以数据要进行持久化存储。 消息生成者发送消息 ...

网友评论

    本文标题:消息队列的可靠性

    本文链接:https://www.haomeiwen.com/subject/hiqooqtx.html