传送门
SpringMVC的源码解析(精品)
Spring6的源码解析(精品)
SpringBoot3框架(精品)
MyBatis框架(精品)
MyBatis-Plus
SpringDataJPA
SpringCloudNetflix
SpringCloudAlibaba(精品)
Shiro
SpringSecurity
java的LOG日志框架
Activiti(敬请期待)
JDK8新特性
JDK9新特性
JDK10新特性
JDK11新特性
JDK12新特性
JDK13新特性
JDK14新特性
JDK15新特性
JDK16新特性
JDK17新特性
JDK18新特性
JDK19新特性
JDK20新特性
JDK21新特性
其他技术文章传送门入口
前言
MQ=messege queue消息中间件
- ActiveMQ:Apache,是java编写的,社区活跃度低,很少使用了
- RabbitMQ:erlang=二郎发音编写,会这个语言的不多,定制化就难,集群只保证高可用,不能提高并发,10万并发
- Kafka:开源的,Scala和java编写(Scala用了jvm),功能少(不支持死信,消息延迟等),100万并发,大数据实时计算和日志采集最佳,不遵守常见MQ协议,是自研的协议
- RocketMQ:阿里对比kafka,取其精华,java编写,10万+并发,功能多,几乎全场景使用,不遵守常见MQ协议,是自研的协议
小哈学java文章中17个方面对比下来:Kafka和RocketMQ两个最牛逼。
备注:SpringCloudNetflix的时候只支持Kafka和RabbitMQ,其他都不支持。SpringCloudAlibaba支持所有,但是提倡用RocketMQ
本文主要说一下MQ的相关面试
一、MQ优缺点
MMAP的零拷贝技术(RabbitMQ/RockitMQ):原来的拷贝是从磁盘到内存再到应用,再从应用到套接字缓冲区(内存)再到网卡,零拷贝去掉了没必要的左侧的CPU拷贝,直接从磁盘拷贝到应用然后后面阶段的路线到网卡
sendFile的零拷贝技术(kafka):原来的4次拷贝中,两次cpu拷贝直接消失了,类似百度网盘链接,磁盘到缓冲区发个百度网盘链接,不用真正的去发视频,然后到应用,然后应用再到套接字缓冲区这边也是传递这个链接(文件描述符的传递),直到网卡这边才真正的读取网盘里面的视频内容。比前面的零拷贝技术更牛逼。
sendFile的零拷贝技术(kafka)
RocketMQ为什么不用kafka的零拷贝技术,原因就是为了处理延迟消息和死信消息。
二、MQ消息重复问题处理(精品)
居然是乐观锁和唯一索引
秒啊,唯一索引这种判重,唯一键可以直接解决重复insert的问题,而重复update的问题可以依靠新表新唯一索引搞定,秒啊,太秒了。
唯一索引在redis里面的应用。都说redis是10万并发,kafka是100万,rockitMQ是10万+,MySQL只有可怜的读1000写700的样子,可以认为MySQL就是1000的并发。所以用redis key setnx命令搞定,而且不报异常。存在返回0 不存在就可以插入。
三、保证MQ消息不丢失
订单超时没有支付
生产者:
1、同步发送,生产者给MQ发消息,会阻塞当前线程,等待MQ返回结果给生成者,生产者可以拿到返回结果。
2、异步发送,生产者先构建发送消息的任务,任务丢给线程池,直接返回了发送完成,实际上并没有执行完成,MQ处理完成以后返回给我们消费者,后面通过回调函数通知我们结果
3、Oneway发送,只负责发送请求不用等待返回,不处理返回结果,性能上是比上面两种好的。这种业务上不能丢失消息的话是不用这种的,如果是日志这种消息量很大,丢几条没关系,可以用,推荐用,日志不用等待什么返回结果。
保证消息不丢失,就用同步方式。
MQ:消息数据是放到磁盘里面的,为了保证速度采用了异步刷盘策略,默认采用异步刷盘,比同步刷盘新能好。异步刷盘的时候,拿到返回结果会放到内存中,然后返回给生产者了,并且异步写入数据到硬盘,数据还没来得及写入硬盘的时候,MQ挂了,也会导致消息丢失。这种时候就要用同步刷盘了,同步刷盘是先返回结果放到内存中,然后在把内存中东西写入硬盘成功后才发给生产者。当然硬盘也会坏,这种就要保证主从架构集群搭建了。Master数据在多个slaver节点里面有备份的。
保证消息不丢失,采用同步刷盘方式。 大招:消息自动重试机制,重试时间和重试次数都可以去配置
消费者:为了保证消费速度,默认是不开启ACK确认机制的,如果消费者所在机器宕机,处理就不对了。当开启ACK确认之后,只有当我们消息处理成功之后,我们才去返回一个确认,当然性能会有所下降,并且导致重复消息问题(业务上保证幂等性就可以解决重复消息问题)。
保证消息不丢失,开启ACK确认机制。
四 、MQ百万消息持续积压问题
事前处理机制,上线前做压力测试,比如生产有2000条,消费只能消费500,则考虑增加消费集群或者消费端代码优化
事中处理机制,这种已经上线了,可能由于活动请求激增,消费者可能被压宕机,这种就得临时扩容消费者机器,高峰期过后再恢复原来部署架构。可以通过k8s动态的自动化扩缩容机制。
事后处理机制,提高消费并行度、批量方式消费(比如crm中批量更新一种活动的订单)、跳过非重要消息(比如丢弃日志)、优化每条消息的消费过程(SQL优化之类的,还有部署到SSD固态硬盘上)
五、如果保证MQ的高可用
NameServer集群启动(注册中心,管理所有Broker,维护Broker的地址、ip、topic、队列的元数据;生产者发送信息先找注册中心,然后再找Broker通信,)-》Broker启动(有自己的消息存储区域)-》创建topic-》Productor启动(生产者)-》Consumer启动(消费者)