mq如何保证高可用,解决重复消费、数据丢失问题和顺序性问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mq如何保证高可用,解决重复消费、数据丢失问题和顺序性问题相关的知识,希望对你有一定的参考价值。
参考技术Arabbitmq有三种模式: 单机模式,普通集群模式,镜像集群模式
kafka架构:多个broker组成,每个broker是一个节点;创建一个topic,这个topic可以划分为多个partition,每个partition可以存在于不同的broker上,每个partition就放一部分数据。
它是一个分布式消息队列,就是说一个topic的数据,是分散放在多个机器上的,每个机器就放一部分数据。
kafka 0.8以前,是没有HA机制的,就是任何一个broker宕机了,那个broker上的partition就废了,没法写也没法读,没有什么高可用性可言。
kafka 0.8以后,提供了HA机制,就是replica副本机制。每个partition的数据都会同步到吉他机器上,形成自己的多个replica副本。然后所有replica会选举一个leader出来,那么生产和消费都跟这个leader打交道,然后其他replica就是follower。写的时候,leader会负责把数据同步到所有follower上去,读的时候就直接读leader上数据即可。kafka会均匀的将一个partition的所有replica分布在不同的机器上,从而提高容错性。
如果某个broker宕机了也没事,它上面的partition在其他机器上都有副本的,如果这上面有某个partition的leader,那么此时会重新选举一个新的leader出来,大家继续读写那个新的leader即可。这就有所谓的高可用性了。
写数据的时候,生产者就写leader,然后leader将数据落地写本地磁盘,接着其他follower自己主动从leader来pull数据。一旦所有follower同步好数据了,就会发送ack给leader,leader收到所有follower的ack之后,就会返回写成功的消息给生产者。
消费的时候,只会从leader去读,但是只有当消息已经被所有follower都同步成功返回ack的时候,这个消息才会被消费者读到。
kafka重复消费的情况:
kafka有个offset的概念,就是每个消息写进去,都有一个offset,代表他的序号,然后consumer消费了数据之后,每隔一段时间,会把自己消费过的消息的offset提交一下,下次重启时,从上次消费到的offset来继续消费。但是offset没来得及提交就重启,这部分会再次消费一次。
怎么保证消息队列消费的幂等性:
丢数据,mq一般分为两种,要么是mq自己弄丢了,要么是我们消费的时候弄丢了
拆分多个queue,每个queue一个consumer,就是多一些queue而已,确实是麻烦点;或者就一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理
写入一个partition中的数据一定是有序的,生产者在写的时候 ,可以指定一个key,比如指定订单id作为key,这个订单相关数据一定会被分发到一个partition中去。消费者从partition中取出数据的时候也一定是有序的,把每个数据放入对应的一个内存队列,一个partition中有几条相关数据就用几个内存队列,消费者开启多个线程,每个线程处理一个内存队列。
消息队列重复消费和数据丢失问题(石衫面试突击学习笔记)
消息队列重复消费问题
首先介绍一下什么叫做消息重复消费的问题:
所以第二个问题来了,怎么保证消息队列的幂等性?
其实还是的结合业务来思考,这里有几个思路:
比如你要拿个数据写库,你先根据主键查询一下,如果这数据有了,就不要插入了,就update一下
如果是写redis,那没有关系,每次都是set天然的幂等
如果不是上面两个场景,实际稍微复杂一点,你需要让生产者发送消息的时候,每条数据加上一个全局的唯一id,类似于订单id之内的东西,然后你这里消息到了之后,先根据这个id去redis里面查询一下,判断一下之前有消费过吗?如果没有消息就进行处理,然后把id写入redis。如果消费过来,就不要进行处理,保证别重复处理相同消息即可
具体如何保证MQ的消息幂等,还得的结合具体业务进行分析
如何保证消息可靠性传输(如何处理消息丢失问题)?
RabbitMQ:
生产者弄丢了数据
rabbitMQ弄丢数据:
消费者弄丢了数据:
再rabbitMQ中,消费者弄丢数据只有一种可能,就是使用了默认autoAck机制,当你的消费者使用默认机制消费数据时,刚好你接收到一条消息的时候,你的消费者挂了,因为你用的是自动提交机制,此时RabbitMQ会认为你的消息消费了,就会给你传下一条消息过来消费,所以造成了消息丢失
消费者端进行消息消费需要改成手动ack,只有当你程序正常运行完后,你才会收到去提交akc,所以不会导致消息丢失
kafka:
消费端弄丢了数据:
kafka弄丢了数据:
所以此时一般是要求起码设置如下4个参数:
给这个topic设置replication.factor参数:这个值必须大1,要求每个partition必须至少有2个副本
在kafka服务端设置min.insync.replicas参数:这个值必须大于1,这是要求一个leader至少感知到有至少一个follower跟自己保持联系,没有掉队,这样才能确保leader挂了还有一个follower
在producer端设置acks=all:这个是要求每条数据,必须是写入所有的replica之后,才能认为是写入成功
在producer端设置retries=MAX:这是是要求一旦写入失败,就无限重试,卡在这里
生产者端:
以上是关于mq如何保证高可用,解决重复消费、数据丢失问题和顺序性问题的主要内容,如果未能解决你的问题,请参考以下文章
MQ那点破事,消息丢失重复消费消费顺序堆积事务高可用....
Kafka在高并发的情况下,如何避免消息丢失和消息重复?kafka消费怎么保证数据消费一次?数据的一致性和统一性?数据的完整性?