消息中间件
用途
异步处理

- 比如某个调用链的业务逻辑可以分为关键和非关键, 那么关键步骤执行完就能立即返回响应, 非关键步骤可以放入MQ异步地消费
- 在业务高峰期, 可以用k8s动态增加关键服务的节点, 用MQ将非关键操作暂存
- 在业务低谷期, 再动态减少关键服务的节点, 消费掉非关键服务
| 业务场景 | 关键步骤 | 非关键步骤 |
|---|---|---|
| 秒杀 | 网关, 鉴权, 并发控制 | 订单生成, 短信回馈, 更新页面 |
削峰填谷
-
侵入式
![img]()
-
本质上是在不同速率的服务之间用MQ做缓冲, 比如高性能网关和相对较慢的后端服务之间
-
非侵入式(令牌桶做sidecar)
![img]()
分布式事务
- 半消息 + 2PC
![img]()
产品对比
| MQ | 特点 |
|---|---|
| Kafka | 适合大数据集中处理, broker采用"先攒后传"模型, 吞吐量高但延时也高 |
| RocketMQ | 适合实时场景, 直接发送, 延时低, 吞吐量低 |
模型

- 生产者 -> Broker -> 消费者
- 为了提高吞吐量, 主题下有多个分区(1:N), 分区的并集是完整的主题
- 分区可以部署到多MQ实例上, 类似redis切片或水平分表的概念
- 分区可以冗余复制到多MQ集群上, 类似备库的概念
- 有序性只在分区层面上保证, 主题层面可能无序
- 多个消费者组成消费者组, 多个消费者实例并行地消费多个队列(1:1)
- 具体消费进度由offset标识
消息丢失
- 如何侦测丢失? 发送时用interceptor附加递增编号和Producer特征, 消费时查看每个分区内的消息编号是否连续
- 生产阶段: 请求-响应机制确保可靠性
- 需要正确处理
return正常和catch重试逻辑 - 假如响应延迟/丢失, 生产者就认为发送失败, 会造成重复发送
![img]()
- 需要正确处理
// 同步式
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实例再转发
-
消费阶段: 消费-反馈机制
- 假如消费成功, 但反馈信息延迟/丢失, broker就认为消费失败, 会造成重复消费
def callback(ch, method, properties, body):
print(" [x] 收到消息 %r" % body)
# 在这儿处理收到的消息
database.save(body)
print(" [x] 消费完成 ")
# 完成消费业务逻辑后发送消费确认响应
ch.basic_ack(delivery_tag = method.delivery_tag)
channel.basic_consume(queue='hello', on_message_callback=callback)
消息重复
- MQ可靠性等级
- 至多一次 -> 允许消息丢失, 但不会重复, 消息丢失由业务层保证
- 至少一次 -> 允许消息重复, 但不会丢失, 消息重复由业务层保证
- 恰好一次 -> 不重复不丢失
- 大多数MQ保证至少一次, 因为业务层去重更简单(接口幂等性)
- 读请求天然幂等
- 写请求
- 实现if absent逻辑, 比如建全局去重表和唯一索引/NX/xxx if not exists, 让消息先走去重表再发到消费者
- 乐观锁版本号机制, 确保一次写请求后版本号+1, 而执行写请求的前提条件是保持原版本号
- 分布式锁 + 消息全局唯一id, 对所有相同的写操作, 执行前先检查状态, 如果是未执行就执行并更新状态, 否则丢弃, 这个过程的原子性由分布式锁保证
消息积压
消费速率可以 > 生产, 但绝不能倒挂
- 生产阶段慢
- stub并发化 -> 低时延
- 批量化 -> 高吞吐
- 消费阶段慢
- stub并发化, 多reactor
- 弹性消费, 根据监控模块判断
- 如果是流量洪峰导致生产海啸 -> 消费者动态扩容
- 如果是消费者集群宕机 -> 容备灾/降级/快速恢复消费能力
- 如果是消费阻塞 -> 熔断/人工介入





浙公网安备 33010602011771号