消息队列-面试连环炮
1:为什么使用消息队列?
限流:流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛。
应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,将请求消息放入消息队列,应用按照处理能力消费处理消息
异步:如用户下单发送短信或者邮件通知,可将通知消息交由消息中间件进行异步通知处理,提高系统的响应时间
解耦:用户下单后,订单系统要通知库存系统扣减库存,通知计费系统统计订单总额。可直接将下单消息发送至消息队列,由消费者自行消费,解决模块间功能耦合
假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续
操作了。实现订单系统与库存系统的应用解耦
2:消息队列有什么优点和缺点?
优点:限流、解耦、异步
缺点:系统可用性降低、系统复杂性增加、系统数据一致性问题(分布式事务)
3:如何保证消息队列的高可用?
NameServer : 提供服务路由注册、管理功能
Producer : 生产者集群
Consumer : 消费者集群
Master : 消息中间件主节点集群
Slaver : 消息中间件从节点集群
4:如何解决消息丢失、顺序消费、重复消费问题?
重复消费产生原因:生产者生产的消息,在接收到消费者消费消息通知后会将队列中的该条消息删除,若消费者消费通知发送
失败则会导致生产者队列中已消费消息未被清理,结果造成消息重复消费。
重复消费解决方案:
(1)生产者每条消息都生成一个唯一的消息id,若为数据库入库操作,利用数据库主键唯一性进行约束
(2)引入redis,消费者消费消息前先根据消息id去redis中查询该条消息是否已消费,若查询结果为空则未被消费,若结果 不为空,则认为属于重复消费
保证消息顺序消费:
(1)添加消息到FIFO队列,保证消息入队有序
(2)每条消息指定消息顺序关系(比如消息id,消息父级id),消费者据此判断消息的顺序性
防止消息丢失:生产者丢失消息、消费者丢失消息、消息队列丢失消息、消息积压
(1)生产者丢失消息(kafka):在kafka生产中,基本会存在一个leader和多个follwer,follwer会去同步leader的信息。
# producer端设置 acks=all,此配置保证follwer同步完成后,才可认为消息发送成功
# producer端设置retries=MAX,一旦消息写入消息队列失败,进行无限重试
(2)消费者丢失消息(kafka):
# 消费者处理消息异常导致消息丢失,将消费者消息处理方式由自动提交更改为手动提交。
(3)消息队列丢失消息(kafka):
# 针对消息队列丢失数据,follwer节点还未同步主节点数据,leader节点就挂了,此时zookeeper需要将其他follwer节 点升级为master节点,这就导致之前master上未同步的消息丢失
解决:replication.factor参数,这个值必须大于1,即要求每个partition必须有至少2个副本
min.insync.replicas参数,这个值必须大于1,这个是要求一个leader至少感知到有至少一个follower还跟自己保 持联系
(4)消息积压(kafka)
(1)采用服务降级措施,在生产端去除优先级较低业务的消息发送
(2)优化消费消费者端代码(或者消费者进行集群扩容),增大消费者消费效率
(3)设置消息过期时间,超过过期时间的消息直接丢弃
5:kafka、activeMq、rabbitMq、rocketMq都有什么区别?
kafka:高吞吐量
activeMq:社区活跃度较低
rabbitMq:社区活跃度高
rocketMq:阿里自研产品
6:如何设计一个消息队列?
(1)可伸缩性、扩展性(broker、topic、partition)
(2)高可用(集群、主从)
(3)可靠性(数据持久化、消息丢失、顺序消费、重复消费)