

如何设计一个牛逼的消息队列? - 架构摆渡人
source link: https://www.cnblogs.com/jiagoubaiduren/p/16213891.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

大家好,我是【架构摆渡人】,一只十年的程序猿。这是消息队列的第一篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友。
通过前面文章的学习,我们对消息队列的作用以及目前主流的一些消息队列中间件有了更深刻的了解。但是那些优秀的中间件都是别人写出来的,如果你在面试的时候,面试官问你:如果让你去设计一个消息队列,你打算怎么做?如果你对消息队列了解的不彻底,那么很有可能被这个问题问懵掉,最后支支吾吾的说不知道。
我们从日常使用消息队列来入手,看设计一个消息队列到底要有哪些关键的点。当你要用消息队列的时候首先肯定是下载部署包,然后部署在服务器上。部署的这个程序我们就理解它是消息队列的服务端程序。在其他消息队列里面都有一个固定的名称:Broker。
那么为什么需要Broker呢?
你的消息要发送出去,必然得有接收方,这个接收方就是Broker。Broker收到消息后不是直接转给消费方,而是要先落盘,存储起来。这样才能保证消息不丢失,不影响业务。同时还有一些其他的业务操作,比如消息的查询。
既然说到存储,我们做业务的时候,都会用三方存储,也就是数据库,比如Mysql。但是MQ的存储,基本上都不会用三方存储,而是直接采用写磁盘的方式,也就是自己要设计要存储格式,自己写,自己解析等等一系列操作。
当然,也不是说不能用三方存储去实现,下篇文章我们再给大家讲讲如何用数据库做消息队列的存储。用数据库做存储其实也就是利用已有的实现来解决复杂度,涉及到底层存储这块,而且还要考虑高性能,其实对技术要求很高的。
像RocketMQ中的存储就涉及到CommitLog,ConsumeQueue,IndexFile等概念。最重要的是磁盘操作我们都知道很慢,而我们经常用的Mysql为了提高性能也是有一套很复杂的设计,比如redo log,buffer pool等,所以如果直接用数据库做存储,是不是相当于站在巨人的肩上去摘果实呢!
我们设计了一个Broker,使用过程中万一这个Broker挂掉了怎么办?这里是不是得考虑下高可用性,所以Broker还需要有主从的设计。
主节点的数据会同步给从节点,主节点出问题后,从节点可以顶上来提供服务,同时从节点也可以提供读的操作,为主节点减轻压力。
一个Broker是部署在某一台服务器上面,这个服务的磁盘存储空间是有限制的,不可能无限扩容。所以当消息量很大的时候,如果只是一直往机器的本地磁盘写数据,最终会写不进去的。
在设计的时候还要考虑数据分片的场景,一个Topic的数据可以分成很多份进行存储,分别存储在不同的Broker上,这样当磁盘不够的时候,可以通过增加Broker的节点来扩容。
那么问题来了,客户端写入的时候怎么知道这个Topic有哪些分片的存储信息,怎么知道有哪些Broker是在线的呢?这就要引入另一个设计:注册中心,在RocketMq中叫NameServer。
NameServer叫注册中心或者路由中心都可以,本质上都一样。Broker启动的时候需要将自身的信息告诉NameServer,同时也要保持一个心跳检查,这样NameServer才能知道Broker当前是否处于正常状态。
NameServer也要支持水平扩展,这样才能保证高可用性。既然要支持水平扩展,那么必然得无状态才行,但是NameServer本身就会存储一些数据,比如Broker信息。
这里有几个实现方式:
Broker启动的时候轮流向所有的NameServer进行注册,这样每个NameServer中都有全量的信息,即使某个节点挂了也不影响。RocketMQ就是使用的这种方式。
Broker启动的时候只向某一台NameServer进行注册,立马返回,然后NameServer之间再进行相互同步,Eureka就是使用的这种方式。
Broker启动的时候只向某一台NameServer进行注册,NameServer会同步向其他的NameServer进行数据的同步操作,等待所有写入成功或者半数写入成功,然后再返回给客户端。Zookeeper就是使用的这种方式。
服务端有了,还有一个必须要有的设计就是SDK了。应用程序通过依赖SDK就可以直接发送消息和消费消息。SDK同时可以考虑支持多语言,这样使用场景更广泛。
SDK主要是用来跟Broker通信的,所以对于网络通信我们也要选择一个合适的框架,比如Netty就非常合适,你要是觉得太难,直接用Http协议也可以,或者直接支持多协议,这些都是需要考虑的场景。
后台管理可以实现很多治理的工作,方便我们在使用消息队列的时候去排查各种问题。
核心功能点:
- 当前集群状态的查看
- 消息的查询
- 消息的消费轨迹查询
- 消息的重复投递
- 消息生产的监控大盘
- 消息消费的监控大盘
- SDK消费线程数的动态调整
本文只是简单的给大家介绍了下设计一个消息队列需要做哪些核心的工作,看起来就几个点而已。但是这几个点你要真正的去写代码实现难度是很大的。当然,我们其实也没必要自己去造轮子,因为你造了也不一定能比目前主流在用的好,但是整体的架构我们还是要了解的,至于细节就看自己需不需要深入了解了。比如消息存储那块,存储格式是怎样的?顺序写如何实现的?mmap技术如何应用的等等。
原创:架构摆渡人(公众号ID:jiagoubaiduren),欢迎分享,转载请保留出处。
Recommend
-
46
“12306”的架构到底有多牛逼? - 51CTO.COM “12306”的架构到底有多牛逼? 笔者专门研究了一下“12306”的服务端架构,学习到了其系统设计上很多亮点,在这里和大家分享一下并模拟一个例子:如何在 100...
-
24
Apache Kafka® 是 一个分布式流处理平台 . 这到底意味着什么呢? 我们知道流处理平台有以下三种特性: 可以让你发布和订阅流式的记录。这一方面与消息队列或者企业消息系统类似。 可以储存...
-
29
使用消息队列,绕不开的一个问题就是如何保证消息不丢失,现在主流的消息中间件都提供了完整的消息可靠性保证机制,可以确保消息的可靠传递,本文以rocketMq为例介绍如何保证消息不丢失,其他消息队列类似 消息传递过程 ...
-
17
简介 差不多十年前,随着功能机的淘汰和智能机的普及,互联网开始进入移动互联网时代,最具代表性的产品就是微博、微信,以及后来的今日头条、快手等。这些移动互联网时代的新产品在过去几年间借着智能手机的风高速成长。 这...
-
8
前言:在之前的业务中,使用了Kafka和RabbitMQ两种消息队列,这篇文章来做一个总结。 消息队列中间件是分布式系统中重要的组件,主要实现异步消息,应用解耦,流量削峰及消息通讯等功能。 下面举例说明在实际应用中消息队列是如何使用的。
-
8
作者:海向 来源:https://www.cnblogs.com/haixiang/p/10826710.html RabbitMQ 简述 RabbitMQ是一个消息...
-
3
架构设计(六):引入消息队列 作者:Grey 原文地址:
-
11
我与 5 种消息队列的 8 年情缘 - 架构 - dbaplus社群:围绕Data、Blockchain、AiOps的企业级专业社群。技术大咖、原创干货,每天精品原创文章推送,每周线上技术分享,每月线下技术沙龙。 谈起消息队列,内心还是会有些波澜。
-
5
V2EX › 程序员 微服务中,消息队列要单独拆一个服务进行消费吗
-
6
近期在项目中用到了无锁队列 (lock free queue)这个东西,在项目中后台需要收集数据,待收集完整后需要落地,如果收集和落地都由一个进程来做,效果不好。无锁队列是蛮实用的一种数据结构。譬如,当一些后台的任务,写数据库,文件等,会出现较长时间的阻塞,可...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK