1.消息队列有哪些作用
解耦:
使用消息队列来作为两个系统直接的通讯方式,两个系统不需要相互依赖了
异步:
使系统A给消费队列发送完消息之后,就可以继续做其它事情了
流量削峰:
如果使用消息队列的方式来调用某个系统,那么消息将在队列中排队,由消费者自己控制消费速度
2.死信队列
死信队列也是一个消息队列,它是用来存放那些没有成功消费的消息的,通常可以用来作为消息重试
3.延时队列
延时队列就是用来存放需要在指定时间被处理的元素的队列,通常可以用来处理一些具有过期性操作的业务,
比如十分钟内未支付则取消订单
4.消息队列的优缺点以及使用场景
优点:
解耦,降低系统之间的依赖
异步处理,不需要同步等待
削峰填谷,将流量从高峰期引到低谷期进行处理
缺点:
增加了系统的复杂度,幂等、重复消费、消息丢失等问题带入
系统的可用性降低,mq的故障会影响系统的可用
存在不一致的问题,消费端可能消费失败
场景:
日志采集
发布订阅
5.消息队列如何保证消息的可靠传输
消息的可靠传输就是不能重复消费,又不能丢失消息
为了避免重复消费,消费者要实现幂等性,保证就算重复消费,也不会有问题
生产者发送消息时,要确认broker确实收到并持久化了这条消息,比如rabbitmq的confirm机制,kafka的
ack机制都可以保证能正确地将消息发送给broker
broker要等待消费者真正确认消费到了消息时才删除掉消息,这里通常就是消费端的ack消息,消费者接受到
一条消息后,如果确认没问题了,就可以给broker发送一个ack,broker接收到ack后,才会删除消息
6.kafka为什么比rocketMQ吞吐量高
kafka的生产者采用的是异步发送消息的机制,当发送一条消息时,消息并没有发送到broker而是缓存起来,
然后直接向业务返回成功,当缓存的消息达到一定数量时再批量发给broker。
这种做法减少了网络IO,从而提高了消息发送的吞吐量,但是如果消息生产者宕机,会导致消息丢失,业务
出错,所以理论上kafka利用此机制提高了性能却降低了可靠性
7.如何保证消息不被重复消费
幂等:
一个数据或者一个请求,重复来多次,确保对应的数据不会改变,不能出错
思路:
如果是写redis,就没问题,使用set,天然幂等性。
生产者发送消息的时候带上一个全局唯一的id,消费者拿到消息后,先根据这个id去redis里查一下,
之前有没有消费过,如果没有消费过就处理,并且写入这个id到redis,如果消费过了,就不处理。
还可以基于数据库的唯一键
8.rabbitMQ如何保证消息的可靠性传输
1.使用事务消息
2.使用消息确认机制
发送方确认:
channel设置为confirm模式,则每条消息会被分配一个唯一id
消息投递成功,信道会发送ack给生产者,包含了id,回调confirmcallback接口
如果发生错误导致消息丢失,发送nack给生产者,回调returncallback接口
ack和nack只有一个触发,且只有一次,是异步触发。可以继续发送消息
接收方确认:
声明队列时,指定noack=false,broker会等待消费者手动返回ack,才会删除消息,否则
立刻删除
broker的ack没有超时机制,只会判断连接是否断开,如果断开,消息会被重新发送
9.使用MQ如何保证分布式事务的最终一致性
分布式事务:业务相关的多个操作,保证他们同时成功或者同时失败
最终一致性:不要求必须强一致性
1.生产者要保证100%的消息投递,事务消息机制
2.消费者需要保证幂等消费,唯一ID+业务自己实现幂等
10.kafka是pull还是push
pull模式:
根据consumer的消费能力进行数据拉取,可以控制速率
可以批量拉取、也可以单条拉取
可以设置不同的提交方式,实现不同的传输语义
缺点:
如果kafka没有数据,会导致consumer空循环,消耗资源
解决:
通过参数设置,consumer拉取数据为空或者没有达到一定数量时进行阻塞
push模式:
不会导致consumer循环等待
缺点:
速率固定、忽略了consumer的消费能力,可能导致拒绝服务或者网络拥塞等情况