大家好,欢迎来到Tlog4J课堂,我是Jensen。
创新互联成立于2013年,是专业互联网技术服务公司,拥有项目成都网站制作、成都网站建设网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元乾安做网站,已为上家服务,为乾安各地企业和个人服务,联系电话:18982081108
面试官:在MQ的整个消息生产消费过程中,如何保障消息100%被消费?
候选人:MQ有个ACK机制,确保消息100%被消费。
面试官:好吧,可以回去等通知了……
这道面试题在考察MQ组件时算是老生常谈了,不知道你是如何回答的?
我们平时都在使用MQ,但使用技术框架只是第一步,去弄明白它的底层原理、深挖技术真相,才是每一位IT从业者的基操。
这里说明一点,想要回答好面试官的问题,最好还是要有金字塔思维——金字塔思维就是从不同维度上来思考问题的一种方式,不重不漏,集体穷尽。
MQ作为异步通讯的消息中间件,其功能除了解耦生产者与消费者,还能用于大流量的削峰填谷,解决业务的最终一致性问题,那么消息的“可靠性”就显得尤为重要了,比如说商品出库后的库存数据通过MQ同步到财务系统,如果消息的可靠性没有保障,那财务系统的存货成本分析数据就无法有效支撑财务团队。
准确来说,我们需要保障MQ消息的可靠性,需要从三个层面/维度解决:生产者100%投递、MQ持久化、消费者100%消费,这里的100%消费指的是消息不少消费,也不多消费。
由于MQ是基础网络通讯的中间件,网络通讯必然因丢包、网络抖动等原因产生数据丢失,MQ组件本身也会由于宕机或软件崩溃而中止服务,从而造成数据丢失,那么我们就需要从这两个根本原因着手补偿,这里科普一下RabbitMQ和Kafka是怎么解决的。
这里我必须先提一提RabbitMQ的消息协议——AMQP(Advanced Message Queuing Protocol,高级消息队列协议),在面试时我经常问候选人一个问题:RabbitMQ用的是什么消息协议?大部分候选人是回答不出来AMQP的,更不用说AMQP模型是如何设计的了。
在服务器中,三个主要功能模块连接成一个处理链完成预期的功能:
使用这个模型我们可以很容易地模拟出存储转发队列和主题订阅这些典型的消息中间件概念。
接下来我们看看RabbitMQ的消息确认机制是如何保障消息可靠性的。
通常来说,消息是在内存中存储通讯的,而基于内存的都是会有数据丢失的问题产生,服务一重启,数据就随之销毁。
在RabbitMQ中对数据的持久化有三方面:交换机持久化、队列持久化、消息持久化。
上面只是说了API层的实现,那RabbitMQ底层又是怎么做消息持久化的呢?
如果指定了持久化参数,它们会以append的方式写文件,会根据文件大小(默认16M)自动切割,生成新的文件,RabbitMQ启动时会创建两个进程,一个负责持久化消息的存储,另一个负责非持久化消息的存储(当内存不够时会用到)。
消息存储时,会在一个叫ets的表中记录消息在文件中的映射以及相关信息(包括ID、偏移量、有效数据、左边文件、右边文件),消息读取时根据该信息到文件中读取,同时更新信息。
消息删除时只从ets删除,变为垃圾数据,当垃圾数据超出比例(默认50%),并且文件数达到3个,就会触发垃圾回收:锁定左右两个文件,整理左边文件有效数据、将左边文件有效数据写入左边,更新文件信息,删除右边,完成合并;当一个文件的有效数据等于0时,删除该文件。
写入文件前先写入buffer缓冲区,如果buffer已满,则写入文件,注意,此时只是操作系统的页存,还没落盘。
每隔25ms刷一次磁盘(比如Linux中的fsync命令),不管buffer(fd的读、写缓存区)满没满,都将buffer和页存中的数据落盘。
还有另外一种落盘机制:每次消息写入后,如果没有后续写入请求,则直接刷盘。
此外,RabbitMQ除了消息确认机制,还有另一种方式——使用事务消息:消息生产端发送commit命令,MQ同步返回commit ok命令,这种方式由于需要同步阻塞等待MQ返回是否投递成功,才能执行别的操作,性能较差,因此不推荐使用。
Kafka在MQ领域以性能高、吞吐能力强、消息堆积能力强等等优势称著,常常用于日志收集、消息系统、用户活动跟踪、运营指标、流式处理等等场景,讲之前先简单聊聊Kafka的架构设计:
Partition:为了实现扩展性,提高并发能力,一个Topic以多个Partition的方式分布到多个Broker上,每个Partition是一个有序的队列,一个Topic的每个Partition都有若干个副本(Replica),一个Leader和若干个Follower;生产者发送数据的对象,以及消费者消费数据的对象,都是通过Leader,Follower负责实时从Leader中同步数据,保持和Leader数据的同步;当Leader发生故障时,某个Follower还会成为新的Leader。
Kafka消息发送端有个ACK机制。
通过设置最小同步副本数和ACK机制,可以让MQ在性能与可靠性上达到平衡。
手工提交offset(偏移量):Kafka消费者在拉取消息后,默认会自动提交offset,由于消费者每次都会根据offset来消费消息的,如果消费者处理业务失败,实际上我们是要重新消费的,所以我们要在消息处理成功后再手工提交offset,确认消息能够成功消费。
很简单,通过减小broker刷盘间隔来实现高可靠。
要深究其原理,得从Kafka的持久化机制来看。
磁盘的顺序读写:与RabbitMQ不同,Kafka是基于磁盘读写的,那为什么Kafka的吞吐量还这么大呢?原因是Kafka的读写是用顺序读写的,不需要寻址随机读写,而由于是用磁盘来写数据,消息堆积能力必然比内存型的RabbitMQ更强
理解了Kafka的持久化机制是直接读写页存+定时刷盘的方式,我们只需要设置刷盘策略即可在性能与可靠性上权衡。
Kafka提供3个参数来优化刷盘机制:
关于框架类的面试题,最重要是得掌握技术框架的底层实现原理、适用场景,基本上回答出这两方面就OK了,其它奇奇怪怪的细节问题要是答不出来,咱就引导面试官说出自己对框架的理解即可,毕竟细节的问题太多了。
那怎么才算掌握呢?起码能通过框架的特性,根据需要实现一个简易版本,比如说自己实现一个Spring框架、实现一个MQ组件等等。
标题名称:面试基操:MQ怎么保障消息可靠性?
网页路径:http://www.mswzjz.cn/qtweb/news9/269459.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能