1.为什么使用消息队列
消息队列是一种“先进先出”的数据结构
常见应用场景:解耦,异步,削峰
##解耦
系统的耦合性越高,容错性就越低,以电商系统为例,用户创建订单后,如果耦合调用库存系统,物流系统,支付系统,任何一个子系统出现故障或者因为升级原因导致暂时不能使用,都会造成操作异常,影响用户使用体验。
使用消息队列解耦合,系统的耦合性就会提高了,比如物流系统发生故障,需要几分钟才能修复,在这段时间内,物流系统要处理的数据被缓存到消息队列中,用户的下单操作正常完成,当物流系统回复后,补充处理存在消息队列中的订单消息即可,终端系统感知不到物流系统发生过几分钟故障。
异步
A系统接受一个请求,需要在本地写库,还需要调用B,C,D三个系统写库,这样总调用时间就会过程,用户体验非常不好
如果使用MQ,那么A系统连续发送三条消息到MQ队列中,假如耗时5ms,A系统从接受一个请求到返回响应给用户总时长就会短很多,大大提高了一用户体验
流量削峰
应用系统如果遇到系统请求流量的瞬间猛增,有可能会将系统压垮,有了消息队列可以将大量请求缓存起来,分散到很长一段时间处理,这样可以大大提到系统稳定性和用户体验
一般情况,为了保证系统的稳定性,如果系统负载超过阈值,就会阻止用户请求,这会影响用户体验,而如果使用消息队列将用户请求缓存起来,等待系统处理完毕后通知用户下单完毕,这样总比不能下单体验好。
各种消息队列产品比较
ActiveMQ:早期是使用的比较多,没有经过高吞吐量场景验证,社区也不活跃
RabbitMQ:稳定性高,elang语言开发,不考虑二次开发可以考虑
RcketMQ:java语言开发,经过高吞吐量验证,便于二次开发
kafka:大数据领域日志采集等业务推荐使用
消息队列对的优点和缺点
缺点:
系统可用性降低
系统复杂度提高
一致性问题
##系统可用性降低
系统引入的外部依赖越多,系统的稳定性越差,一旦MQ宕机,整个系统就会瘫痪
解决方案:集群
系统复杂度提高
MQ的加入大大增加了系统的复杂度,以前系统是同步的远程调用,现在是通过MQ的异步调用
一致性问题
A系统处理完业务,通过MQ给B,C,D三个系统发送消息数据,如果B系统,C系统处理成功,D系统处理失败。
如何保证消息数据处理的一致性?
通过分布式事务处理
如何保证消息队列的高可用性
RoketMQ高可用-双主双从
- 生产者通过NameServer发现Broker
- 生产者发送队列消息到2个Broker主节点
- Broker主节点分别和各自从节点同步数据
- 消费者从主或者从节点订阅消息
如何保证消息不丢失
消息丢失的原因
情况一:消息的生产者没有成功发送到MQ Broker
情况二:消息发送给MQ Broker后,Broker宕机导致内存中的消息数据丢失
情况三:消费者消费了消息,但是没有处理完毕就出现异常导致丢失
确保消息不丢失方案
- 消息发送者发送给MQ Broker后,MQ Broker给生产者确认收到
- MQ收到消息后进行消息持久化
- 消费者收到消息处理完毕后手动进行ack确认
- MQ收到消费者ack确认后删除持久化的消息
发送方可靠发送
MQ进行消息持久化
消费方消费完进行ack确认,MQ收到消费方的ack确认在删除本地消息
如何保证消息不被重读消费?如何保证消息消费的幂等性?
- 对重复消息产生的原因思考
- 对保证消息幂等性的方案
重读消息产生的原因
- 发送重读消息
当一条消息已被成功发送到服务端,此时出现了网络闪断,导致服务端对客户端的应答失败。如果此时生产者意识到消息发送失败并尝试再次发送消息,消费者后续会收到两条相同的消息
- 消费时消息重复
消息消费的场景下,消息已经投递到消费者并完成业务处理,当消费方给MQ服务端反馈应答的时候网络闪断,为了保证消息至少被消费一次,MQ服务端将在网络恢复后再次尝试投递之前之前已被消费方处理过的消息,此时消费者就会收到两条相同的消息。
- 消息幂等性
- 消息发送者发送消息时携带一个全局唯一的消息ID
- 消费者获取消费后根据id在redis/db中查询是否存在消费记录
- 如果没有消费过就正常消费,消费完毕后写入redis/db
- 如果消息消费过就直接舍弃
如何保证消息消费的顺序性
1、考察是否理解什么是顺序消息
2、考察消费者是否是思考过确保消息顺序消费的方案
消息有序指的是可以按照消息的发送顺序来消费
什么是消息的顺序消费?
- 消费方按照消息发送的顺序进行消费,分为全局消费消息和局部消费消息
- 最常见的是局部顺序消费
如何保证消息的顺序消费?
- 全局顺序消费,生产者:MQ:消费者=1:1:1
- 局部顺序消息:
- 生产者将同一组消息发送到单个队列
- 多个消费者并行对消息进行消费
- Queue通过分段锁保证消息消费的顺序性
大量消息堆积怎么处理
1、考察是否清楚消息堆积的原因
2、针对消息堆积如何进行处理
解决方案
- 检查并修复消费方的正常消费速度
- 将堆积消息转存到容量更大的MQ集群
- 增加多个消费者节点并进行消费堆积消息
- 消费完毕后,恢复原始架构
消息堆积的原因?
- 消费方消费出现故障
如何处理堆积消息
- 将堆积消息分发到更大容量的MQ集群
- 增加消费方节点并进行消费