oppo后端16连问(四)

chujichenxuyuan
发布于 2022-5-16 18:04
浏览
0收藏

10. 你们项目使用了RocketMQ对吧?那你知道如何保证消息不丢失吗?


一个消息从生产者产生,到被消费者消费,主要经过这3个过程:

 oppo后端16连问(四)-鸿蒙开发者社区1.生产者产生消息
2.消息发送到存储端,保存下来
3.消息推送到消费者,消费者消费完,ack应答。


因此如何保证MQ不丢失消息,可以从这三个阶段阐述:

 

 •  生产者保证不丢消息
 •  存储端不丢消息
 •  消费者不丢消息


10.1 生产者保证不丢消息


生产端如何保证不丢消息呢?确保生产的消息能顺利到达存储端。

 

如果是RocketMQ消息中间件的话,Producer生产者提供了三种发送消息的方式,分别是:

 

 •  同步发送
 •  异步发送
 •  单向发送


生产者要想发消息时保证消息不丢失,可以:

 

 •  采用同步方式发送,send消息方法返回成功状态,即消息正常到达了存储端Broker
 •  如果send消息异常或者返回非成功状态,可以发起重试。
 •  可以使用事务消息,RocketMQ的事务消息机制就是为了保证零丢失来设计的


10.2 存储端不丢消息


如何保证存储端的消息不丢失呢?确保消息持久化到磁盘,那就是刷盘机制嘛。

 

刷盘机制分同步刷盘和异步刷盘

 

 •  同步刷盘:生产者消息发过来时,只有持久化到磁盘,RocketMQ的存储端Broker才返回一个成功的ACK响应。它保证消息不丢失,但是影响了性能。
 •  异步刷盘:只要消息写入PageCache缓存,就返回一个成功的ACK响应。这样提高了MQ的性能,但是如果这时候机器断电了,就会丢失消息。

 

除了同步刷盘机制,还有一个维度需要考虑。Broker一般是集群部署的,有主节点和从节点。消息到Broker存储端,只有主节点和从节点都写入成功,才反馈成功的ack给生产者。这就是同步复制,它保证了消息不丢失,但是降低了系统的吞吐量。与之对应即是异步复制,只要消息写入主节点成功,就返回成功的ack,它速度快,但是会有性能问题。

 

10.3 消费阶段不丢消息


消费者执行完业务逻辑,再反馈会Broker说消费成功,这样才可以保证消费阶段不丢消息。

 

11. 事务消息是否了解?场景题:比如下单清空购物车,你是如何设计的?


事务消息主要用来解决消息生产者和消息消费者的数据一致性问题。我们先来回忆一下:一条普通的消息队列消息,从产生到被消费,经历的流程:oppo后端16连问(四)-鸿蒙开发者社区1.生产者产生消息,发送到MQ服务器
2.MQ收到消息后,将消息持久化到存储系统。
3.MQ服务器返回ACk到生产者。
4.MQ服务器把消息push给消费者
5.消费者消费完消息,响应ACK
6.MQ服务器收到ACK,认为消息消费成功,即在存储中删除消息。


消息队列的事务消息流程是怎样的呢?

oppo后端16连问(四)-鸿蒙开发者社区

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,它会反查生产者,然后根据查询到的结果执行最终状态。

 

我们举个下订单清空购物车的例子吧。订单系统创建完订单后,然后发消息给下游系统购物车系统,清空购物车。

 

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,它会反查生产者,然后根据查询到的结果(回滚操作或者重新发送消息)执行最终状态。

 

有些伙伴可能有疑惑,如果消费者消费失败怎么办呢?那数据是不是不一致啦?所以就需要消费者消费成功,执行业务逻辑成功,再反馈ack嘛。如果消费者消费失败,那就自动重试嘛,接口支持幂等即可。

标签
已于2022-5-16 18:04:02修改
收藏
回复
举报
回复
    相关推荐