github(入门简易版)
消息队列
- 为什么使用消息队列?消息队列有什么优点和缺点?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么优点和缺点?
- 如何保证消息队列的高可用?
- 如何保证消息不被重复消费?(如何保证消息消费的幂等性)
- 如何保证消息的可靠性传输?(如何处理消息丢失的问题)
- 如何保证消息的顺序性?
- 如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?
- 如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路。
石衫的架构笔记(进阶版)
MQ的基本使用和原理(三大经典入门问题)
3.哥们,消息中间件在你们项目里是如何落地的?
---- 系统可用性降低:涉及到了MQ挂掉之后的高可用保障方案。可以参考一下:
-
通过这两篇文章,具体看看我们在各种场景下遇到MQ故障采取的高可用降级方案。
----- 系统稳定性降低:系统稳定性可能会下降,故障会增多,需要为了解决各种MQ引发的技术问题,采取很多的技术方案。
关于这个,我们后面会用专门的文章聊聊MQ中间件的这些问题的解决方案,包括:
-
消息高可靠传递(0丢失)
-
消息幂等性传递(绝对不重复)
-
百万消息积压的线上故障处理
-----分布式一致性问题(参考上面的“最终一致性分布式事务的99.99%。。。”)
消息中间件的【消费端】如何保证数据不丢失的一整套技术方案解析:
----以下分别从消费者突然宕机可能导致数据丢失,以及集群突然崩溃可能导致的数据丢失两个角度讨论了一下数据如何不丢失:
扎心!线上服务宕机时,如何保证数据100%不丢失?(消费者部分取消ack自动确认机制)
消息中间件集群崩溃,如何保证百万生产数据不丢失?(MQ的queue持久化+消息持久化)
----如何保证消息中间件全链路数据100%不丢失(1)【引出方案:生产者部分ack机制确保消息一定持久化落地到了磁盘】
----如何保证消息中间件全链路数据100%不丢失(2)【具体的手动ack机制,核心是channel+delivery tag,以及通知mq的nack机制,即失败不确认,让mq发消息给其他消费者】
----消息中间件如何实现消费吞吐量的百倍优化?(主要是unack的积压问题,从而引出channle中的prefetch count的概念)
总结:如果你是基于RabbitMQ来做消息中间件的话,消费端的代码里,必须考虑三个问题:手动ack、处理失败的nack、prefetch count的合理设置。这三个问题背后涉及到了各种机制:
自动ack机制
delivery tag机制
ack批量与异步提交机制
消息重发机制
手动nack触发消息重发机制
prefetch count过大导致内存溢出问题
prefetch count过小导致吞吐量过低
消息中间件的【生产端】如何保证数据不丢失的,相关技术方案:
具体解决方案:
1.引出了confirm机制,接着探究confirm机制投递消息的高延迟性问题。
2.首先,用来临时存放未ack消息的存储需要承载高并发写入,但不需要复杂的运算操作,这种存储首选绝对不是MySQL之类的数据库,而建议采用kv存储。kv存储承载高并发能力极强,而且kv操作性能很高。
其次,投递消息之后等待ack的过程必须是异步的,也就是类似上面那样的代码,已经给出了一个初步的异步回调的方式。
所以,整体解决confirm的高延迟的方案就是:kv存储未ack消息+channle的confirm监听器
但是,像我们上面这样从生产者到消费者的一套方案就能真的能做到100%数据不丢失吗?考虑以下情况:
生产端投递了消息到MQ,而且持久化到磁盘并且回传ack给生产端了。但是此时MQ还没投递消息给消费端,结果MQ部署的机器突然宕机。
参考的方案就是用MQ的集群机制,给一个数据做多个副本(即RabbitMQ的镜像集群机制)【类似kafka的topic+partition机制】
消息中间件优化
面试官:如果让你设计一个消息中间件,如何将其网络通信性能优化10倍以上?(kafka:batch机制 + request 机制)
解析:他会在客户端放一个内存缓冲区,每次你写一条订单(消息/partition)先放到内存缓冲区里去,然后在内存缓冲区里,会把多个订单给打包起来成为一个batch;通过这种多个batch打包成一个request一次性发往Broker的方式,又进一步提升了网络通信的效率和性能。
支撑百万连接的系统应该如何设计其高并发架构?(参考kafka的设计思想,reactor连接多路复用)