所有栏目 | 云社区 美国云服务器[国内云主机商]
你的位置:首页 > 云社区 » 正文

高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?

发布时间:2020-04-15 16:13:27

资讯分类:消息中间件  投递  生产者  并发  消息  生产者  投递
高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?

消息中间件消息不丢失主要从以下几个方面考虑

投递

生产者向消息中间件投递消息是push的方式,这种方法会出现以下情况

1、生产者挂掉了

情况是这样的,你的生产者收到了数据,并存到了数据库中,同时生产者要降消息push到消息中间件做异步处理。这时候如果生产者挂掉了,就导致消息数据没有push到消息中间件里,也就会出现数据不一致的问题。

这时候我们可以在数据库设置是否投递成功标志位,在生产者push之后,再将标志位设置为已经投递。另外,客气启动一个定时任务,检测是否有消息没有投递,保证消息数据一定会进入中间件。

2、消息重试

生产者没有挂掉,但是因为网络等其他问题,导致生产者不知道有没有投递成功。这时候生产者可以失败重试,这保证消息可以再次投递。但是这有可能会出现重复投递,导致出现中间件消息数据重复。

存储

消息中间件是存到磁盘上的,存入磁盘的消息一般是不会丢失的,同时磁盘文件还会做备份。如果一个丢失了,可以通过备份文件恢复。

消费

一般消费者需要在消费者消费成功之后再设置提交消费位点。如果消费失败,消费者不提交消费位点还是可以消费该数据的。这就引出一个问题就是消息重复消费。这个问题和上边提到的消息重复投递相同,都会导致重复消费,这就需要考虑消费的幂等性,可以做消费记录,防止重复消费。

高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?

消息传递分3步:

1, 生产者 --> MQ

2, MQ 缓存

3, MQ --> 消费者

如何确保消息不丢失?

各家MQ都有复杂的机制,拿RocketMQ举例,对应上面的3步,简单来说:

第1步,同步阻塞投递

如果返回成功,则说明消息一定投递到了Broker。

如果返回超时,默认重试2次。而超时,到底成功还是失败,可通过实时API查询Broker确定,不过一般人不会这么干。那应该怎么办?

第2步,刷盘持久化,分同步和异步。为了性能,一般选择异步,但极端情况下Broker挂掉时,异步方式可能丢失消息,这个跟具体集群方式有关。而消息丢了,怎么发现?

第3步,如果消费者没有返回成功标识,Broker会默认重试最多16次。那超过16次,怎么发现?

RocketMQ已经为我们提供了完善的机制,高并发下,如何确保100%消息不丢失并且被正确消费完成,则要回答上面1,2,3提出的问题。

我在实际工作中,使用RocketMQ时,都是额外再开发一个“定时任务”来检查业务处理结果,不管是1,2,3哪一步出现问题,都可以由这个任务发现。这个补偿任务的方式可以用在很多MQ中,有人说任务的性能低、及时性不高,但你要知道消息丢失毕竟是小概率事件,这个任务只是确保万一。

最后要说的是,为了消息的不丢失,就避免不了消息的重复,所以无论如何,使用者还都要实现“消费的幂等性”。

PS: 没有经历过大厂,不知道他们怎么处理的。有知道的,请指点一下,谢谢。

高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?

1.先来看下消息的投递过程,消息发送分为三步,见图

2.发送方通过这三步便可以保证消息发送到mq的可靠性:

第一步send将消息发送给mq,

第二步mq将消息持久化,mq需要保证高可用, 消息持久化化后不会丢失,一般都会存在多个副本,多个副本之间可以使用raft协议保证数据一致性。

第三步mq应答到send方确认消息已投递。

但是因为1,2,3步中都可能出现故障,需要重试发送请求。如果是1,2步失败直接重试就可以了,如果第三步失败了,就可能一条消息会出现多条,这就需要消费端去保证消费的幂等性。


高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?

你这个问题应该是指的是投递保证一致性,还是投递成功了,并且收到了ack确认的话然后消息没有存在在消息队列中?

第一个的话,一般来说为了保证消息正确投递,用有acid特性的数据库,如MySQL,可以保证消息能正确投递,如rabbitmq有confirm机制,callback机制,还有不被重复投递。当然这样做的话并发效果可能不是很强,但是可以保证稳定,这就是业务场景而定了。

第二个的话,基本不用担心了,很多消息队列都有持久化功能,在某些灾难情况下可以保证不丢失,正常业务情况下,消息会被正确消费。

高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?

讨论消息丢失的前提是消息已经发送到MQ,如果发送都没成功,何来丢失的说法?然后发送消息只是一个普通的RPC远程调用而已,如果失败,那是消息生产者自己要处理的事情。就像写入数据到数据库失败一样。所以我觉得楼主提这个问题本身就没有理解什么叫做消息丢失。

高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?

1.调整操作系统核心参数,确保每一台服器在操作系统层能承载高并发

2.消息中间件参数调整,确保中间件本身有足够缓存

3.提升后端业务处理的性能,减少中间件的堵塞

4.使用http2.0

高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?

第一,可以使用消息投递后qos机制,进行ack应答,如果投递后一定时间没收到消费ack,qos本身会进行重发。

第二,对于发送的消息,可以先持久化,然后定时轮训发送,对于消费者,可以先将消息报文持久化,然后定时消费,做业务处理。

留言与评论(共有 0 条评论)
   
验证码:
Top