欢迎关注我的公众号:石杉的架构笔记(ID:shishan100)面试
周一至周五早8点半!精品技术文章准时送上!算法
(1)前情提示数据库
(2)保证投递消息不丢失的confirm机制性能优化
(3)confirm机制的代码实现网络
(4)confirm机制投递消息的高延迟性架构
(5)高并发下如何投递消息才能不丢失并发
(6)消息中间件全链路100%数据不丢失能作到吗?异步
上篇文章:《面试大杀器:消息中间件如何实现消费吞吐量的百倍优化?》,咱们分析了RabbitMQ开启手动ack机制保证消费端数据不丢失的时候,prefetch机制对消费者的吞吐量以及内存消耗的影响。分布式
经过分析,咱们知道了prefetch过大容易致使内存溢出,prefetch太小又会致使消费吞吐量太低,因此在实际项目中须要慎重测试和设置。微服务
这篇文章,咱们转移到消息中间件的生产端,一块儿来看看如何保证投递到MQ的数据不丢失。
若是投递出去的消息在网络传输过程当中丢失,或者在RabbitMQ的内存中还没写入磁盘的时候宕机,都会致使生产端投递到MQ的数据丢失。
并且丢失以后,生产端本身还感知不到,同时还没办法来补救。
下面的图就展现了这个问题。
因此本文呢,咱们就来逐步分析一下。
其实要解决这个问题,相信你们看过以前的消费端ack机制以后,也都猜到了。
很简单,就是生产端(好比上图的订单服务)首先须要开启一个confirm模式,接着投递到MQ的消息,若是MQ一旦将消息持久化到磁盘以后,必须也要回传一个confirm消息给生产端。
这样的话,若是生产端的服务接收到了这个confirm消息,就知道是已经持久化到磁盘了。
不然若是没有接收到confirm消息,那么就说明这条消息半路可能丢失了,此时你就能够从新投递消息到MQ去,确保消息不要丢失。
并且一旦你开启了confirm模式以后,每次消息投递也一样是有一个delivery tag的,也是起到惟一标识一次消息投递的做用。
这样,MQ回传ack给生产端的时候,会带上这个delivery tag。你就知道具体对应着哪一次消息投递了,能够删除这条消息。
此外,若是RabbitMQ接收到一条消息以后,结果内部出错发现没法处理这条消息,那么他会回传一个nack消息给生产端。此时你就会感知到这条消息可能处理有问题,你能够选择从新再次投递这条消息到MQ去。
或者另外一种状况,若是某条消息很长时间都没给你回传ack/nack,那多是极端意外状况发生了,数据也丢了,你也能够本身从新投递消息到MQ去。
经过这套confirm机制,就能够实现生产端投递消息不会丢失的效果。你们来看看下面的图,一块儿来感觉一下。
下面,咱们再来看看confirm机制的代码实现:
这里有一个很关键的点,就是一旦启用了confirm机制投递消息到MQ以后,MQ是不保证何时会给你一个ack或者nack的。
由于RabbitMQ本身内部将消息持久化到磁盘,自己就是经过异步批量的方式来进行的。
正常状况下,你投递到RabbitMQ的消息都会先驻留在内存里,而后过了几百毫秒的延迟时间以后,再一次性批量把多条消息持久化到磁盘里去。
这样作,是为了兼顾高并发写入的吞吐量和性能的,由于要是你来一条消息就写一次磁盘,那么性能会不好,每次写磁盘都是一次fsync强制刷入磁盘的操做,是很耗时的。
因此正是由于这个缘由,你打开了confirm模式以后,极可能你投递出去一条消息,要间隔几百毫秒以后,MQ才会把消息写入磁盘,接着你才会收到MQ回传过来的ack消息,这个就是所谓confirm机制投递消息的高延迟性。
你们看看下面的图,一块儿来感觉一下。
你们能够考虑一下,在生产端高并发写入MQ的场景下,你会面临两个问题:
一、你每次写一条消息到MQ,为了等待这条消息的ack,必须把消息保存到一个存储里。
而且这个存储不建议是内存,由于高并发下消息是不少的,每秒可能都几千甚至上万的消息投递出去,消息的ack要等几百毫秒的话,放内存可能有内存溢出的风险。
二、绝对不能以同步写消息 + 等待ack的方式来投递,那样会致使每次投递一个消息都同步阻塞等待几百毫秒,会致使投递性能和吞吐量大幅度降低。
针对这两个问题,相对应的方案其实也呼之欲出了。
首先,用来临时存放未ack消息的存储须要承载高并发写入,并且咱们不须要什么复杂的运算操做,这种存储首选绝对不是MySQL之类的数据库,而建议采用kv存储。kv存储承载高并发能力极强,并且kv操做性能很高。
其次,投递消息以后等待ack的过程必须是异步的,也就是相似上面那样的代码,已经给出了一个初步的异步回调的方式。
消息投递出去以后,这个投递的线程其实就能够返回了,至于每一个消息的异步回调,是经过在channel注册一个confirm监听器实现的。
收到一个消息ack以后,就从kv存储中删除这条临时消息;收到一个消息nack以后,就从kv存储提取这条消息而后从新投递一次便可;也能够本身对kv存储里的消息作监控,若是超过必定时长没收到ack,就主动重发消息。
你们看看下面的图,一块儿来体会一下:
到此为止,咱们已经把生产端和消费端如何保证消息不丢失的相关技术方案结合RabbitMQ这种中间件都给你们分析过了。
其实,架构思想是通用的, 不管你用的是哪种MQ中间件,他们提供的功能是不太同样的,可是你都须要考虑以下几点:
生产端如何保证投递出去的消息不丢失:消息在半路丢失,或者在MQ内存中宕机致使丢失,此时你如何基于MQ的功能保证消息不要丢失?
MQ自身如何保证消息不丢失:起码须要让MQ对消息是有持久化到磁盘这个机制。
消费端如何保证消费到的消息不丢失:若是你处理到一半消费端宕机,致使消息丢失,此时怎么办?
目前来讲,咱们初步的借着RabbitMQ举例,已经把从前到后一整套技术方案的原理、设计和实现都给你们分析了一遍了。
可是此时真的能作到100%数据不丢失吗?恐怕未必,你们再考虑一下个特殊的场景。
生产端投递了消息到MQ,并且持久化到磁盘而且回传ack给生产端了。
可是此时MQ还没投递消息给消费端,结果MQ部署的机器忽然宕机,并且由于未知的缘由磁盘损坏了,直接在物理层面致使MQ持久化到磁盘的数据找不回来了。
这个你们千万别觉得是开玩笑的,你们若是留意留意行业新闻,这种磁盘损坏致使数据丢失的是真的有的。
那么此时即便你把MQ重启了,磁盘上的数据也丢失了,数据是否是仍是丢失了?
你说,我能够用MQ的集群机制啊,给一个数据作多个副本,好比后面咱们就会给你们分析RabbitMQ的镜像集群机制,确实能够作到数据多副本。
可是即便数据多副本,必定能够作到100%数据不丢失?
好比说你的机房忽然遇到地震,结果机房里的机器所有没了,数据是否是仍是全丢了?
说这个,并非说要抬杠。而是告诉你们,技术这个东西,100%都是理论上的指望。
应该说,咱们凡事都朝着100%去作,可是理论上是不可能彻底作到100%保证的,可能就是作到99.9999%的可能性数据不丢失,可是仍是有千万分之一的几率会丢失。
固然,从实际的状况来讲,能作到这种地步,其实基本上已经基本数据不会丢失了。
end
若有收获,请帮忙转发,您的鼓励是做者最大的动力,谢谢!
一大波微服务、分布式、高并发、高可用的原创系列文章正在路上
欢迎扫描下方二维码,持续关注:
石杉的架构笔记(id:shishan100)
十余年BAT架构经验倾囊相授
推荐阅读:
二、【双11狂欢的背后】微服务注册中心如何承载大型系统的千万级访问?
三、【性能优化之道】每秒上万并发下的Spring Cloud参数优化实战
六、大规模集群下Hadoop NameNode如何承载每秒上千次的高并发访问
七、【性能优化的秘密】Hadoop如何将TB级大文件的上传性能优化上百倍
九、【坑爹呀!】最终一致性分布式事务如何保障实际生产中99.99%高可用?
十一、【眼前一亮!】看Hadoop底层算法如何优雅的将大规模集群性能提高10倍以上?
1六、亿级流量系统架构之如何设计全链路99.99%高可用架构
1八、大白话聊聊Java并发面试问题之volatile究竟是什么?
1九、大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?
20、大白话聊聊Java并发面试问题之谈谈你对AQS的理解?
2一、大白话聊聊Java并发面试问题之公平锁与非公平锁是啥?
2二、大白话聊聊Java并发面试问题之微服务注册中心的读写锁优化
2三、互联网公司的面试官是如何360°无死角考察候选人的?(上篇)
2四、互联网公司面试官是如何360°无死角考察候选人的?(下篇)
2五、Java进阶面试系列之一:哥们,大家的系统架构中为何要引入消息中间件?
2六、【Java进阶面试系列之二】:哥们,那你说说系统架构引入消息中间件有什么缺点?
2七、【行走的Offer收割机】记一位朋友斩获BAT技术专家Offer的面试经历
2八、【Java进阶面试系列之三】哥们,消息中间件在大家项目里是如何落地的?
2九、【Java进阶面试系列之四】扎心!线上服务宕机时,如何保证数据100%不丢失?
30、一次JVM FullGC的背后,竟隐藏着惊心动魄的线上生产事故!
3一、【高并发优化实践】10倍请求压力来袭,你的系统会被击垮吗?
3二、【Java进阶面试系列之五】消息中间件集群崩溃,如何保证百万生产数据不丢失?
3三、亿级流量系统架构之如何在上万并发场景下设计可扩展架构(上)?
3四、亿级流量系统架构之如何在上万并发场景下设计可扩展架构(中)?
3五、亿级流量系统架构之如何在上万并发场景下设计可扩展架构(下)?
3七、亿级流量系统架构之如何保证百亿流量下的数据一致性(上)
3八、亿级流量系统架构之如何保证百亿流量下的数据一致性(中)?
3九、亿级流量系统架构之如何保证百亿流量下的数据一致性(下)?
40、互联网面试必杀:如何保证消息中间件全链路数据100%不丢失(1)
4一、互联网面试必杀:如何保证消息中间件全链路数据100%不丢失(2)
做者:石杉的架构笔记 连接:juejin.im/post/5c263a… 来源:掘金 著做权归做者全部,转载请联系做者得到受权!