目录

  • 一、什么是消息队列
  • 优点:
  • 缺点:
  • 二、常见MQ产品
  • 三、如何保证传输信息的不丢失?
  • 1、数据会在哪些情况下丢失?
  • 2、如何避免生产者写入数据到MQ的时候发生丢失?
  • `Kafka`:消息发送+回调函数:发送成功之后,生产者会收到MQ的回调
  • `RocketMQ`: 1、采用消息发送+回调 2、采用事务消息的思想
  • `RabbitMQ`:1、采用消息发送+回调 2、采用手动事务
  • 3、如何避免MQ主从同步的时候数据丢失?
  • `RocketMQ`: 1、普通消息:使用同步同步,或者异步同步的方式;2、Dledger集群,至少三个结点:选举、两阶段的事务提交
  • `RabbitMQ`:1、普通集群:节点之间不会主动进行数据的同步,容易造成数据丢失;2、镜像集群:节点之间会主动进行数据的同步,数据安全性得到提高
  • `Kafka`: 本身允许部分数据的丢失
  • 4、如何避免`MQ`存盘的时候数据丢失?
  • `RocketMQ`:同步刷盘 异步刷盘:同步刷盘能保证数据存盘的成功,但是吞吐量很低;异步刷盘吞吐量很高,但是可能存在存盘不成功但是返回结果成功的情况
  • `RabbitMQ`:将队列配置为持久化队列,在3.x版本中有一个队列类型叫Quorum的队列,会采用Raft协议来进行消息同步
  • 5、如何避免消费者对`MQ`进行消费的时候数据丢失?
  • `RocketMQ`:使用默认的方式进行消费,不采用异步的方式
  • `RabbitMQ`:将autoCommit更改为手动提交offset
  • `Kafka`:手动提交offset
  • 四、如何保证消息消费的幂等性
  • 1、所有`MQ`产品都没有主动解决幂等性的问题,需要消费者自己控制
  • 2、`RocketMQ`: 给每一个消息分配一个Message ID,这个ID作为一个消费者判断幂等的依据;但是这种机制对于RabbitMQ和Kafka并不适用,而且当RocketMQ中消息变多时,也无法保证Message ID全局唯一
  • 3、最好自带一个有业务标识的ID,如OrderID或者统一分配ID
  • 五、如何保证消息的顺序?
  • 1、`Kafka`和`RabbitMQ`本身没法保证消息的顺序,只有对`Kafka`和`RabbitMQ`的使用场景进行定制才能保证有序
  • 2、`MQ`只需要保证局部有序,不需要保证全局有序
  • 3、`RocketMQ`使用MessageSelector将一组有序的消息放在同一个队列中,消费者需要消费整个队列中的消息
  • 六、如何保证消息的高效读写?
  • 1、常规的文件拷贝
  • `RocketMQ`采用的是mmap,例如commitLog
  • `Kafka`的index日志文件采用的也是mmap,其余文件没有采用零拷贝的方式;并且Kafka采用transfile的方式将硬盘数据加载到网卡。
  • 七、如何保证分布式事务的最终一致性?
  • 1、什么是分布式事务?
  • 2、`MQ`要达成最终一致性的话,需要保证两点:
  • 生产者100%将消息发出:采用事务消息机制
  • 消费者需要保证幂等性消费:为每一个消息设置一个唯一ID+通过业务逻辑实现幂等的操作
  • 3、拓展:分布式`MQ`的三种语义:
  • 八、如何自己设计一个MQ?
  • 1、思考的方式应该从整体到细节;从业务场景出发,再到技术实现
  • 2、以现有的产品为基础:`RocketMQ`就是一个很好的产品


一、什么是消息队列

MQ是一个FIFO的队列:一端连接生产者,一端连接消费者;

优点:

异步:实现异步消息的发送,提高系统的吞吐量和响应速度
解耦:减少服务之间的影响,提高系统的稳定性和课扩展性
削峰:以稳定的系统资源应对突发的流量冲击

缺点:

系统的可用性降低:一旦MQ宕机,整个业务系统将会受影响
系统的复杂度提高

二、常见MQ产品

Kafka:集群高可用,吞吐量大,性能非常好;缺点:数据容易丢失,功能比较单一;使用场景:日志分析,大数据收集的场景
RabbitMQ:消息可靠性高,功能全面;缺点:吞吐量比较低,消息累计之后会造成性能的下降,erlang语言难以做到定制;使用场景:小规模场景
RocketMQ:高吞吐,高性能,功能非常全面;缺点:RocketMQ是阿里提供的,开源版本功能不全;而且周边生态不完整;几乎适用于所有场景

三、如何保证传输信息的不丢失?

1、数据会在哪些情况下丢失?

Java mps是什么_Java mps是什么

2、如何避免生产者写入数据到MQ的时候发生丢失?

Kafka:消息发送+回调函数:发送成功之后,生产者会收到MQ的回调
RocketMQ: 1、采用消息发送+回调 2、采用事务消息的思想

Java mps是什么_kafka_02

RabbitMQ:1、采用消息发送+回调 2、采用手动事务

手动事务:channel.txSelect() 开启事务
channel.txCommit() 提交事务
channel.txRollback() 回滚事务

这种方式会对channel产生阻塞,降低系统的吞吐量。

最新的RabbitMQ支持的Publish Confirm。采用的思想和RocketMQ事务消息相似。

3、如何避免MQ主从同步的时候数据丢失?

RocketMQ: 1、普通消息:使用同步同步,或者异步同步的方式;2、Dledger集群,至少三个结点:选举、两阶段的事务提交

Java mps是什么_队列_03

RabbitMQ:1、普通集群:节点之间不会主动进行数据的同步,容易造成数据丢失;2、镜像集群:节点之间会主动进行数据的同步,数据安全性得到提高
Kafka: 本身允许部分数据的丢失

4、如何避免MQ存盘的时候数据丢失?

RocketMQ:同步刷盘 异步刷盘:同步刷盘能保证数据存盘的成功,但是吞吐量很低;异步刷盘吞吐量很高,但是可能存在存盘不成功但是返回结果成功的情况
RabbitMQ:将队列配置为持久化队列,在3.x版本中有一个队列类型叫Quorum的队列,会采用Raft协议来进行消息同步

5、如何避免消费者对MQ进行消费的时候数据丢失?

RocketMQ:使用默认的方式进行消费,不采用异步的方式
RabbitMQ:将autoCommit更改为手动提交offset
Kafka:手动提交offset

Java mps是什么_消息队列_04

四、如何保证消息消费的幂等性

1、所有MQ产品都没有主动解决幂等性的问题,需要消费者自己控制
2、RocketMQ: 给每一个消息分配一个Message ID,这个ID作为一个消费者判断幂等的依据;但是这种机制对于RabbitMQ和Kafka并不适用,而且当RocketMQ中消息变多时,也无法保证Message ID全局唯一
3、最好自带一个有业务标识的ID,如OrderID或者统一分配ID

五、如何保证消息的顺序?

1、KafkaRabbitMQ本身没法保证消息的顺序,只有对KafkaRabbitMQ的使用场景进行定制才能保证有序

RabbitMQ要保证exchange只对应一个队列,而且一个队列只对应一个消费者
Kafka要定制生产者的partition,将消息分配到同一个partition下;每一个topic只对应一个消费者

2、MQ只需要保证局部有序,不需要保证全局有序

3、RocketMQ使用MessageSelector将一组有序的消息放在同一个队列中,消费者需要消费整个队列中的消息

Java mps是什么_java_05

六、如何保证消息的高效读写?

KafkaRocketMQ采用零拷贝的方式实现文件的高效读写

1、常规的文件拷贝

Java mps是什么_队列_06


零拷贝的做法:不直接拷贝文件,只拷贝文件的映射,分为mmaptransfile

Java mps是什么_消息队列_07


Java中对零拷贝进行了封装;mmap采用MappedByteBuffer对象进行操作,而transfile采用FileChannel进行操作。

mmap拷贝方式适用于小文件:1.5G-2G

transfile拷贝方式无文件大小限制

RocketMQ采用的是mmap,例如commitLog

Kafka的index日志文件采用的也是mmap,其余文件没有采用零拷贝的方式;并且Kafka采用transfile的方式将硬盘数据加载到网卡。

七、如何保证分布式事务的最终一致性?

1、什么是分布式事务?

分布式事务指:业务相关的多个操作,要么全部成功,要么全部失败;比如下单操作可以分为支付和物流发货,两者需同时成功或者同事失败
最终一致性指:多个操作最终状态的完成可以存在一定的延时,只需要最终可以达到正确的状态即可;比如下单和发货操作,不一定一下单扣钱就完成发货单的生成,中间可以存在一定的间隔

2、MQ要达成最终一致性的话,需要保证两点:

生产者100%将消息发出:采用事务消息机制
消费者需要保证幂等性消费:为每一个消息设置一个唯一ID+通过业务逻辑实现幂等的操作

3、拓展:分布式MQ的三种语义:

At least once:生产者每次发送完消息都需要确认是否发送成功,否则重新发送;消费者同样每次消费完之后都需要确认是否消费成功
At most once:生产者发完一次消息之后就完事了,不重复确认是否发送成功;消费者消费完之后就完事了,也不重复确认是否消费成功
Exactly once:刚刚好发送(消费)一次;
RocketMQ官方并不能保证exactly once,商业版中提供了exactly once实现机制
Kafka最新版本提供了exactly once的demo
RabbitMQ:erlang天生就是一道屏障(用的人太少了),很少用来实现最终一致性

八、如何自己设计一个MQ?

1、思考的方式应该从整体到细节;从业务场景出发,再到技术实现
2、以现有的产品为基础:RocketMQ就是一个很好的产品

思路:1、MQ的作用,项目大概的样子:先设计出一个单机FIFO的数据结构;高效,可扩展

2、将单机队列扩展为分布式队列 -分布式的集群管理

3、基于Topic定制生产者消息分发的路由策略:发送者路由策略、消费者与队列对应关系(一个消费者对应多个队列、一个消费者只对应队列集群中的其中一个队列),消费者路由策略

4、实现高效的网络通信。Netty、Http

5、规划日志文件、实现文件高效读写:零拷贝,顺序写,服务重启后快速还原现场

6、定制高级功能:死信队列、延迟队列、事务消息等等:贴合实际,随意发挥

Java mps是什么_队列_08