消息队列面试

烟雨 4年前 (2021-08-04) 阅读数 452 #面试

一、消息队列应用场景

异步处理

场景说明:用户注册后,需要发注册邮件和注册短信。传统的做法有两种 1.串行的方式;2.并行方式。

(1)串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。

image.png

(2)并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。

image.png

应用解耦

场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。如下图

image.png

传统模式的缺点:

  • 假如库存系统无法访问,则订单减库存将失败,从而导致订单失败

  • 订单系统与库存系统耦合

如何解决以上问题呢?引入应用消息队列后的方案,如下图:

image.png

  • 订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功

  • 库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作

  • 假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦

流量削锋

流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛

应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。

  • 可以控制活动的人数

  • 可以缓解短时间内高流量压垮应用

    image.png

  • 用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面

  • 秒杀业务根据消息队列中的请求信息,再做后续处理

日志处理

日志处理是指将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题。架构简化如下

image.png

  • 日志采集客户端,负责日志数据采集,定时写受写入Kafka队列

  • Kafka消息队列,负责日志数据的接收,存储和转发

  • 日志处理应用:订阅并消费kafka队列中的日志数据

二、如何保证消息不丢失

1、确保消息送到MQ:消息确认机制(Confirm模式)。
2、确保消息路由到正确队列:路由失败通知,可以将失败的消息返回给生产者,重新投递。
3、确保消息在队列中正确存储:交换机、队列、消息持久化。
4、确保队列的消息正确投递给消费者:手动确认模式、消费者处理完毕后确认。

三、消息重复消费,如何解决重复消费?

基本都是消息投/消费后没有正确回复MQ,导致的重复投/消费。
1、要求消息的幂等性。
2、MVCC多版本并发控制:乐观锁的一种实现。也就是说,生产者发送消息要带上版本号,消费者更新时,对比版本号,若不一致则无法成功。
3、去重表:利用数据库表的特性来实现幂等性,表上建立一个唯一索引,保证某一类数据一旦执行完毕,后续同样的请求不在处理了。比如:利用日志表来记录处理成功的消息ID。

四、如何进行RocketMQ的性能调优

JVM层面

暂停监控
消除偏向锁:RockeMQ都是多线程操作,没必要使用偏向锁,通过JVM参数:-XX:-UseBiasedLocking禁用偏向锁。
垃圾回收参数:
-Xms8G -Xmx8G -Xmn4G -XX:+UseG1GC
堆空间,年轻代多给一点内存,RockeMQ推荐使用G1垃圾回收器。
-XX:G1HeapRegionSize=16M
G1收集器的region(区域)大小设置为16M.
-XX:G1ReservePercent=25
G1管理老年代里预留25%的空闲内存,保证新生代对象进入老年代时,有足够的空间。
-XX:initiatingHeapOccupancyPercent=30
当堆内存使用率达到30%后自动启动G1的并发垃圾回收。

操作系统层面

基本参数
vm.overcommit_memory=1
是否允许内存过量分配{0:当用户申请内存时,内核去检查是否有这么大的内存,1:内核始终认为,是有足够的内存空间,直到他用完为止,2:内核禁止任何形式的过量分配内存}
vm.swappiness=10
swappiness=0:仅在内存不足的情况下,当空闲内存低于vm.min_free_bkytes_limit时,使用交换空间。
swappiness=1:内核版本3.5及以上、Red Hat内核版本2.6.32-303及以上,尽量少用交换空间。
swappiness=10:当前系统内存足够时,推荐设置,可提高性能。
swappiness=60:默认值。
swappiness=100:内核将积极的使用交换空间。
vm.max_max_count=655360
定义了一个进程能拥有最多的线程。
ulimit=1000000
limits.conf设置用户能打开的最大文件数。
网卡
关闭IROBalance 
IROBalance主要功能是可以合理利用调度分配到各个CPU核心上,特别针对目前主流多核心CPU,但是实际往往影响CPU使用的均衡性。建议关闭。
TCP NODEALY
Nagle算法用于对缓冲区内的一定数量的消息进行自动连接。该处理过程成为Nagling,通过减少必要发送的封包数量,提高网络应用程序系统的效率(Nagle虽然解决了小封包问题,但是也导致了较高的不可预期的延迟,同时降低了吞吐量,所以不需要开启Nagle算法)。


版权声明

非特殊说明,本文由Zender原创或收集发布,欢迎转载。

上一篇:Redis面试 下一篇:1、NIO基础

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

作者文章
热门