MQ的优点
异步解耦
使用 MQ 使得应用间解耦,提升容错性和可维护性。异步能提高系统的响应速度、吞吐量。
削峰填谷
以稳定的系统资源应对突发的流量冲击。
如何防消息丢失
通用方案
1、消息持久化
2、消费者端不要使用异步消费机制
3、整个MQ挂了之后准备降级方案,可以将数据找个地方先缓存下来(redis,文件等),然后起一个任务尝试将这些数据发送到MQ。
RabbitMq
生产者确认Confirm
利用回调函数来控制消息的可控性投递
a、消息从 producer 到 exchange 则会返回一个 confirmCallback
b、消息从 exchange–>queue 投递失败则会返回一个 returnCallback
消费者确认Ack
三种确认方式: 自动确认:none、手动确认:manual、根据异常情况确认:auto
实际处理中可以设置成手动确认,业务处理成功后调用basicAck()确认成功;如果异常则调用basicNack()让其自动重新发送消息或者basicReject()拒绝消息。
RocketMq
生产者使用事务消息
1、生产者发生half消息给Mq,此时消息是在一个half队列中的
2、Mq回复half消息
3、生产者执行本地事务
4、返回本地事务状态
a、若成功commit,则进行提交,即将消息从half队列中转到正常队列中
b、若失败rollback,则进行回滚,将消息丢弃
c、若状态未知unKnown,则会定时回查生产者本地事务状态
配置同步刷盘+Dledger主从架构
同步刷盘:在返回写成功状态时,消息已经被写入磁盘。
Dledger主从架构:使用raft协议的两阶段提交(类似nacos)来保证文件在主从间同步。
Kafka
生产者配置acks
acks=0: 表示producer不需要等待broker确认收到消息的回复。性能最高,但是最容易丢消息
acks=1: 至少要等待leader已经成功将数据写入本地log
acks=-1或all:leader需要等待所有备份都成功写入本地log,最强的保证,但影响性能。
消费者配置手动提交(配置MANUAL)
处理完成后,需要手动调用acknowledge()来提交
如何防止消息被重复消费
消息重复的场景:发送时重复、投递时重复等
解决方式:在RocketMq都有唯一的MessageId可以保证唯一。
所有MQ基本都是在消费端来做重复校验,最好是使用业务上的唯一标识来防止重复
如何处理大规模积压的消息
RabbitMq
增加消费者数来快速消费
RocketMq
1、如果Topic下的MessageQueue配置得是足够多的,那么我们只要通过增加消费者就行了。
2、如果MessageQueue配置的不多,多增加消费者也没用;这时可以创建一个新的Topic,配置足够多的MessageQueue。将旧Topic中的消息转储到新的Topic中增加消费者数量来消费新的Topic。
Kafka
可以修改消费端逻辑,让其将收到的消息快速转发到其他Topic(可以设置很多分区),然后再启动多个消费者同时消费新Topic主题的不同分区。
延迟消息
RabbitMq
使用TTL(消息过期时间) + DLX(死信队列)来实现
需要给队列绑定死信交换机,这样消息过期时会发送到死信队列
RocketMq
天然支持延迟消息,给消息配置延迟级别DelayTimeLevel(18个级别)来实现
Kafka
需要代码逻辑自定义实现,可以定义不同的延迟队列(topic_1s,topic_5s),将消息发到对应的队列中,然后在消费端轮询处理,看消息有没有过期,过期就进行处理。