欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

面试进阶:如何设计一个MQ

程序员文章站 2022-04-15 20:02:31
前言如何设计一个XXX?在面试时我们经常遇到这样的问题...

前言

如何设计一个XXX?在面试时我们经常遇到这样的问题。实际上,不管是设计什么,数据库也好,MQ也好,rpc框架也好,我们想要实现其功能,一般来说是比较好实现的,数据库最基本的保存数据的功能,我们写个文件就好,rpc框架,我们用http传输完全可以实现,MQ同样也是如此。

实际上问题的难点在于,我们如何将其设计的高可用,高性能,可伸缩,如何在完成功能的基础上支持更高级的特性,如数据库的事务,MQ的exactly once,等等。

所以这一类问题,实际上考察的是我们的整体的一个架构能力,以及对常用的开源组件的原理的熟悉程度。

以MQ为例

我们知道MQ最基本的功能是传输消息,做一个缓冲。生产者发送消息至MQ,消费者从MQ拉取消息,实际上一个队列就可以实现这个功能。在这个队列的基础上,我们考虑增强其功能。

首先是如何将其实现为可伸缩的,如何能够在需要时对其进行扩容,如何增加其吞吐量。解决方法当然就是加机器,加机器可不是简单的堆叠就好了,我们要设计成分布式的系统。那么如何设计呢?这里就可以借鉴各个开源MQ的分布式架构了。以kafka为例,我们将消息抽象,分为broker -> topic -> partition这么几层,每个broker作为单独的一个存储节点,存储几个topic的某个partition。这时候数据量太大,容量不够用了怎么办呢?有了这个架构就好解决了,我们加几台机器,给要扩容的topic加几个partition,问题就简单的解决了。

那么高可用怎么保证的呢?这个的实现方式思路都是比较一致的,我们搞几个副本不就好了,每个broker我们搞两个副本,在这三个里选出一个性能最好的来作为master,剩下的两个作为slave,生产数据消费数据我们都从master里做,master同步到slave后操作才算完成,再搞个zookeeper来做监控,看哪个master节点挂了马上选出一个新的master来,这样就保证了整个系统的高可用,副本越多,越不容易出问题。

至于性能上怎么优化,则要看具体的应用场景,常用的可能就是mmap来读写发送数据,追加写文件提升效率等等。

剩下的就是我们MQ常常需要考虑的那几个问题了,消息重复,消息丢失,消息堆积,等等。

  1. 消息重复 消息重复两种可能,一种是生产者发送给MQ的消息重复了,一种是消费者重复消费了MQ里的消息,其实单单靠MQ是无法解决这个问题的,因为对于一条消息而言MQ很难知道这是一条重复的消息,除非消息有一个UUID可供鉴别,因此去重,或者说做幂等通常由生产者消费者协同来做,在消费者侧由数据库主键或者redis来做去重。而MQ需要保证每一条消息的准确送达。
  2. 消息丢失 这个问题如何解决呢?我们可以引入一个confirm机制,对于生产者,每发送一条消息到MQ,MQ收到后,发送一个confirm给生产者,对于没收到confirm的消息,生产者进行重新发送,这样保证了生产者到MQ消息的不丢失。那么MQ内部如何保证呢?我们有了之前的副本容错机制,不放心的话我们可以再加一层保险,将其持久化到硬盘,写入完成后MQ发送confirm给到生产者,这样就不会丢失了。对于消费端同样也是如此,消费端消费完成后,提交一个confirm给到MQ,MQ就知道消费完成。
  3. 消息堆积 消息堆积一般是由于消费者挂掉了或者消费者消费过慢引起的。这样的问题实际上也不是单独MQ就能够解决的。一般遇到这种问题,我们会恢复消费者的消费速度,多布几个消费节点,同时MQ的通量不够的情况下也会紧急扩容,这就利用到了上文说到的可伸缩性。当把堆积的消息处理完成后,再回复MQ和消费者至原来的状态。

本文地址:https://blog.csdn.net/GaleZhang/article/details/108205046

相关标签: 中间件