用途
异步处理
- 比如某个调用链的业务逻辑可以分为关键和非关键, 那么关键步骤执行完就能立即返回响应, 非关键步骤可以放入MQ异步地消费
- 在业务高峰期, 可以用k8s动态增加关键服务的节点, 用MQ将非关键操作暂存
- 在业务低谷期, 再动态减少关键服务的节点, 消费掉非关键服务
业务场景 | 关键步骤 | 非关键步骤 |
---|---|---|
秒杀 | 网关, 鉴权, 并发控制 | 订单生成, 短信回馈, 更新页面 |
削峰填谷
-
侵入式
-
本质上是在不同速率的服务之间用MQ做缓冲, 比如高性能网关和相对较慢的后端服务之间
-
非侵入式(令牌桶做sidecar)
分布式事务
- 半消息 + 2PC
产品对比
MQ | 特点 |
---|---|
Kafka | 适合大数据集中处理, broker采用"先攒后传"模型, 吞吐量高但延时也高 |
RocketMQ | 适合实时场景, 直接发送, 延时低, 吞吐量低 |
模型
- 生产者 -> Broker -> 消费者
- 为了提高吞吐量, 主题下有多个分区(1:N), 分区的并集是完整的主题
- 分区可以部署到多MQ实例上, 类似redis切片或水平分表的概念
- 分区可以冗余复制到多MQ集群上, 类似备库的概念
- 有序性只在分区层面上保证, 主题层面可能无序
- 多个消费者组成消费者组, 多个消费者实例并行地消费多个队列(1:1)
- 具体消费进度由offset标识
消息丢失
- 如何侦测丢失? 发送时用interceptor附加递增编号和Producer特征, 消费时查看每个分区内的消息编号是否连续
- 生产阶段: 请求-响应机制确保可靠性
- 需要正确处理
return正常
和catch重试
逻辑
- 需要正确处理
// 同步式
try {
RecordMetadata metadata = producer.send(record).get();
log.info(" 消息发送成功!");
} catch (Throwable e) {
log.warn(" 消息发送失败!尝试重试");
try {
retry10Times();
} catch (Throwable e) {
log.error("重试失败!");
return
}
}
// 异步式
producer.send(record, (metadata, exceptionHandler()) -> {
if (metadata != null) {
log.info(" 消息发送成功。");
} else {
log.warn(" 消息发送失败!, 尝试重试");
() -> exceptionHandler();
}
});
-
broker中转阶段
- 单点broker -> 先刷盘后转发
- 集群broker -> raft, 发送到一半以上broker实例再转发
-
消费阶段: 消费-反馈机制
- 1