有状态服务和无状态服务
二者之间最重要的一个区别在于:是否需要在本地存储持久化数据。需要在本地存储持久化数据的就是有状态服务,反之就是无状态服务。消息队列集群应该是按照有状态服务来设计的。
消息队列的集群设计思路
当前业界主流的分布式集群,一般都是基于主从(Master/Slave)思想来设计的。即通过一个组件来管理整个集群的相关工作,比如创建和删除主题、节点上下线等等。这个组件一般叫做 Master(主节点)或 Controller(控制器)。
元数据存储
消息队列集群元数据是指集群中 Topic、分区、配置、节点、权限等信息。元数据必须保证可靠、高效地存储,不允许丢失。因为一旦元数据丢失,其实际的消息数据也会变得没有意义。
依赖第三方存储引擎是指直接使用第三方组件来完成元数据信息的存储,比如 ZooKeeper、etcd、单机或者分布式数据库等等。这种方案的优点是拿来即用,无需额外的开发成本。缺点是需要依赖第三方组件,会增加额外的部署维护成本,并且受限于第三方组件的瓶颈和稳定性,也可能会有数据一致性问题。
集群内部自实现存储是指在消息队列应用内部自定义实现元数据存储服务,相当于在消息队列集群中实现一个小型的 ZooKeeper。这种方案的优点是集群内部集成了这部分能力,部署架构就很简单轻量,应用自我把控性高,不会有第三方依赖问题。缺点是开发成本高,从头开始自研,相对于成熟组件而言,稳定性上短期会比较弱,需要投入时间打磨。
节点发现
当前业界主要有配置文件、类广播机制、集中式组件三种手段来完成节点发现。
节点探活
一般需要有一个角色来对集群内所有节点进行探活或者保活,这个角色一般是主节点(Master/Leader/Controller)或第三方组件。
技术上一般分为主动上报和定时探测两种,这两种方式的主要区别在于心跳探活发起方的不同。从技术和实现上看,差别都不大,从稳定性来看,一般推荐主动上报。
主节点选举
主节点的选择一般有相互选举和依赖第三方组件争抢注册两种方式。
集群构建流程拆解
节点启动大致分为以下四步:
- 节点启动时在某个组件(如图中的 Controller 或 Metadata Service)上注册节点数据,该组件会保存该节点的元数据信息。
- 节点注册完成后,会触发选举流程选举出一个主节点(Controller)。
- 节点会定期向主节点(或 Metadata Service)上报心跳用来确保异常节点能快速被剔除。
- 当节点异常下线或有新节点上线时,同步更新集群中的元数据信息。
创建 Topic
创建 Topic 大致分为以下四步:
- 客户端指定分区和副本数量,调用 Controller 创建 Topic。
- Controller 根据当前集群中的节点、节点上的 Topic 和分区等元数据信息,再根据一定的规则,计算出新的 Topic 的分区、副本的分布,同时选出分区的 Leader(主分片)。
- Controller 调用 Metadata Service 保存元数据信息。
- Controller 调用各个 Broker 节点创建 Topic、分区、副本。
Leader 切换
Leader 切换的流程可以分为以下四步:
- Controller 会持续监听节点的存活状态,持续监控 Broker 节点是否可用。
- 根据一定的机制,判断节点挂掉后,开始触发执行 Leader 切换操作。
- Controller 通过 RPC 调用通知存活的 Broker2 和 Broker3,将对应分区的 Follower 提升为 Leader。
- 变更保存所有元数据。
此文章为11月Day15学习笔记,内容来源于极客时间《深入拆解消息队列 47 讲》