共计 1680 个字符,预计需要花费 5 分钟才能阅读完成。
为什么要应用 MQ
当面试官问出“为什么要应用 MQ”时,其实也就是在问 MQ 有哪些作用?
1. 解耦
一个我的项目随着业务迭代会一直减少上游调用方,依照传统形式,那么每减少一个上游,就须要批改一次以后我的项目的代码,减少新的上游交互逻辑,工作量不堪称不大。
而如果在这里思考接入 MQ 作为两头代理,那么只须要将数据写入到 MQ,而不必思考简单的交互通信。并且,上游减少时,根本也不必批改上游代码,只须要让上游监听对应的通道即可。甚至,配合上动静配置,能够实现上游零批改地减少上游服务。
2. 异步
如果须要进步高延时接口的响应速度。那么,就能够思考应用 MQ 来实现异步执行,只须要将申请信息写入 MQ 就能够立刻返回,实现高响应速度,至于残余的工作交给 MQ 即可。
3. 流量削峰
如果业务中有高流量的场景,为了防止高流量一下子打到数据库层,造成数据库瘫痪,能够思考将申请写入 MQ,即 MQ 作为一个缓冲区,而后在零碎反对的生产速度下,通过上游服务一直地生产 MQ 中累积的音讯。当高峰期过后,MQ 中的积压音讯将缓缓被生产掉。
MQ 长处和毛病
长处
如上所述:
- 解耦
- 异步
- 流量削峰
毛病
- 升高了零碎的可用性。原先只有上下游,现在两头多了个 MQ。一旦 MQ 故障,整个零碎将不可用。
- 进步了零碎的复杂性。多了 MQ 之后,开发过程中可能须要思考 MQ 反复生产,音讯失落,如果保障音讯程序的问题。
- 一致性问题。MQ 作为两头代理,多个上游执行过程中,某个或多个执行失败,那么势必造成数据的不统一。
不同的 MQ 区别
总结而言,如果是技术挑战不高,举荐应用 RabbitMQ(Erlang 语言妨碍 Java 工程师深入研究把握它);如果研发能力强的,能够思考 RocketMQ;如果是用于大数据畛域,那么举荐 Kafka。
不同 MQ 架构剖析
RabbitMQ
RocketMQ
Kafka
如何保障音讯不反复生产(幂等)
- 如果将数据写入到 Mysql,须要依据表主键判断行是否存在进行新增或更新即可;
- 如果将数据写入到 redis,间接写入即可。不过,须要一个业务惟一 ID 作为 redis 的 key;
- 如果没有应用到 Mysql 或 redis,那么还是须要应用其中一个来存储曾经生产过的音讯,解决办法同上。
如何保障音讯不失落(以 RabbitMQ 为例)
1. 保障生产者不丢数据
一是能够思考开启 RabbitMQ 提供的事务操作。当产生音讯失落异样时,能够回滚事务,而后从新发送。这种形式下会极大地升高 MQ 吞吐量;
二是开启 channel 的 confirm 模式。生产者发送音讯给 MQ 后,MQ 会回传一个 ack。如果生产者没有收到,就能够重试。该监听办法是异步的,不会阻塞,能够间接进行下一条的发送。
2. 保障 MQ 不丢数据
这里须要开启 MQ 的长久化。RabbitMQ 开启长久化分两步,一是开启 queue 的长久化,这样 MQ 会长久化 queue 的元数据;二是设置发送音讯时的音讯选项,是否长久化。
当 MQ 本人宕机,重启之后,也能够从磁盘中复原 queue 和 queue 中的音讯。
3. 保障消费者不丢数据
消费者默认有 AutoAck 的设置,即消费者会主动告诉 RabbitMQ,这条音讯曾经生产实现。如果这条音讯正在生产过程中,且消费者曾经告诉 MQ 音讯生产胜利,而此时消费者又产生故障,那么这条音讯将失落。
解决办法也很显著,就是敞开 AutoAck,音讯生产完了才返回 ack。
如何保障音讯有序生产
在某些场景下,须要保障 MQ 中的音讯有序地生产。比方同一行记录的多个操作写入到 MQ(binlog 同步到 MQ),如果消费者不是有序生产的话,可能就会造成数据的不一致性。
解决办法也简略,RabbitMQ 就是一个 queue 对应一个 consumer。因为写入到一个 queue 的音讯是有序的,一个 consumer 生产起来天然也是有序的。Kafka 则是一个 partition 对应一个 consumer。
如果一个 queue 对应一个消费者的生产速度达不到业务需要,能够依据业务 key,将音讯通过 hash 算法,映射到多个内存队列,而后开启多个线程进行生产。对于同一个业务 key 的音讯,它们的生产是程序的。