关于java:消息中间件MQ与RabbitMQ面试题2021最新版

28次阅读

共计 10528 个字符,预计需要花费 27 分钟才能阅读完成。

为什么应用 MQ?MQ 的长处

简答

  • 异步解决 – 相比于传统的串行、并行形式,进步了零碎吞吐量。
  • 利用解耦 – 零碎间通过音讯通信,不必关怀其余零碎的解决。
  • 流量削锋 – 能够通过音讯队列长度管制申请量;能够缓解短时间内的高并发申请。
  • 日志解决 – 解决大量日志传输。
  • 音讯通信 – 音讯队列个别都内置了高效的通信机制,因而也能够用在纯的音讯通信。比方实现点对点音讯队列,或者聊天室等。

详答

次要是:解耦、异步、削峰。

解耦:A 零碎发送数据到 BCD 三个零碎,通过接口调用发送。如果 E 零碎也要这个数据呢?那如果 C 零碎当初不须要了呢?A 零碎负责人简直解体…A 零碎跟其它各种乌七八糟的零碎重大耦合,A 零碎产生一条比拟要害的数据,很多零碎都须要 A 零碎将这个数据发送过去。如果应用 MQ,A 零碎产生一条数据,发送到 MQ 外面去,哪个零碎须要数据本人去 MQ 外面生产。如果新零碎须要数据,间接从 MQ 里生产即可;如果某个零碎不须要这条数据了,就勾销对 MQ 音讯的生产即可。这样下来,A 零碎压根儿不须要去思考要给谁发送数据,不须要保护这个代码,也不须要思考人家是否调用胜利、失败超时等状况。

就是一个零碎或者一个模块,调用了多个零碎或者模块,相互之间的调用很简单,保护起来很麻烦。然而其实这个调用是不须要间接同步调用接口的,如果用 MQ 给它异步化解耦。

异步:A 零碎接管一个申请,须要在本人本地写库,还须要在 BCD 三个零碎写库,本人本地写库要 3ms,BCD 三个零碎别离写库要 300ms、450ms、200ms。最终申请总延时是 3 + 300 + 450 + 200 = 953ms,靠近 1s,用户感觉搞个什么货色,慢死了慢死了。用户通过浏览器发动申请。如果应用 MQ,那么 A 零碎间断发送 3 条音讯到 MQ 队列中,如果耗时 5ms,A 零碎从承受一个申请到返回响应给用户,总时长是 3 + 5 = 8ms。

削峰:缩小顶峰期间对服务器压力。

音讯队列有什么优缺点?RabbitMQ 有什么优缺点?

长处下面曾经说了,就是 在非凡场景下有其对应的益处 解耦 异步 削峰

毛病有以下几个:

零碎可用性升高

原本零碎运行好好的,当初你非要退出个音讯队列进去,那音讯队列挂了,你的零碎不是呵呵了。因而,零碎可用性会升高;

零碎复杂度进步

退出了音讯队列,要多思考很多方面的问题,比方:一致性问题、如何保障音讯不被反复生产、如何保障音讯可靠性传输等。因而,须要思考的货色更多,复杂性增大。

一致性问题

A 零碎解决完了间接返回胜利了,人都认为你这个申请就胜利了;然而问题是,要是 BCD 三个零碎那里,BD 两个零碎写库胜利了,后果 C 零碎写库失败了,咋整?你这数据就不统一了。

所以音讯队列理论是一种非常复杂的架构,你引入它有很多益处,然而也得针对它带来的害处做各种额定的技术计划和架构来躲避掉,做好之后,你会发现,妈呀,零碎复杂度晋升了一个数量级,兴许是简单了 10 倍。然而关键时刻,用,还是得用的。

你们公司生产环境用的是什么消息中间件?

这个首先你能够说下你们公司选用的是什么消息中间件,比方用的是 RabbitMQ,而后能够初步给一些你对不同 MQ 中间件技术的选型剖析。

举个例子:比如说 ActiveMQ 是老牌的消息中间件,国内很多公司过来使用的还是十分宽泛的,性能很弱小。

然而问题在于没法确认 ActiveMQ 能够撑持互联网公司的高并发、高负载以及高吞吐的简单场景,在国内互联网公司落地较少。而且应用较多的是一些传统企业,用 ActiveMQ 做异步调用和零碎解耦。

而后你能够说说 RabbitMQ,他的益处在于能够撑持高并发、高吞吐、性能很高,同时有十分欠缺便捷的后盾治理界面能够应用。

另外,他还反对集群化、高可用部署架构、音讯高牢靠反对,性能较为欠缺。

而且通过调研,国内各大互联网公司落地大规模 RabbitMQ 集群撑持本身业务的 case 较多,国内各种中小型互联网公司应用 RabbitMQ 的实际也比拟多。

除此之外,RabbitMQ 的开源社区很沉闷,较高频率的迭代版本,来修复发现的 bug 以及进行各种优化,因而综合思考过后,公司采取了 RabbitMQ。

然而 RabbitMQ 也有一点缺点,就是他本身是基于 erlang 语言开发的,所以导致较为难以剖析外面的源码,也较难进行深层次的源码定制和革新,毕竟须要较为扎实的 erlang 语言功底才能够。

而后能够聊聊 RocketMQ,是阿里开源的,通过阿里的生产环境的超高并发、高吞吐的考验,性能卓越,同时还反对分布式事务等非凡场景。

而且 RocketMQ 是基于 Java 语言开发的,适宜深刻浏览源码,有须要能够站在源码层面解决线上生产问题,包含源码的二次开发和革新。

另外就是 Kafka。Kafka 提供的消息中间件的性能显著较少一些,绝对上述几款 MQ 中间件要少很多。

然而 Kafka 的劣势在于专为超高吞吐量的实时日志采集、实时数据同步、实时数据计算等场景来设计。

因而 Kafka 在大数据畛域中配合实时计算技术(比方 Spark Streaming、Storm、Flink)应用的较多。然而在传统的 MQ 中间件应用场景中较少采纳。

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

ActiveMQRabbitMQRocketMQKafkaZeroMQ
单机吞吐量比 RabbitMQ 低2.6w/s(音讯做长久化)11.6w/s17.3w/s29w/s
开发语言JavaErlangJavaScala/JavaC
次要维护者ApacheMozilla/SpringAlibabaApacheiMatix,创始人已逝世
成熟度成熟成熟开源版本不够成熟比拟成熟只有 C、PHP 等版本成熟
订阅模式点对点(p2p)、播送(公布 - 订阅)提供了 4 种:direct, topic ,Headers 和 fanout。fanout 就是播送模式基于 topic/messageTag 以及依照音讯类型、属性进行正则匹配的公布订阅模式基于 topic 以及依照 topic 进行正则匹配的公布订阅模式点对点(p2p)
长久化反对大量沉积反对大量沉积反对大量沉积反对大量沉积不反对
程序音讯不反对不反对反对反对不反对
性能稳定性个别较差很好
集群形式反对简略集群模式,比方’主 - 备’,对高级集群模式反对不好。反对简略集群,’ 复制’模式,对高级集群模式反对不好。罕用 多对’Master-Slave’模式,开源版本需手动切换 Slave 变成 Master人造的‘Leader-Slave’无状态集群,每台服务器既是 Master 也是 Slave不反对
治理界面个别较好个别

综上,各种比照之后,有如下倡议:

个别的业务零碎要引入 MQ,最早大家都用 ActiveMQ,然而当初的确大家用的不多了,没通过大规模吞吐量场景的验证,社区也不是很沉闷,所以大家还是算了吧,我集体不举荐用这个了;

起初大家开始用 RabbitMQ,然而的确 erlang 语言阻止了大量的 Java 工程师去深入研究和掌控它,对公司而言,简直处于不可控的状态,然而的确人家是开源的,比较稳定的反对,活跃度也高;

不过当初的确越来越多的公司会去用 RocketMQ,的确很不错,毕竟是阿里出品,但社区可能有忽然黄掉的危险(目前 RocketMQ 已捐给 Apache,但 GitHub 上的活跃度其实不算高)对本人公司技术实力有相对自信的,举荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有沉闷的开源社区,相对不会黄。

所以 中小型公司 ,技术实力较为个别,技术挑战不是特地高,用 RabbitMQ 是不错的抉择; 大型公司,基础架构研发实力较强,用 RocketMQ 是很好的抉择。

如果是 大数据畛域 的实时计算、日志采集等场景,用 Kafka 是业内规范的,相对没问题,社区活跃度很高,相对不会黄,何况简直是全世界这个畛域的事实性标准。

MQ 有哪些常见问题?如何解决这些问题?

MQ 的常见问题有:

  1. 音讯的程序问题
  2. 音讯的反复问题

音讯的程序问题

音讯有序指的是能够依照音讯的发送程序来生产。

如果生产者产生了 2 条音讯:M1、M2,假设 M1 发送到 S1,M2 发送到 S2,如果要保障 M1 先于 M2 被生产,怎么做?

解决方案:

(1)保障生产者 – MQServer – 消费者是一对一对一的关系

缺点:

  • 并行度就会成为音讯零碎的瓶颈(吞吐量不够)
  • 更多的异样解决,比方:只有生产端呈现问题,就会导致整个解决流程阻塞,咱们不得不破费更多的精力来解决阻塞的问题。(2)通过正当的设计或者将问题合成来躲避。
  • 不关注乱序的利用理论大量存在
  • 队列无序并不意味着音讯无序 所以从业务层面来保障音讯的程序而不仅仅是依赖于音讯零碎,是一种更正当的形式。

音讯的反复问题

造成音讯反复的根本原因是:网络不可达。

所以解决这个问题的方法就是绕过这个问题。那么问题就变成了:如果生产端收到两条一样的音讯,应该怎么解决?

生产端解决音讯的业务逻辑放弃幂等性。只有放弃幂等性,不论来多少条反复音讯,最初解决的后果都一样。保障每条音讯都有惟一编号且保障音讯解决胜利与去重表的日志同时呈现。利用一张日志表来记录曾经解决胜利的音讯的 ID,如果新到的音讯 ID 曾经在日志表中,那么就不再解决这条音讯。

什么是 RabbitMQ?

RabbitMQ 是一款开源的,Erlang 编写的,基于 AMQP 协定的消息中间件

rabbitmq 的应用场景

(1)服务间异步通信

(2)程序生产

(3)定时工作

(4)申请削峰

RabbitMQ 基本概念

  • Broker:简略来说就是音讯队列服务器实体
  • Exchange:音讯交换机,它指定音讯按什么规定,路由到哪个队列
  • Queue:音讯队列载体,每个音讯都会被投入到一个或多个队列
  • Binding:绑定,它的作用就是把 exchange 和 queue 依照路由规定绑定起来
  • Routing Key:路由关键字,exchange 依据这个关键字进行音讯投递
  • VHost:vhost 能够了解为虚构 broker,即 mini-RabbitMQ server。其外部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其领有独立的权限零碎,能够做到 vhost 范畴的用户管制。当然,从 RabbitMQ 的全局角度,vhost 能够作为不同权限隔离的伎俩(一个典型的例子就是不同的利用能够跑在不同的 vhost 中)。
  • Producer:音讯生产者,就是投递音讯的程序
  • Consumer:音讯消费者,就是承受音讯的程序
  • Channel:音讯通道,在客户端的每个连贯里,可建设多个 channel,每个 channel 代表一个会话工作

由 Exchange、Queue、RoutingKey 三个能力决定一个从 Exchange 到 Queue 的惟一的线路。

RabbitMQ 的工作模式

一.simple 模式(即最简略的收发模式)

1. 音讯产生音讯,将音讯放入队列

2. 音讯的消费者(consumer) 监听 音讯队列, 如果队列中有音讯, 就生产掉, 音讯被拿走后, 主动从队列中删除(隐患 音讯可能没有被消费者正确处理, 曾经从队列中隐没了, 造成音讯的失落,这里能够设置成手动的 ack, 但如果设置成手动 ack,解决完后要及时发送 ack 音讯给队列,否则会造成内存溢出)。

二.work 工作模式(资源的竞争)

1. 音讯产生者将音讯放入队列消费者能够有多个, 消费者 1, 消费者 2 同时监听同一个队列, 音讯被生产。C1 C2 独特争抢以后的音讯队列内容, 谁先拿到谁负责生产音讯(隐患:高并发状况下, 默认会产生某一个音讯被多个消费者独特应用, 能够设置一个开关(syncronize) 保障一条音讯只能被一个消费者应用)。

三.publish/subscribe 公布订阅(共享资源)

1、每个消费者监听本人的队列;

2、生产者将音讯发给 broker,由交换机将音讯转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接管到音讯。

四.routing 路由模式

1. 音讯生产者将音讯发送给交换机依照路由判断, 路由是字符串(info) 以后产生的音讯携带路由字符(对象的办法), 交换机依据路由的 key, 只能匹配上路由 key 对应的音讯队列, 对应的消费者能力生产音讯;

2. 依据业务性能定义路由字符串

3. 从零碎的代码逻辑中获取对应的性能字符串, 将音讯工作扔到对应的队列中。

4. 业务场景:error 告诉;EXCEPTION; 谬误告诉的性能; 传统意义的谬误告诉; 客户告诉; 利用 key 路由, 能够将程序中的谬误封装成音讯传入到音讯队列中, 开发者能够自定义消费者, 实时接管谬误;

五.topic 主题模式(路由模式的一种)

1. 星号井号代表通配符

2. 星号代表多个单词, 井号代表一个单词

3. 路由性能增加含糊匹配

4. 音讯产生者产生音讯, 把音讯交给交换机

5. 交换机依据 key 的规定含糊匹配到对应的队列, 由队列的监听消费者接管音讯生产

(在我的了解看来就是 routing 查问的一种含糊匹配,就相似 sql 的含糊查问形式)

如何保障 RabbitMQ 音讯的程序性?

拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,的确是麻烦点;或者就一个 queue 然而对应一个 consumer,而后这个 consumer 外部用内存队列做排队,而后分发给底层不同的 worker 来解决。

音讯如何散发?

若该队列至多有一个消费者订阅,音讯将以循环(round-robin)的形式发送给消费者。每条音讯只会分发给一个订阅的消费者(前提是消费者可能失常解决音讯并进行确认)。通过路由可实现多生产的性能

音讯怎么路由?

音讯提供方 -> 路由 -> 一至多个队列音讯公布到交换器时,音讯将领有一个路由键(routing key),在音讯创立时设定。通过队列路由键,能够把队列绑定到交换器上。音讯达到交换器后,RabbitMQ 会将音讯的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规定);

罕用的交换器次要分为一下三种:

fanout:如果交换器收到音讯,将会播送到所有绑定的队列上

direct:如果路由键齐全匹配,音讯就被投递到相应的队列

topic:能够使来自不同源头的音讯可能达到同一个队列。应用 topic 交换器时,能够应用通配符

音讯基于什么传输?

因为 TCP 连贯的创立和销毁开销较大,且并发数受系统资源限度,会造成性能瓶颈。RabbitMQ 应用信道的形式来传输数据。信道是建设在实在的 TCP 连贯内的虚构连贯,且每条 TCP 连贯上的信道数量没有限度。

如何保障音讯不被反复生产?或者说,如何保障音讯生产时的幂等性?

先说为什么会反复生产:失常状况下,消费者在生产音讯的时候,生产结束后,会发送一个确认音讯给音讯队列,音讯队列就晓得该音讯被生产了,就会将该音讯从音讯队列中删除;

然而因为网络传输等等故障,确认信息没有传送到音讯队列,导致音讯队列不晓得本人曾经生产过该音讯了,再次将音讯分发给其余的消费者。

针对以上问题,一个解决思路是:保障音讯的唯一性,就算是屡次传输,不要让音讯的屡次生产带来影响;保障音讯等幂性;

比方:在写入音讯队列的数据做惟一标示,生产音讯时,依据惟一标识判断是否生产过;

假如你有个零碎,生产一条音讯就往数据库里插入一条数据,要是你一个音讯反复两次,你不就插入了两条,这数据不就错了?然而你要是生产到第二次的时候,本人判断一下是否曾经生产过了,若是就间接扔了,这样不就保留了一条数据,从而保障了数据的正确性。

如何确保音讯正确地发送至 RabbitMQ?如何确保音讯接管方生产了音讯?

发送方确认模式

将信道设置成 confirm 模式(发送方确认模式),则所有在信道上公布的音讯都会被指派一个惟一的 ID。

一旦音讯被投递到目标队列后,或者音讯被写入磁盘后(可长久化的音讯),信道会发送一个确认给生产者(蕴含音讯惟一 ID)。

如果 RabbitMQ 产生外部谬误从而导致音讯失落,会发送一条 nack(notacknowledged,未确认)音讯。

发送方确认模式是异步的,生产者应用程序在期待确认的同时,能够持续发送音讯。当确认音讯达到生产者应用程序,生产者应用程序的回调办法就会被触发来解决确认音讯。

接管方确认机制

消费者接管每一条音讯后都必须进行确认(音讯接管和音讯确认是两个不同操作)。只有消费者确认了音讯,RabbitMQ 能力平安地把音讯从队列中删除。

这里并没有用到超时机制,RabbitMQ 仅通过 Consumer 的连贯中断来确认是否须要从新发送音讯。也就是说,只有连贯不中断,RabbitMQ 给了 Consumer 足够长的工夫来解决音讯。保证数据的最终一致性;

上面列举几种非凡状况

  • 如果消费者接管到音讯,在确认之前断开了连贯或勾销订阅,RabbitMQ 会认为音讯没有被散发,而后从新分发给下一个订阅的消费者。(可能存在音讯反复生产的隐患,须要去重)
  • 如果消费者接管到音讯却没有确认音讯,连贯也未断开,则 RabbitMQ 认为该消费者忙碌,将不会给该消费者散发更多的音讯。

如何保障 RabbitMQ 音讯的牢靠传输?

音讯不牢靠的状况可能是音讯失落,劫持等起因;

失落又分为:生产者失落音讯、音讯列表失落音讯、消费者失落音讯;

生产者失落音讯:从生产者弄丢数据这个角度来看,RabbitMQ 提供 transaction 和 confirm 模式来确保生产者不丢音讯;

transaction 机制就是说:发送音讯前,开启事务(channel.txSelect()), 而后发送音讯,如果发送过程中呈现什么异样,事务就会回滚(channel.txRollback()), 如果发送胜利则提交事务(channel.txCommit())。然而,这种形式有个毛病:吞吐量降落;

confirm 模式用的居多:一旦 channel 进入 confirm 模式,所有在该信道上公布的音讯都将会被指派一个惟一的 ID(从 1 开始),一旦音讯被投递到所有匹配的队列之后;

rabbitMQ 就会发送一个 ACK 给生产者(蕴含音讯的惟一 ID),这就使得生产者晓得音讯曾经正确达到目标队列了;

如果 rabbitMQ 没能解决该音讯,则会发送一个 Nack 音讯给你,你能够进行重试操作。

音讯队列丢数据:音讯长久化。

解决音讯队列丢数据的状况,个别是开启长久化磁盘的配置。

这个长久化配置能够和 confirm 机制配合应用,你能够在音讯长久化磁盘后,再给生产者发送一个 Ack 信号。

这样,如果音讯长久化磁盘之前,rabbitMQ 阵亡了,那么生产者收不到 Ack 信号,生产者会主动重发。

那么如何长久化呢?

这里顺便说一下吧,其实也很容易,就上面两步

  1. 将 queue 的长久化标识 durable 设置为 true, 则代表是一个长久的队列
  2. 发送音讯的时候将 deliveryMode=2

这样设置当前,即便 rabbitMQ 挂了,重启后也能复原数据

消费者失落音讯:消费者丢数据个别是因为采纳了主动确认音讯模式,改为手动确认音讯即可!

消费者在收到音讯之后,解决音讯之前,会主动回复 RabbitMQ 已收到音讯;

如果这时解决音讯失败,就会失落该音讯;

解决方案:解决音讯胜利后,手动回复确认音讯。

为什么不应该对所有的 message 都应用长久化机制?

首先,必然导致性能的降落,因为写磁盘比写 RAM 慢的多,message 的吞吐量可能有 10 倍的差距。

其次,message 的长久化机制用在 RabbitMQ 的内置 cluster 计划时会呈现“坑爹”问题。矛盾点在于,若 message 设置了 persistent 属性,但 queue 未设置 durable 属性,那么当该 queue 的 owner node 出现异常后,在未重建该 queue 前,发往该 queue 的 message 将被 blackholed;若 message 设置了 persistent 属性,同时 queue 也设置了 durable 属性,那么当 queue 的 owner node 异样且无奈重启的状况下,则该 queue 无奈在其余 node 上重建,只能期待其 owner node 重启后,能力复原该 queue 的应用,而在这段时间内发送给该 queue 的 message 将被 blackholed。

所以,是否要对 message 进行长久化,须要综合思考性能须要,以及可能遇到的问题。若想达到 100,000 条 / 秒以上的音讯吞吐量(单 RabbitMQ 服务器),则要么应用其余的形式来确保 message 的牢靠 delivery,要么应用十分疾速的存储系统以反对全长久化(例如应用 SSD)。另外一种解决准则是:仅对要害音讯作长久化解决(依据业务重要水平),且应该保障要害音讯的量不会导致性能瓶颈。

如何保障高可用的?RabbitMQ 的集群

RabbitMQ 是比拟有代表性的,因为是基于主从(非分布式)做高可用性的,咱们就以 RabbitMQ 为例子解说第一种 MQ 的高可用性怎么实现。RabbitMQ 有三种模式:单机模式、一般集群模式、镜像集群模式。

单机模式,就是 Demo 级别的,个别就是你本地启动了玩玩儿的?,没人生产用单机模式

一般集群模式,意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。你创立的 queue,只会放在一个 RabbitMQ 实例上,然而每个实例都同步 queue 的元数据(元数据能够认为是 queue 的一些配置信息,通过元数据,能够找到 queue 所在实例)。你生产的时候,实际上如果连贯到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过去。这计划次要是进步吞吐量的,就是说让集群中多个节点来服务某个 queue 的读写操作。

镜像集群模式:这种模式,才是所谓的 RabbitMQ 的高可用模式。跟一般集群模式不一样的是,在镜像集群模式下,你创立的 queue,无论元数据还是 queue 里的音讯都会存在于多个实例上,就是说,每个 RabbitMQ 节点都有这个 queue 的一个残缺镜像,蕴含 queue 的全副数据的意思。而后每次你写音讯到 queue 的时候,都会主动把音讯同步到多个实例的 queue 上。RabbitMQ 有很好的治理控制台,就是在后盾新增一个策略,这个策略是镜像集群模式的策略,指定的时候是能够要求数据同步到所有节点的,也能够要求同步到指定数量的节点,再次创立 queue 的时候,利用这个策略,就会主动将数据同步到其余的节点下来了。这样的话,益处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还蕴含了这个 queue 的残缺数据,别的 consumer 都能够到其它节点下来生产数据。害处在于,第一,这个性能开销也太大了吧,音讯须要同步到所有机器上,导致网络带宽压力和耗费很重!RabbitMQ 一个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的残缺数据。

如何解决音讯队列的延时以及过期生效问题?音讯队列满了当前该怎么解决?有几百万音讯继续积压几小时,说说怎么解决?

音讯积压解决方法:长期紧急扩容:

先修复 consumer 的问题,确保其复原生产速度,而后将现有 cnosumer 都停掉。
新建一个 topic,partition 是原来的 10 倍,长期建设好原先 10 倍的 queue 数量。
而后写一个长期的散发数据的 consumer 程序,这个程序部署下来生产积压的数据,生产之后不做耗时的解决,间接平均轮询写入长期建设好的 10 倍数量的 queue。
接着长期征用 10 倍的机器来部署 consumer,每一批 consumer 生产一个长期 queue 的数据。这种做法相当于是长期将 queue 资源和 consumer 资源扩充 10 倍,以失常的 10 倍速度来生产数据。
等疾速生产完积压数据之后,得复原原先部署的架构,从新用原先的 consumer 机器来生产音讯。
MQ 中音讯生效:假如你用的是 RabbitMQ,RabbtiMQ 是能够设置过期工夫的,也就是 TTL。如果音讯在 queue 中积压超过肯定的工夫就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 mq 里,而是大量的数据会间接搞丢。咱们能够采取一个计划,就是批量重导,这个咱们之火线上也有相似的场景干过。就是大量积压的时候,咱们过后就间接抛弃数据了,而后等过了高峰期当前,比方大家一起喝咖啡熬夜到早晨 12 点当前,用户都睡觉了。这个时候咱们就开始写程序,将失落的那批数据,写个长期程序,一点一点的查出来,而后从新灌入 mq 外面去,把白天丢的数据给他补回来。也只能是这样了。假如 1 万个订单积压在 mq 外面,没有解决,其中 1000 个订单都丢了,你只能手动写程序把那 1000 个订单给查出来,手动发到 mq 里去再补一次。

mq 音讯队列块满了:如果音讯积压在 mq 里,你很长时间都没有解决掉,此时导致 mq 都快写满了,咋办?这个还有别的方法吗?没有,谁让你第一个计划执行的太慢了,你长期写程序,接入数据来生产,生产一个抛弃一个,都不要了,疾速生产掉所有的音讯。而后走第二个计划,到了早晨再补数据吧。

设计 MQ 思路

比如说这个音讯队列零碎,咱们从以下几个角度来考虑一下:

首先这个 mq 得反对可伸缩性吧,就是须要的时候疾速扩容,就能够减少吞吐量和容量,那怎么搞?设计个分布式的零碎呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果当初资源不够了,简略啊,给 topic 减少 partition,而后做数据迁徙,减少机器,不就能够寄存更多数据,提供更高的吞吐量了?

其次你得考虑一下这个 mq 的数据要不要落地磁盘吧?那必定要了,落磁盘能力保障别过程挂了数据就丢了。那落磁盘的时候怎么落啊?程序写,这样就没有磁盘随机读写的寻址开销,磁盘程序读写的性能是很高的,这就是 kafka 的思路。

其次你考虑一下你的 mq 的可用性啊?这个事儿,具体参考之前可用性那个环节解说的 kafka 的高可用保障机制。多正本 -> leader & follower -> broker 挂了从新选举 leader 即可对外服务。

能不能反对数据 0 失落啊?能够的,参考咱们之前说的那个 kafka 数据零失落计划。

作者:ThinkWon
起源:https://thinkwon.blog.csdn.ne…

本文首发于公众号:Java 版 web 我的项目,欢送关注获取更多精彩内容

正文完
 0