MQ消息中间件,面试能问些什么?
为什么应用音讯队列?音讯队列的长处和毛病?
kafka、activemq、rabbitmq、rocketmq都有什么优缺点?
面试官角度剖析:
(1)你知不知道你们零碎里为什么要用音讯队列这个货色?
(2)既然用了音讯队列这个货色,你知不知道用了有什么益处?
(3)既然你用了MQ,那么过后为什么选用这一款MQ?
1. 为什么应用音讯队列?
面试官问这个问题的冀望之一的答复是,你们公司有什么业务场景,这个业务场景有什么技术挑战,如果不必MQ可能会很麻烦,然而再用了之后带来了很多益处。
音讯队列的常见应用场景有很多然而外围的有三个:解耦、异步、削峰
解耦
场景形容:A零碎发送个数据到BCD三个零碎,接口调用发送,那如果E零碎也要这个数据呢?那如果C零碎当初不须要了呢?当初A零碎又要发送第二种数据了呢?A零碎负责人解体中...再来点解体的事儿,A零碎要时时刻刻思考BCDE四个零碎如果挂了怎么办?那我要不要重发?我要不要把音讯存起来?头发都白了啊...
应用了MQ之后的解耦场景
面试技巧:你须要思考下,你负责的零碎中是否有相似的场景,就是一个零碎或者一个模块,调用了多个零碎或者模块,相互之间的调用很简单,保护起来很麻烦。然而其实这个调用是不须要间接同步调用接口的,如果MQ给他异步化解耦也是能够的,你就须要去思考在你的我的项目里是不是能够使用这个MQ去进行零碎解耦 。
异步
场景形容:零碎A承受一个申请,须要在本人本地写库,还须要在零碎BCD三个零碎写库,本人本地写库须要3ms。BCD别离须要300ms、450ms、200ms。最终总好时长:953ms,靠近1s。给用户的体验感觉一点也不好。
不必MQ的同步高延时申请场景
应用MQ异步化之后的接口性能优化
削峰
场景形容:每天 0 点到 11 点,零碎A惊涛骇浪,每秒并发申请数量就 100 个。后果每一一到11点到1点,每秒并发申请数量就会暴增大1万条 。然而零碎最大的解决能力就只能每秒钟解决1000个申请。
没有用MQ的时候高峰期零碎被打死的场景
应用MQ来进行削峰的场景
2. 音讯队列的有点和毛病?
长处:非凡场景下解耦、异步、削峰。
毛病:
零碎可用性升高:零碎引入的内部依赖越多,越容易挂掉,原本你就是A零碎调用BCD三个零碎的接口就好了,人ABCD四个零碎好好的没什么问题,你偏加个MQ进来,万一MQ挂了怎么办,整套零碎解体了,就完蛋了
零碎复杂性进步:硬生生加个MQ进来,你怎么保障音讯没有反复生产?怎么解决音讯失落的状况?怎么保障消息传递的程序性?
一致性问题:零碎A解决完了间接返回胜利了,人家都认为你这个申请胜利了;但问题是,要是BCD三个零碎哪里BD零碎胜利了,后果C零碎写库失败了,咋整?数据就不统一了,
所以音讯队列是一种非常复杂的架构,引入它有很多益处,然而也得针对他带来的害处做各种额定的技术计划和架构来躲避掉。做好之后你会发现零碎复杂度晋升了一个数量积,然而关键时刻,用,还是要用的。
3. kafka、activemq、rabbitmq、rocketmq都有什么优缺点?
个性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
---|---|---|---|---|
单机吞吐量 | 万级,吞吐量比RocketMQ和Kafka要低了一个数量级 | 万级,吞吐量比RocketMQ和Kafka要低了一个数量级 | 10万级,RocketMQ也是能够撑持高吞吐的一种MQ | 10万级别,这是kafka最大的长处,就是吞吐量高。 个别配合大数据类的零碎来进行实时数据计算、日志采集等场景 |
topic数量对吞吐量的影响 | topic能够达到几百,几千个的级别,吞吐量会有较小幅度的降落这是RocketMQ的一大劣势,在等同机器下,能够撑持大量的topic | topic从几十个到几百个的时候,吞吐量会大幅度降落所以在等同机器下,kafka尽量保障topic数量不要过多。如果要撑持大规模topic,须要减少更多的机器资源 | ||
时效性 | ms级 | 微秒级,这是rabbitmq的一大特点,提早是最低的 | ms级 | 提早在ms级以内 |
可用性 | 高,基于主从架构实现高可用性 | 高,基于主从架构实现高可用性 | 十分高,分布式架构 | 十分高,kafka是分布式的,一个数据多个正本,多数机器宕机,不会失落数据,不会导致不可用 |
音讯可靠性 | 有较低的概率失落数据 | 通过参数优化配置,能够做到0失落 | 通过参数优化配置,音讯能够做到0失落 | |
性能反对 | MQ畛域的性能极其齐备 | 基于erlang开发,所以并发能力很强,性能极其好,延时很低 | MQ性能较为欠缺,还是分布式的,扩展性好 | 性能较为简单,次要反对简略的MQ性能,在大数据畛域的实时计算以及日志采集被大规模应用,是事实上的规范 |
优劣势总结 | 十分成熟,功能强大,在业内大量的公司以及我的项目中都有利用 偶然会有较低概率失落音讯 而且当初社区以及国内利用都越来越少,官网社区当初对ActiveMQ 5.x保护越来越少,几个月才公布一个版本 而且的确次要是基于解耦和异步来用的,较少在大规模吞吐的场景中应用 | erlang语言开发,性能极其好,延时很低;吞吐量到万级,MQ性能比拟齐备而且开源提供的治理界面十分棒,用起来很好用社区绝对比拟沉闷,简直每个月都公布几个版本分在国内一些互联网公司近几年用rabbitmq也比拟多一些然而问题也是不言而喻的,RabbitMQ的确吞吐量会低一些,这是因为他做的实现机制比拟重。而且erlang开发,国内有几个公司有实力做erlang源码级别的钻研和定制?如果说你没这个实力的话,的确偶然会有一些问题,你很难去看懂源码,你公司对这个货色的掌控很弱,根本职能依赖于开源社区的疾速保护和修复bug。而且rabbitmq集群动静扩大会很麻烦,不过这个我感觉还好。其实次要是erlang语言自身带来的问题。很难读源码,很难定制和掌控。 | 接口简略易用,而且毕竟在阿里大规模利用过,有阿里品牌保障日解决音讯上百亿之多,能够做到大规模吞吐,性能也十分好,分布式扩大也很不便,社区保护还能够,可靠性和可用性都是ok的,还能够撑持大规模的topic数量,反对简单MQ业务场景而且一个很大的劣势在于,阿里出品都是java系的,咱们能够本人浏览源码,定制本人公司的MQ,能够掌控社区活跃度绝对较为个别,不过也还能够,文档相对来说简略一些,而后接口这块不是依照规范JMS标准走的有些零碎要迁徙须要批改大量代码还有就是阿里出台的技术,你得做好这个技术万一被摈弃,社区黄掉的危险,那如果你们公司有技术实力我感觉用RocketMQ挺好的 | kafka的特点其实很显著,就是仅仅提供较少的外围性能,然而提供超高的吞吐量,ms级的提早,极高的可用性以及可靠性,而且分布式能够任意扩大 同时kafka最好是撑持较少的topic数量即可,保障其超高吞吐量 而且kafka惟一的一点劣势是有可能音讯反复生产,那么对数据准确性会造成极其轻微的影响,在大数据畛域中以及日志采集中,这点轻微影响能够疏忽 这个个性人造适宜大数据实时计算以及日志收集 |
1. 引入音讯队列之后如何保障其高可用性?
(1)RabbitMQ的高可用性
RabbitMQ是比拟有代表性的,因为是基于主从做高可用性的,咱们就以他为例子解说第一种MQ的高可用性怎么实现。
rabbitmq有三种模式:单机模式,一般集群模式,镜像集群模式
(1.1) 单机模式
就是demo级别的,个别就是你本地启动了玩玩儿的,没人生产用单机模式
(1.2)一般集群模式
意思就是在多台机器上启动多个rabbitmq实例,每个机器启动一个。然而你创立的queue,只会放在一个rabbtimq实例上,然而每个实例都同步queue的元数据。完了你生产的时候,实际上如果连贯到了另外一个实例,那么那个实例会从queue所在实例上拉取数据过去。
这种形式的确很麻烦,也不怎么好,没做到所谓的分布式,就是个一般集群。因为这导致你要么消费者每次随机连贯一个实例而后拉取数据,要么固定连贯那个queue所在实例生产数据,前者有数据拉取的开销,后者导致单实例性能瓶颈。
而且如果那个放queue的实例宕机了,会导致接下来其余实例就无奈从那个实例拉取,如果你开启了音讯长久化,让rabbitmq落地存储音讯的话,音讯不肯定会丢,得等这个实例复原了,而后才能够持续从这个queue拉取数据。
所以这个事儿就比拟难堪了,这就没有什么所谓的高可用性可言了,这计划次要是进步吞吐量的,就是说让集群中多个节点来服务某个queue的读写操作。
(1.3)镜像集群模式
这种模式,才是所谓的rabbitmq的高可用模式,跟一般集群模式不一样的是,你创立的queue,无论元数据还是queue里的音讯都会存在于多个实例上,而后每次你写音讯到queue的时候,都会主动把音讯到多个实例的queue里进行音讯同步。
这样的话,益处在于,你任何一个机器宕机了,没事儿,别的机器都能够用。害处在于,第一,这个性能开销也太大了吧,音讯同步所有机器,导致网络带宽压力和耗费很重!第二,这么玩儿,就没有扩展性可言了,如果某个queue负载很重,你加机器,新增的机器也蕴含了这个queue的所有数据,并没有方法线性扩大你的queue
那么怎么开启这个镜像集群模式呢?我这里简略说一下,防止面试人家问你你不晓得,其实很简略rabbitmq有很好的治理控制台,就是在后盾新增一个策略,这个策略是镜像集群模式的策略,指定的时候能够要求数据同步到所有节点的,也能够要求就同步到指定数量的节点,而后你再次创立queue的时候,利用这个策略,就会主动将数据同步到其余的节点下来了。
(2)kafka的高可用性
kafka一个最根本的架构意识:多个broker组成,每个broker是一个节点;你创立一个topic,这个topic能够划分为多个partition,每个partition能够存在于不同的broker上,每个partition就放一部分数据。
这就是人造的分布式音讯队列,就是说一个topic的数据,是扩散放在多个机器上的,每个机器就放一部分数据。
实际上rabbitmq之类的,并不是分布式音讯队列,他就是传统的音讯队列,只不过提供了一些集群、HA的机制而已,因为无论怎么玩儿,rabbitmq一个queue的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个queue的残缺数据。
kafka 0.8以前,是没有HA机制的,就是任何一个broker宕机了,那个broker上的partition就废了,没法写也没法读,没有什么高可用性可言。
kafka 0.8当前,提供了HA机制,就是replica正本机制。每个partition的数据都会同步到吉他机器上,造成本人的多个replica正本。而后所有replica会选举一个leader进去,那么生产和生产都跟这个leader打交道,而后其余replica就是follower。写的时候,leader会负责把数据同步到所有follower下来,读的时候就间接读leader上数据即可。只能读写leader?很简略,要是你能够随便读写每个follower,那么就要care数据一致性的问题,零碎复杂度太高,很容易出问题。kafka会平均的将一个partition的所有replica散布在不同的机器上,这样才能够进步容错性。
这么搞,就有所谓的高可用性了,因为如果某个broker宕机了,没事儿,那个broker下面的partition在其余机器上都有正本的,如果这下面有某个partition的leader,那么此时会从新选举一个新的leader进去,大家持续读写那个新的leader即可。这就有所谓的高可用性了。
写数据的时候,生产者就写leader,而后leader将数据落地写本地磁盘,接着其余follower本人被动从leader来pull数据。一旦所有follower同步好数据了,就会发送ack给leader,leader收到所有follower的ack之后,就会返回写胜利的音讯给生产者。(当然,这只是其中一种模式,还能够适当调整这个行为)
生产的时候,只会从leader去读,然而只有一个音讯曾经被所有follower都同步胜利返回ack的时候,这个音讯才会被消费者读到。
实际上这块机制,讲深了,是能够十分之深刻的,然而我还是回到咱们这个课程的主题和定位,聚焦面试,至多你听到这里大抵明确了kafka是如何保障高可用机制的了,对吧?不至于无所不知,现场还能给面试官画画图。要遇上面试官的确是kafka高手,深挖了问,那你只能说不好意思,太深刻的你没钻研过。
然而大家肯定要明确,这个事件是要衡量的,你当初是要疾速突击常见面试题体系,而不是要深刻学习kafka,要深刻学习kafka,你是没那么多工夫的。你只能确保,你之前兴许压根儿不晓得这块,然而当初你晓得了,面试被问到,你大略能够说一说。而后很多其余的候选人,兴许还不如你,没看过这个,被问到了压根儿答不进去,相比之下,你还能说点进去,大略就是这个意思了。
2. 如何保障音讯不被反复生产(如何保障音讯生产时的幂等性)?
其实这个很常见的一个问题,这俩问题根本能够连起来问。既然是生产音讯,那必定要思考思考会不会反复生产?能不能防止反复生产?或者反复生产了也别造成零碎异样能够吗?这个是MQ畛域的根本问题,其实实质上还是问你应用音讯队列如何保障幂等性,这个是你架构里要思考的一个问题。
首先就是比方rabbitmq、rocketmq、kafka,都有可能会呈现生产反复生产的问题,失常。因为这问题通常不是mq本人保障的,是给你保障的。而后咱们挑一个kafka来举个例子,说说怎么反复生产吧。
kafka实际上有个offset的概念,就是每个音讯写进去,都有一个offset,代表他的序号,而后consumer生产了数据之后,每隔一段时间,会把本人生产过的音讯的offset提交一下,代表我曾经生产过了,下次我要是重启啥的,你就让我持续从上次生产到的offset来持续生产吧。
然而凡事总有意外,比方咱们之前生产常常遇到的,就是你有时候重启零碎,看你怎么重启了,如果碰到点焦急的,间接kill过程了,再重启。这会导致consumer有些音讯解决了,然而没来得及提交offset,难堪了。重启之后,多数音讯会再次生产一次。
其实反复生产不可怕,可怕的是你没思考到反复生产之后,怎么保障幂等性。
给你举个例子吧。假如你有个零碎,生产一条往数据库里插入一条,要是你一个音讯反复两次,你不就插入了两条,这数据不就错了?然而你要是生产到第二次的时候,本人判断一下曾经生产过了,间接扔了,不就保留了一条数据?
一条数据反复呈现两次,数据库里就只有一条数据,这就保障了零碎的幂等性
幂等性,我艰深点说,就一个数据,或者一个申请,给你反复来屡次,你得确保对应的数据是不会扭转的,不能出错。
那所以第二个问题来了,怎么保障音讯队列生产的幂等性?
其实还是得联合业务来思考,我这里给几个思路:
(1)比方你拿个数据要写库,你先依据主键查一下,如果这数据都有了,你就别插入了,update一下好吧
(2)比方你是写redis,那没问题了,反正每次都是set,人造幂等性
(3)比方你不是下面两个场景,那做的略微简单一点,你须要让生产者发送每条数据的时候,外面加一个全局惟一的id,相似订单id之类的货色,而后你这里生产到了之后,先依据这个id去比方redis里查一下,之前生产过吗?如果没有生产过,你就解决,而后这个id写redis。如果生产过了,那你就别解决了,保障别反复解决雷同的音讯即可。
还有比方基于数据库的惟一键来保障反复数据不会反复插入多条,咱们之火线上零碎就有这个问题,就是拿到数据的时候,每次重启可能会有反复,因为kafka消费者还没来得及提交offset,反复数据拿到了当前咱们插入的时候,因为有惟一键束缚了,所以反复数据只会插入报错,不会导致数据库中呈现脏数据
如何保障MQ的生产是幂等性的,须要联合具体的业务来看
如何保障音讯的幂等性
3. 如何保障音讯的牢靠传输(如何解决音讯失落的问题)?
这个是必定的,用mq有个根本准则,就是数据不能多一条,也不能少一条,不能多,就是方才说的反复生产和幂等性问题。不能少,就是说这数据别搞丢了。那这个问题你必须得考虑一下。
如果说你这个是用mq来传递十分外围的音讯,比如说计费,扣费的一些音讯,因为我以前设计和研发过一个公司十分外围的广告平台,计费零碎,计费零碎是很重的一个业务,操作是很耗时的。所以说广告零碎整体的架构外面,实际上是将计费做成异步化的,而后两头就是加了一个MQ。
咱们过后为了确保说这个MQ传递过程中相对不会把计费音讯给弄丢,花了很多的精力。广告主投放了一个广告,明明说好了,用户点击一次扣费1块钱。后果要是用户动不动点击了一次,扣费的时候搞的音讯丢了,咱们公司就会一直的少几块钱,几块钱,千里之行;始于足下,这个就对公司是一个很大的损失。
面试题分析
这个丢数据,mq个别分为两种,要么是mq本人弄丢了,要么是咱们生产的时候弄丢了。咱们从rabbitmq和kafka别离来剖析一下
rabbitmq这种mq,一般来说都是承载公司的外围业务的,数据是相对不能弄丢的
RabbitMQ可能存在的数据失落问题
(1)rabbitmq
1)生产者弄丢了数据
生产者将数据发送到rabbitmq的时候,可能数据就在半路给搞丢了,因为网络啥的问题,都有可能。
此时能够抉择用rabbitmq提供的事务性能,就是生产者发送数据之前开启rabbitmq事务(channel.txSelect),而后发送音讯,如果音讯没有胜利被rabbitmq接管到,那么生产者会收到异样报错,此时就能够回滚事务(channel.txRollback),而后重试发送音讯;如果收到了音讯,那么能够提交事务(channel.txCommit)。然而问题是,rabbitmq事务机制一搞,基本上吞吐量会下来,因为太耗性能。
所以一般来说,如果你要确保说写rabbitmq的音讯别丢,能够开启confirm模式,在生产者那里设置开启confirm模式之后,你每次写的音讯都会调配一个惟一的id,而后如果写入了rabbitmq中,rabbitmq会给你回传一个ack音讯,通知你说这个音讯ok了。如果rabbitmq没能解决这个音讯,会回调你一个nack接口,通知你这个音讯接管失败,你能够重试。而且你能够联合这个机制本人在内存里保护每个音讯id的状态,如果超过肯定工夫还没接管到这个音讯的回调,那么你能够重发。
事务机制和cnofirm机制最大的不同在于,事务机制是同步的,你提交一个事务之后会阻塞在那儿,然而confirm机制是异步的,你发送个音讯之后就能够发送下一个音讯,而后那个音讯rabbitmq接管了之后会异步回调你一个接口告诉你这个音讯接管到了。
所以个别在生产者这块防止数据失落,都是用confirm机制的。
2)rabbitmq弄丢了数据
就是rabbitmq本人弄丢了数据,这个你必须开启rabbitmq的长久化,就是音讯写入之后会长久化到磁盘,哪怕是rabbitmq本人挂了,复原之后会主动读取之前存储的数据,个别数据不会丢。除非极其常见的是,rabbitmq还没长久化,本人就挂了,可能导致大量数据会失落的,然而这个概率较小。
设置长久化有两个步骤,第一个是创立queue的时候将其设置为长久化的,这样就能够保障rabbitmq长久化queue的元数据,然而不会长久化queue里的数据;第二个是发送音讯的时候将音讯的deliveryMode设置为2,就是将音讯设置为长久化的,此时rabbitmq就会将音讯长久化到磁盘下来。必须要同时设置这两个长久化才行,rabbitmq哪怕是挂了,再次重启,也会从磁盘上重启复原queue,复原这个queue里的数据。
而且长久化能够跟生产者那边的confirm机制配合起来,只有音讯被长久化到磁盘之后,才会告诉生产者ack了,所以哪怕是在长久化到磁盘之前,rabbitmq挂了,数据丢了,生产者收不到ack,你也是能够本人重发的。
哪怕是你给rabbitmq开启了长久化机制,也有一种可能,就是这个音讯写到了rabbitmq中,然而还没来得及长久化到磁盘上,后果不巧,此时rabbitmq挂了,就会导致内存里的一点点数据会失落。
3)生产端弄丢了数据
rabbitmq如果失落了数据,次要是因为你生产的时候,刚生产到,还没解决,后果过程挂了,比方重启了,那么就难堪了,rabbitmq认为你都生产了,这数据就丢了。
这个时候得用rabbitmq提供的ack机制,简略来说,就是你敞开rabbitmq主动ack,能够通过一个api来调用就行,而后每次你本人代码里确保解决完的时候,再程序里ack一把。这样的话,如果你还没解决完,不就没有ack?那rabbitmq就认为你还没解决完,这个时候rabbitmq会把这个生产调配给别的consumer去解决,音讯是不会丢的。
(2)kafka
1)生产端弄丢了数据
惟一可能导致消费者弄丢数据的状况,就是说,你那个生产到了这个音讯,而后消费者那边主动提交了offset,让kafka认为你曾经生产好了这个音讯,其实你刚筹备解决这个音讯,你还没解决,你本人就挂了,此时这条音讯就丢咯。
这不是一样么,大家都晓得kafka会主动提交offset,那么只有敞开主动提交offset,在解决完之后本人手动提交offset,就能够保证数据不会丢。然而此时的确还是会反复生产,比方你刚解决完,还没提交offset,后果本人挂了,此时必定会反复生产一次,本人保障幂等性就好了。
生产环境碰到的一个问题,就是说咱们的kafka消费者生产到了数据之后是写到一个内存的queue里先缓冲一下,后果有的时候,你刚把音讯写入内存queue,而后消费者会主动提交offset。
而后此时咱们重启了零碎,就会导致内存queue里还没来得及解决的数据就失落了
2)kafka弄丢了数据
这块比拟常见的一个场景,就是kafka某个broker宕机,而后从新选举partiton的leader时。大家想想,要是此时其余的follower刚好还有些数据没有同步,后果此时leader挂了,而后选举某个follower成leader之后,他不就少了一些数据?这就丢了一些数据啊。
生产环境也遇到过,咱们也是,之前kafka的leader机器宕机了,将follower切换为leader之后,就会发现说这个数据就丢了
所以此时个别是要求起码设置如下4个参数:
- 给这个topic设置replication.factor参数:这个值必须大于1,要求每个partition必须有至多2个正本
- 在kafka服务端设置min.insync.replicas参数:这个值必须大于1,这个是要求一个leader至多感知到有至多一个follower还跟本人保持联系,没落伍,这样能力确保leader挂了还有一个follower吧
- 在producer端设置acks=all:这个是要求每条数据,必须是写入所有replica之后,能力认为是写胜利了
- 在producer端设置retries=MAX(很大很大很大的一个值,有限次重试的意思):这个是要求一旦写入失败,就有限重试,卡在这里了
咱们生产环境就是依照上述要求配置的,这样配置之后,至多在kafka broker端就能够保障在leader所在broker产生故障,进行leader切换时,数据不会失落
3)生产者会不会弄丢数据
如果依照上述的思路设置了ack=all,肯定不会丢,要求是,你的leader接管到音讯,所有的follower都同步到了音讯之后,才认为本次写胜利了。如果没满足这个条件,生产者会主动一直的重试,重试有限次。
1. 如何保障音讯的程序性?
其实这个也是用MQ的时候必问的话题,第一看看你理解不理解程序这个事儿?第二看看你有没有方法保障音讯是有程序的?这个生产零碎中常见的问题。
我举个例子,咱们以前做过一个mysql binlog同步的零碎,压力还是十分大的,日同步数据要达到上亿。mysql -> mysql,常见的一点在于说大数据team,就须要同步一个mysql库过去,对公司的业务零碎的数据做各种简单的操作。
你在mysql里增删改一条数据,对应进去了增删改3条binlog,接着这三条binlog发送到MQ外面,到生产进去顺次执行,起码得保障人家是依照程序来的吧?不然原本是:减少、批改、删除;你楞是换了程序给执行成删除、批改、减少,不全错了么。
原本这个数据同步过去,应该最初这个数据被删除了;后果你搞错了这个程序,最初这个数据保留下来了,数据同步就出错了。
先看看程序会错乱的俩场景
(1)rabbitmq:一个queue,多个consumer,这不显著乱了
(2)kafka:一个topic,一个partition,一个consumer,外部多线程,这不也显著乱了
那如何保障音讯的程序性呢?简略简略
(1)rabbitmq:拆分多个queue,每个queue一个consumer,就是多一些queue而已,的确是麻烦点;
或者就一个queue然而对应一个consumer,而后这个consumer外部用内存队列做排队,而后分发给底层不同的worker来解决
(2)kafka:一个topic,一个partition,一个consumer,外部单线程生产,写N个内存queue,而后N个线程别离生产一个内存queue即可
如何解决音讯队列的延时以及过期生效问题?音讯队列满了当前该怎么解决?有几百万音讯继续积压几小时,说说怎么解决?
你看这问法,其实实质针对的场景,都是说,可能你的生产端出了问题,不生产了,或者生产的极其极其慢。接着就坑爹了,可能你的音讯队列集群的磁盘都快写满了,都没人生产,这个时候怎么办?或者是整个这就积压了几个小时,你这个时候怎么办?或者是你积压的工夫太长了,导致比方rabbitmq设置了音讯过期工夫后就没了怎么办?
所以就这事儿,其实线上挺常见的,个别不出,一出就是大case,个别常见于,举个例子,生产端每次生产之后要写mysql,后果mysql挂了,生产端hang那儿了,不动了。或者是生产端出了个什么叉子,导致生产速度极其慢。
对于这个事儿,咱们一个一个来梳理吧,先假如一个场景,咱们当初生产端出故障了,而后大量音讯在mq里积压,当初事变了,慌了
(1)大量音讯在mq里积压了几个小时了还没解决
几千万条数据在MQ里积压了七八个小时,从下午4点多,积压到了早晨很晚,10点多,11点多
这个是咱们实在遇到过的一个场景,的确是线上故障了,这个时候要不然就是修复consumer的问题,让他复原生产速度,而后傻傻的期待几个小时生产结束。这个必定不能在面试的时候说吧。
一个消费者一秒是1000条,一秒3个消费者是3000条,一分钟是18万条,1000多万条
所以如果你积压了几百万到上千万的数据,即便消费者复原了,也须要大略1小时的工夫能力恢复过来
个别这个时候,只能操作长期紧急扩容了,具体操作步骤和思路如下:
1)先修复consumer的问题,确保其复原生产速度,而后将现有cnosumer都停掉
2)新建一个topic,partition是原来的10倍,长期建设好原先10倍或者20倍的queue数量
3)而后写一个长期的散发数据的consumer程序,这个程序部署下来生产积压的数据,生产之后不做耗时的解决,间接平均轮询写入长期建设好的10倍数量的queue
4)接着长期征用10倍的机器来部署consumer,每一批consumer生产一个长期queue的数据
5)这种做法相当于是长期将queue资源和consumer资源扩充10倍,以失常的10倍速度来生产数据
6)等疾速生产完积压数据之后,得复原原先部署架构,从新用原先的consumer机器来生产音讯
(2)这里咱们假如再来第二个坑
假如你用的是rabbitmq,rabbitmq是能够设置过期工夫的,就是TTL,如果音讯在queue中积压超过肯定的工夫就会被rabbitmq给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在mq里,而是大量的数据会间接搞丢。
这个状况下,就不是说要减少consumer生产积压的音讯,因为实际上没啥积压,而是丢了大量的音讯。咱们能够采取一个计划,就是批量重导,这个咱们之火线上也有相似的场景干过。就是大量积压的时候,咱们过后就间接抛弃数据了,而后等过了高峰期当前,比方大家一起喝咖啡熬夜到早晨12点当前,用户都睡觉了。
这个时候咱们就开始写程序,将失落的那批数据,写个长期程序,一点一点的查出来,而后从新灌入mq外面去,把白天丢的数据给他补回来。也只能是这样了。
假如1万个订单积压在mq外面,没有解决,其中1000个订单都丢了,你只能手动写程序把那1000个订单给查出来,手动发到mq里去再补一次
(3)而后咱们再来假如第三个坑
如果走的形式是音讯积压在mq里,那么如果你很长时间都没解决掉,此时导致mq都快写满了,咋办?这个还有别的方法吗?没有,谁让你第一个计划执行的太慢了,你长期写程序,接入数据来生产,生产一个抛弃一个,都不要了,疾速生产掉所有的音讯。而后走第二个计划,到了早晨再补数据吧。
1. 如果让你写一个音讯队列,该如何进行架构设计啊?说一下你的思路
其实聊到这个问题,个别面试官要考查两块:
(1)你有没有对某一个音讯队列做过较为深刻的原理的理解,或者从整体理解把握住一个mq的架构原理
(2)看看你的设计能力,给你一个常见的零碎,就是音讯队列零碎,看看你能不能从全局把握一下整体架构设计,给出一些关键点进去
其实答复这类问题,说白了,起码不求你看过那技术的源码,起码你大略晓得那个技术的基本原理,外围组成部分,根本架构形成,而后参照一些开源的技术把一个零碎设计进去的思路说一下就好
比如说这个音讯队列零碎,咱们来从以下几个角度来考虑一下
说实话,我个别面相似问题的时候,大部分人根本都会蒙,因为平时素来没有思考过相似的问题,大多数人就是平时埋头用,从来不去思考背地的一些货色。相似的问题,我常常问的还有,如果让你来设计一个spring框架你会怎么做?如果让你来设计一个dubbo框架你会怎么做?如果让你来设计一个mybatis框架你会怎么做?
其实答复这类问题,说白了,起码不求你看过那技术的源码,起码你大略晓得那个技术的基本原理,外围组成部分,根本架构形成,而后参照一些开源的技术把一个零碎设计进去的思路说一下就好
比如说这个音讯队列零碎,咱们来从以下几个角度来考虑一下
(1)首先这个mq得反对可伸缩性吧,就是须要的时候疾速扩容,就能够减少吞吐量和容量,那怎么搞?设计个分布式的零碎呗,参照一下kafka的设计理念,broker -> topic -> partition,每个partition放一个机器,就存一部分数据。如果当初资源不够了,简略啊,给topic减少partition,而后做数据迁徙,减少机器,不就能够寄存更多数据,提供更高的吞吐量了?
(2)其次你得考虑一下这个mq的数据要不要落地磁盘吧?那必定要了,落磁盘,能力保障别过程挂了数据就丢了。那落磁盘的时候怎么落啊?程序写,这样就没有磁盘随机读写的寻址开销,磁盘程序读写的性能是很高的,这就是kafka的思路。
2.其次你考虑一下你的mq的可用性啊?
这个事儿,具体参考咱们之前可用性那个环节解说的kafka的高可用保障机制。多正本 -> leader & follower -> broker挂了从新选举leader即可对外服务。
(4)能不能反对数据0失落啊?能够的,参考咱们之前说的那个kafka数据零失落计划
其实一个mq必定是很简单的,面试官问你这个问题,其实是个凋谢题,他就是看看你有没有从架构角度整体构思和设计的思维以及能力。的确这个问题能够刷掉一大批人,因为大部分人平时不思考这些货色。
起源:blog.csdn.net/qq_29676623/article/details/85108070
欢送关注公众号 【码农开花】一起学习成长
我会始终分享Java干货,也会分享收费的学习材料课程和面试宝典
回复:【计算机】【设计模式】有惊喜哦