EMQX 集群
EMQX 集群是指多个 EMQX 节点协同工作,组成一个统一系统。各节点之间自动共享客户端会话、主题订阅和路由信息,实现消息的无缝传递与系统的水平扩展。
相比单节点模式需要独立处理所有连接与数据,集群架构可在节点间分担负载,在节点故障时自动重路由流量,确保服务持续可用。该架构非常适合构建大规模、关键业务的 MQTT 消息平台与物联网系统。
本章导读
本章节将全面介绍 EMQX 集群的核心概念与实践应用,包括:
无论您是构建高可用 MQTT 平台,还是准备部署生产级集群,本章节都将为您提供清晰的指导。
为什么使用 EMQX 集群
EMQX 集群适用于对可靠性、可扩展性与高性能有严格要求的大规模或关键业务系统。其主要优势包括:
- 可扩展性:通过增加节点横向扩展系统,支持不断增长的 MQTT 客户端与消息量。
- 高可用性:分布式架构避免单点故障,某些节点宕机时系统依然可用。
- 负载均衡:集群中的节点可分担消息处理与连接负载,避免资源瓶颈。
- 集中管理:支持统一的管理界面和 API,简化运维工作。
- 数据一致性与安全性:会话和路由状态在集群节点间自动同步,确保数据一致并保障通信安全。
EMQX 集群工作原理
一个 EMQX 集群由多个节点组成,每个节点都运行一个 EMQX 实例,这些节点协同工作以路由消息、管理 MQTT 会话,并确保高可用性与可扩展性。每个节点都会与其他节点通信,分享客户端订阅和路由信息,从而确保消息能够准确传递给所有相关订阅者,无论这些订阅者连接在哪个节点上。
这种分布式架构使 EMQX 能够支持关键任务型消息系统,实现极低的停机时间与灵活的横向扩展。
集群架构演进
EMQX 5.0 之前:基于 Mnesia 的集群架构
早期版本的 EMQX 使用 Erlang/OTP 内置的 Mnesia 数据库,并采用全互联(Full-Mesh)拓扑结构。每个节点通过 Erlang 分布式协议(默认端口为 4370)与集群中所有其他节点建立直接的 TCP 连接,构成一个高度耦合的系统。

然而,这种架构存在以下限制:
- 节点数增加时,同步开销显著增加
- 集群规模超过 5 个节点时,容易出现不稳定
- 扩展性有限,通常只能通过垂直扩展(提升硬件性能)来应对
EMQX 4.3 在基准测试中可支持 1000 万并发连接,但需要进行广泛的性能调优并依赖高性能硬件。详情参见性能测试报告。
EMQX 5.0 及以后:Mria + RLOG 架构
从 5.0 版本起,EMQX 引入了全新的 Mria 集群架构,支持更大规模、更稳定的集群运行。
核心改进包括:
- 核心节点与副本节点角色分离:核心节点负责写操作和完整数据复制,副本节点则只读,负责客户端会话处理。
- 复制日志(RLOG)机制:实现从核心节点到副本节点的异步、高吞吐数据复制。
- 可扩展性提升:单个集群可支持高达 1 亿个 MQTT 连接。

注意
集群功能在试用期内可用,但一旦试用期结束,您需要购买商业 License 才能继续使用该功能。没有有效的商业 License,试用期结束后,集群功能将被禁用。
为了支持这一架构,EMQX 基于 Erlang/OTP 平台,并借助一套内部数据结构来完成消息路由与投递。接下来的支撑 EMQX 集群的 Erlang/OTP 架构和集群数据结构小节将详细介绍这些运行机制。
支撑 EMQX 集群的 Erlang/OTP 架构
EMQX 基于 Erlang/OTP 平台开发,这是一个最初为构建分布式电信系统而设计的运行时系统与框架。在 Erlang 中,每个运行实例被称为一个节点(Node),其名称格式为 <name>@<host>
,例如:emqx1@192.168.0.10
。
Erlang 节点通过 TCP 连接并使用轻量级的消息传递进行通信。这种机制构成了 EMQX 集群通信的基础。所有集群节点必须使用相同的 Cookie 以完成认证。一旦连接建立并认证通过,该节点即可自动加入集群。在 EMQX 5.x 中,节点的角色(核心或副本)会决定它在数据复制与路由中的职责。
集群数据结构
为了在分布式集群中高效路由消息,EMQX 使用三种关键内部数据结构:订阅表、路由表和主题树。这些结构协同工作,确保消息即使在跨节点传输的情况下也能被正确投递给订阅者。
订阅表(分区存储)
每个 EMQX 节点维护一个本地订阅表,用于记录直接连接到该节点的客户端订阅信息。数据是分区存储的,因为每个节点仅保存自身客户端的订阅信息,从而减少了集群的同步负担并提升扩展性。
当消息被路由到某个节点时,该节点会查找本地订阅表以确定哪些客户端应接收该消息。
示例结构:
node1:
topic1 -> client1, client2
topic2 -> client3
node2:
topic1 -> client4
该示例说明了同一个主题(如 topic1
)可在多个节点上拥有订阅者,而每个节点独立管理自身的映射关系。
路由表(由核心节点复制)
路由表记录了哪些主题在哪些节点上被订阅。在 EMQX 5.x 中,该表由核心节点维护并复制到所有节点。副本节点仅保留只读副本,这些数据通过 RLOG 同步机制传输。
当客户端在副本节点上发起订阅时,该事件会被上报给核心节点,由其更新全局路由表,并同步到其他节点。
示例结构:
topic1 -> node1, node2
topic2 -> node3
topic3 -> node2, node4
主题树(由核心节点复制)
主题树是一种分层结构,用于匹配发布的主题与订阅模式(包括 MQTT 通配符 +
和 #
)。它帮助 EMQX 高效处理复杂的主题过滤逻辑。
与路由表类似,主题树由核心节点构建并同步至所有副本节点。当客户端(如 client1
)订阅 t/+/x
时,该订阅模式将被添加至主题树,并在全集群中同步更新。
主题订阅关系示例:
客户端 | 节点 | 订阅主题 |
---|---|---|
client1 | node1 | t/+/x, t/+/y |
client2 | node2 | t/# |
client3 | node3 | t/+/x, t/a |
在这些订阅建立后,EMQX 将构建如下的主题树与路由表:

消息分发流程
当一个 MQTT 客户端发布消息时,它所在的节点(无论是核心还是副本)使用主题树匹配消息主题与所有订阅模式,同时查找路由表,并根据消息主题将消息转发到对应的节点(可能是多个节点)。然后,接收到消息的节点会查找本地订阅表,并将消息发送至对应的订阅者。
例如,当客户端 1
发布一条消息到主题 t/a
时,消息在节点之间的路由和分发如下:
客户端 1
向节点 1
发布一条主题为t/a
的消息;节点 1
查询主题树,了解到t/a
与现有主题t/a
和t/#
相匹配。节点 1
查询路由表,并得知:节点 2
上有客户端订阅了t/#
主题;节点 3
上有客户端订阅了t/a
主题;因此节点 1
会将消息同时转发给节点 2
和节点 3
。
节点 2
收到转发的t/a
消息后,通过查询本地订阅表,将消息分发给订阅了t/#
的客户端。节点 3
收到转发的t/a
消息后,通过查询本地订阅表,将消息分发给订阅了t/a
的客户端。- 消息发布完成。
如需进一步了解 EMQX 集群设计,请参见 EMQX 集群设计。
集群特性概览
EMQX 基于其自研的 Ekka 库扩展了 Erlang 原生的分布式机制,提供了一整套先进的集群能力。通过 Ekka 提供的抽象层,EMQX 实现了自动节点发现、动态集群组建、网络分区处理、节点清理等关键特性。
节点发现与自动集群
EMQX 支持多种节点发现机制,可在不同的部署环境中实现自动集群:
策略 | 描述 |
---|---|
手动 | 通过手动命令创建一个集群 |
静态 | 基于静态节点列表的自动集群 |
DNS | 基于 DNS A 和 SRV 记录的自动集群 |
etcd | 通过 etcd 的自动集群 |
k8s | 基于 Kubernetes 服务的自动集群 |
详细说明请参阅:创建与管理集群。
网络分区自动修复
EMQX 提供网络分区自动修复功能,在发生网络分区时可自动恢复集群,无需人工干预,适用于对高可用性有严格要求的关键业务场景。
该功能由 cluster.autoheal
参数控制,默认启用:
cluster.autoheal = true
启用后,EMQX 会持续监测集群内节点之间的连接状态。当检测到网络分区时,会隔离受影响的节点,并继续使用剩余节点对外提供服务。一旦网络恢复,系统会自动将被隔离的节点重新加入集群。
集群节点自动清理
EMQX 支持自动清理离线节点的功能,可在配置的时间间隔后自动将断开连接的节点移出集群,从而避免长期离线节点影响集群性能。
该功能默认启用,由 cluster.autoclean
参数控制,默认时间间隔为 24 小时:
cluster.autoclean = 24h
跨节点会话保持
在 EMQX 集群模式下,MQTT 客户端的持久会话支持跨节点保持与迁移,确保连接切换时会话状态不丢失。
启用方法如下:
- MQTT 3.x 客户端:设置
clean_start = false
- MQTT 5.0 客户端:设置
clean_start = false
且session_expiry_interval > 0
启用后,当客户端断开连接时,EMQX 会保留其与 Client ID 关联的会话信息。客户端重新连接后,EMQX 会恢复之前的会话,投递断开期间积压的消息,并保留原有订阅。
例如负载均衡的两台集群节点: node1 与 node2,同一 MQTT 客户端先连接 node1,node1 节点会创建持久会话;客户端断线重连到 node2 时,MQTT 的连接在 node2 节点,持久会话仍在 node1 节点。
这一机制确保客户端在连接节点变化时,仍能收到离线期间缓存的消息,并保持订阅状态不变。
网络要求
为确保集群性能,EMQX 要求集群节点之间的网络延迟低于 10 毫秒;若延迟超过 100 毫秒,集群可能无法正常运行。
建议将核心节点部署在同一私有网络中。在 Mria+RLOG 架构下,也推荐将副本节点部署在同一私有网络内。
下一步:创建 EMQX 集群
您可继续阅读以下章节了解如何创建 EMQX 集群。