消息队列知识总结2

  • Post author:
  • Post category:其他




如何保证数据一致性,事务消息如何实现?

一条普通的MQ消息,从产生到被消费,大概流程如下:

1,生产者产生消息,发送带MQ服务器

2,MQ收到消息后,将消息持久化到存储系统。

3,MQ服务器返回ACk到生产者。

4,MQ服务器把消息push给消费者

5,消费者消费完消息,响应ACK

6,MQ服务器收到ACK,认为消息消费成功,即在存储中删除消息。

在这里插入图片描述

举个下订单的例子吧。订单系统创建完订单后,再发送消息给下游系统。如果订单创建成功,然后消息没有成功发送出去,下游系统就无法感知这个事情,出导致数据不一致。 如何保证数据一致性呢?可以使用事务消息。一起来看下事务消息是如何实现的吧。

在这里插入图片描述

1,生产者产生消息,发送一条半事务消息到MQ服务器

2,MQ收到消息后,将消息持久化到存储系统,这条消息的状态是待发送状态。

3,MQ服务器返回ACK确认到生产者,此时MQ不会触发消息推送事件

4,生产者执行本地事务

5,如果本地事务执行成功,即commit执行结果到MQ服务器;如果执行失败,发送rollback。

6,如果是正常的commit,MQ服务器更新消息状态为可发送;如果是rollback,即删除消息。

7,如果消息状态更新为可发送,则MQ服务器会push消息给消费者。消费者消费完就回ACK。

8,如果MQ服务器长时间没有收到生产者的commit或者rollback,它会反查生产者,然后根据查询到的结果执行最终状态。



如何保证数据的顺序消费

在KaRka中,Topic在单个分区的生产消费是有序的。通常我们申请多个分区是为了提高生产消费的吞吐量,但多个分区就会导致消费消息时无序。

保证顺序消费的方法有:

要想保证顺序消费,就必须要保证顺序消费的消息在同一个队列。

1.只申请1个分区;仅推荐在吞吐量低的顺序场景下用

2.这种场景申请多个分区,生产时使用消息Key;生产者发送消息时如果指定了Key,则这条消息会根据Key的Hash发送到对应的分区,也就是说带有相同Key的消息会被发送到相同的分区。(如果不携带Key的话是轮询发送到所有分区)

写 N 个内存 Queue,具有相同 key 的数据都到同一个内存 Queue;然后对于 N 个线程,每个线程分别消费一个内存 Queue 即可,这样就能保证顺序性。

顺序消费典型的应用场景:

1,用于同步数据库和redis之间的数据(单个消费者)

2,某些电商场景必须严格遵守消息的执行顺序,比如说待支付–已支付–开始发货–订单完成–评价。如果开始发货在已支付之前面执行,就会产生业务问题。

在使用消息key来确保消息发布到多个分区时,要注意key的hash函数,尽量避免大多数消息发布到一个分区,否则会出现流量倾斜。



消息中间件如何做到高可用?

以Kafka为例。

Kafka 的基础集群架构,由多个broker组成,每个broker都是一个节点。当你创建一个topic时,它可以划分为多个partition,而每个partition放一部分数据,分别存在于不同的 broker 上。也就是说,一个 topic 的数据,是分散放在多个机器上的,每个机器就放一部分数据。

每个partition放一部分数据,如果对应的broker挂了,那这部分数据是不是就丢失了?那不是保证不了高可用吗?

Kafka 0.8 之后,提供了复制多副本机制来保证高可用,即每个 partition 的数据都会同步到其它机器上,形成多个副本。然后所有的副本会选举一个 leader 出来,让leader去跟生产和消费者打交道,其他副本都是follower。写数据时,leader 负责把数据同步给所有的follower,读消息时,直接读 leader 上的数据即可。如何保证高可用的?就是假设某个 broker 宕机,这个broker上的partition 在其他机器上都有副本的。如果挂的是leader的broker呢?其他follower会重新选一个leader出来。



版权声明:本文为lf173089386原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。