目录
- 一、什么是消息队列
- 优点:
- 缺点:
- 二、常见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、数据会在哪些情况下丢失?
2、如何避免生产者写入数据到MQ的时候发生丢失?
Kafka
:消息发送+回调函数:发送成功之后,生产者会收到MQ的回调
RocketMQ
: 1、采用消息发送+回调 2、采用事务消息的思想
RabbitMQ
:1、采用消息发送+回调 2、采用手动事务
手动事务:channel.txSelect()
开启事务channel.txCommit()
提交事务channel.txRollback()
回滚事务
这种方式会对channel产生阻塞,降低系统的吞吐量。
最新的RabbitMQ
支持的Publish Confirm。采用的思想和RocketMQ
事务消息相似。
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
的使用场景进行定制才能保证有序
RabbitMQ
要保证exchange只对应一个队列,而且一个队列只对应一个消费者Kafka
要定制生产者的partition,将消息分配到同一个partition下;每一个topic只对应一个消费者
2、MQ
只需要保证局部有序,不需要保证全局有序
3、RocketMQ
使用MessageSelector将一组有序的消息放在同一个队列中,消费者需要消费整个队列中的消息
六、如何保证消息的高效读写?
Kafka
和RocketMQ
采用零拷贝的方式实现文件的高效读写
1、常规的文件拷贝
零拷贝的做法:不直接拷贝文件,只拷贝文件的映射,分为mmap
和transfile
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的demoRabbitMQ
:erlang天生就是一道屏障(用的人太少了),很少用来实现最终一致性
八、如何自己设计一个MQ?
1、思考的方式应该从整体到细节;从业务场景出发,再到技术实现
2、以现有的产品为基础:RocketMQ
就是一个很好的产品
思路:1、MQ
的作用,项目大概的样子:先设计出一个单机FIFO的数据结构;高效,可扩展
2、将单机队列扩展为分布式队列 -分布式的集群管理
3、基于Topic定制生产者消息分发的路由策略:发送者路由策略、消费者与队列对应关系(一个消费者对应多个队列、一个消费者只对应队列集群中的其中一个队列),消费者路由策略
4、实现高效的网络通信。Netty、Http
5、规划日志文件、实现文件高效读写:零拷贝,顺序写,服务重启后快速还原现场
6、定制高级功能:死信队列、延迟队列、事务消息等等:贴合实际,随意发挥