为什么使用消息队列 MQ ?

消息队列的常见使用场景有很多,比较核心的有3个,解耦、异步、削峰。

进行放款申请时,其中有一个步骤需要生成合同成功后,需要发送一条短信给客户,让客户签署。 通过加入消息队列,异步的形式发送短信,以提升业务处理速度。即使发送短信服务不可用,也可等待其服务可用时,重新从消息队列里获取信息,发送短信,不会阻塞主业务。 除此之外,除了发送短信,如果需要增加其他的业务,比如站内信服务提醒,可以随时加入进行消息消费。 还有就是,业务系统在每个时间点处接受到的请求数量不一样,高峰期,服务器处理能力并不能应对突然的流量,可以通过时间换取空间,将 需要处理的业务放入消息队列中,让服务器慢慢消费,处理,达到平缓处理突发请求的效果。

如何选择消息队列

producers → exchanges → queues → consumers

rabbitMq: 稳定性,可靠性高。适合对数据一致性要求较高的场景。

kafka: 分布式消息发布订阅系统,性能高效,可扩展良好并且可持久化,兼容性比较好,在大数据领域,优先支持,极限处理能力可以超过每秒2k万条消息,缺点是延迟比比较高,topic 过多,性能会下降。

RocketMQ: Java开发,参考kafka,性能、稳定性、 可靠性值得信赖,中文设计,持续发展,Java开发,扩展和2次开发容易

如何保证消息不丢失?

  • 确保消息到 MQ

  • 确保消息路由到正确的队列

  • 确保消息在队列中正确的存储

  • 确保消息从队列中正确的投递给消费者

解决方案:

  • 发送方确认模式 设置连接工厂时,需要打开消息确认开关,在 rabbittemplate中需要设置一个回调函数,进行 ack 确认处理

  • 路由失败通知,打开通知 Mandatory,开启失败通知,再设置一个回调方法,失败通知执行方法。

  • 交换器、队列、消息都需要持久化

  • 消费者手动确认消费消息,配置消息容器,开启手动确认。

什么是消息重复?

发送时重复 - 网络 - 卡顿 - 本身

消费重复

  • 应用处理发送问题,没有发出确认

  • 应用处理完成,网络出现问题

  • 应用处理超时

  • 消息中间件出问题,宕机,重启后,又重发

如何解决MQ中的重复消息?

主要要求接受者来处理这种重复情况,要求消费者的消息处理是幂等操作。

去重表,利用数据库特性,设计一个唯一性的键,例如id,当消息来时,先插入到表中,如果不存在,则进行业务处理,并确认消息消费,如果存在,则捕获异常,直接确认返回。适用于分布式,在各个服务可以针对业务不同单独设计一张这种表来处理消息重复问题。

消息队列的优缺点、使用场景

优点: - 解耦 - 异步处理 - 削峰

缺点 - 增加系统复杂度,需要处理幂等、重复消费、消息丢失等问题 - 一致性,消费端可能失败 - 可用性降低,mq故障会影响系统可用

场景: 日志采集、发布订阅等

如何保证消息可靠传输

  • 不能重复消息

  • 消息成功发送

死信队列、延时队列

死信队列,也是一个消息队列,只是存放那些没有成功消费的消息,延长消息的生命周期。 延时队列,指定需要在多久后才能被消费,用来处理一些过期新的操作业务,比如 10 分钟内未支付则取消订单。