为什么要使用消息队列,解决什么问题?(消峰、解藕、异步)
消峰填谷
客户端=》 网关 =〉 消息队列=》秒杀服务
异步解耦
消息队列中的重要概念理解。(主题、消费组、队列,游标?)
主题(Topic)
消息传输和存储的顶层容器,用于标识同一类业务逻辑的消息
队列(MessageQueue)
消息存储和传输的实际容器,一个Topic有多个队列,可水平扩展
消息(Message)
单位消息,每个消息都有扩展性,负载等信息
消费者(Consumer)
接受并处理消息的运行实体,取到消息业务逻辑进行处理,分PushConsumer和PullConsumer等
消费者组
也叫Consumer ID,多个消费行为一致的消费者的负载均衡分组
生产者
构建并传输消息到服务端的运行实体
消息队列的两种模式
队列模式
发布-订阅模式
如何实现多消息者订阅同一份消息
RabbitMQ消息模式
生产者将消息发送给Exchange交换机,交换机路由到不同的队列,不同的消费者针对不同的队列进行消费,实现简单、但是消息存储冗余
RocketMQ/Kafka消息模式
生产者将消息推送到队列之后,如果有消费者去消费这个主题上的消息,在队列上记录下不同消费者互不干扰不同的消费位置,它就可享有同一份消息
RocketMQ 部署架构
核心关系:主题、队列、消费者、消费组、消费位置
最佳实践:合理划分主题和Tag
接入Rocket MQ,业务消息的拆分可以基于Topic进行,也可以基于消息tag和属性进行
遵守三个基本原则
1、消息的类型是否一致:不同类型的消息,如顺序消息和普通消息需要使用不同的主题进行拆分,无法通过tag标签进行分类
2、业务域是否相同:不同业务域和部门的消息应该拆分不同的主题。例如物流消息和支付消息应该使用两个不同的主题
3、消息量级和重要性是否一致:如果消息的量级规模存在巨大差异,或者说消息的链路重要程度存在差异,则应该使用不同的主题进行隔离拆分
订阅关系一致性
同一个消费组、订阅的Topic一样,且过滤的表达式也要一致
消息堆积怎么办?
1、发送端堆积(比较少见)
批量发送
增加并发
2、消费端堆积
增加资源:
加机器、升配置等。增加机器无效果考虑增加topic队列数
提升消费性能
优化消费逻辑,批量并发消费、改用性能更好的语言
解决报错
顺序消费,某个队列单条消息消费失败(大量的消费重试),导致队列阻塞,堆积
系统降级
服务重要业务,降低影响
一定要保证消费端的性能要高于生产端的发送性能、这样才的系统才能健康的持续运行
Rocket MQ 如何确保消息不丢失(生产、存储、消费三个阶段)
生产阶段 消息在生产者创建出来,经过网络传输到Broker端
检查发送状态、失败要有补偿机制
存储阶段 在这个阶段消息在Broker端存储。
集群部署,主备都写成功,才返回成功
消费阶段 Consumer从Broker上拉取消息,经过网络传输到Consumer上
失败重试、消费者失败回应RECONSUMER_LATER
重试多次进入死信队列、堆积监控。
如何处理消费过程中的重复问题?(消费重复的情况必然存在,如何幂等处理?)
在MQTT协议中,给出了三种传递消息时能够提供服务质量的标准
At most once: 无可靠性保证、允许丢消息
At least once:至少被送达一次。即不丢消息,但也有少量重复。
Exactly once:消息只会被送达一次,不丢失也不重复
幂等性
At least once+幂等性 = Exactly once
1、利用数据库的唯一约束实现幂等(主键、如Redis setnx)
2、为更新的数据设置前置条件
3、记录并检查操作(Token机制或者GUID(全局唯一ID)机制)
Rocket MQ 如何解决消息顺序问题?(全局有序只能开一个队列,局部有序,要求顺序放同一个队列)
顺序消息:有网络延迟如何保证消费顺序?
因为网络延迟M2消息比M1先到Server服务端
全局有序
增加ACK确认机制,全局串行,缺点只要一条消息有问题,就会全局阻塞
局部有序
需要顺序消费时,针对队列加锁串行消费,这样实现局部有序,适用于大多数场景,使得同一个Topic中多个队列能并行消费,提高效率
RocketMQ 事务消息:二阶段消息+反查机制
概念:事务消息,主要解决生产方和消费方的数据最终一致性问题。
Q1:作为消息发送方,如何保证两步数据一致?
Q2:作为消息发送方,能保证消费时一定成功么?