前言
几乎所有高可用集群都绕不开一个核心问题:多实例部署时,如何保证同一时间只有一个节点执行业务?
典型场景:定时任务调度、消息消费协调、库存调度、数据同步、集群控制器选主。
纵观所有开源中间件,分布式集群高可用本质只有两种实现路线,没有第三种:
-
外部中间件协调模式:业务服务无状态,依赖 MySQL / Redis / ZK 抢锁实现选主(XXL-Job 主流架构)
-
内嵌共识算法模式:服务内部集成 Raft,自己完成心跳、投票、选主,无需外部协调组件(Nacos、PowerJob 架构)

两者最大、最核心的差距:是否拥有「状态机执行能力」。
核心前置知识:什么是状态机?(区分两套架构的关键)
状态机是 Raft 协议独有的核心能力,也是普通锁方案永远无法替代的能力。
1. 定义
状态机是一套 确定性业务执行模型:
相同指令 + 相同执行顺序 = 最终数据状态绝对一致
Raft 会把所有修改操作封装成日志,同步到多数节点、落盘成功后,所有节点按统一顺序执行同一套业务逻辑,天然保证集群数据强一致。
2. 完整执行链路
客户端指令 → Raft日志同步过半节点 → 日志提交 → 统一触发状态机执行业务代码 → 落地最终状态
3. 状态机两种使用形态(非常关键)
① 空状态机(只用来选主)
不写任何业务逻辑、不落地 RocksDB、不复制业务数据。只复用 Raft 的:心跳、任期、投票、防脑裂、自动故障切换。
作用:纯替代 ZK/MySQL 锁,只做集群选主。
② 自定义业务状态机(Raft 的真正价值)
开发者重写 apply 方法,写入自己的核心业务:
- 库存原子扣减、防超卖校验
- 分布式锁抢占 / 释放
- 全局自增计数器、活动限流统计
- 订单状态流转、幂等判断
优势:全网原子执行、无并发问题、不会超卖、不会数据错乱。
4. 为什么 MySQL/Redis/ZK 没有状态机能力?
中间件锁方案只有「存储、抢锁、标记」能力,没有统一日志、没有顺序执行、没有原子业务回调。
并发场景只能:客户端查数据 → 本地计算 → 写回,天生并发不安全,无法实现原子业务逻辑。
路线一:外部中间件协调式(XXL-Job 主流方案)
1. 核心思想
业务服务本身无集群共识能力、无状态机能力。
选主交给第三方中间件,业务数据存在 MySQL,集群协调和业务数据彻底分离。
服务是彻底无状态的。
2. 三类具体实现
(1)MySQL 行锁(XXL-Job 默认)
一张全局锁表,所有节点定时竞争排他锁,抢到锁即为 Master。
- 优点:零依赖、最简单、运维成本最低
- 缺点:DB 单点压力、无多数派容错、极端场景有脑裂风险
(2)ZooKeeper ZAB 选主
利用 ZK 临时节点 + 监听机制实现抢主。
- 优点:成熟稳定、无脑裂、自动切换
- 缺点:需要独立部署 ZK 集群
Curator 的 LeaderLatch / LeaderSelector 是该方案标准工具。
(3)Redis 锁选主(Redisson)
基于 SETNX + 自动续约实现轻量选主。
- 优点:项目普遍已有 Redis,无需额外组件
- 缺点:弱一致,网络分区可能出现双主,不适合金融/库存场景
3. 架构最大特点
- 选主归选主,业务数据归业务数据
- 所有核心数据统一存在 MySQL,节点本地不存状态
- 无状态机、无法原子执行业务计算
- 服务重启、宕机、扩容完全无感
4. 适用场景
只需要「唯一节点干活」,不需要多副本一致、不需要原子业务计算:
- 定时任务调度(XXL-Job 典型场景)
- 简单消息消费协调
- 基础集群控主
路线二:内嵌共识算法 Raft(JRaft / MicroRaft / Ratis / DLedger)
1. 核心思想
业务服务自己就是集群,节点之间自动心跳、投票、选主,无需任何外部协调中间件。
Raft 是 「选主 + 日志复制 + 状态机执行业务」一体化协议。
2. Raft 可以只用来选主(很多人误解这里)
Raft 不一定要存业务数据、不一定要做复杂同步。
你可以使用 空状态机模式:
- 不落地 RocksDB
- 不复制业务日志
- 只保留:心跳、任期、自动选举、故障切换、多数派防脑裂
业务数据依然放 MySQL,仅用 Raft 替代 ZK/MySQL 锁做高可靠选主。
3. 主流开源 Raft 库
- MicroRaft:最轻量(几百KB),专门适配纯选主场景
- SOFAJRaft:功能最全,Nacos 底层依赖,可轻用、可重度业务扩展
- DLedger:RocketMQ 主从选主同款
- Apache Ratis:大数据生态标准 Raft 实现
4. Raft 架构独有优势
- 无脑裂:多数派机制永远保证集群只有一个 Leader
- 零外部依赖:Jar 内嵌,无需部署 ZK/etcd
- 可无限扩展:
- 简单场景:空状态机只做选主
- 复杂场景:开启自定义状态机 + RocksDB,实现库存、锁、计数器强一致
5. 适用场景
两种场景 必须用 Raft:
- 不想部署任何中间件,需要内嵌式、无脑裂、高可靠集群选主
- 需要原子业务逻辑、强一致数据(库存扣减、分布式锁、状态流转、全局计数)
两种架构终极对比
|-------|-------------------------|----------------------------|
| 维度 | 外部中间件选主(MySQL/ZK/Redis) | 内嵌 Raft 选主 |
| 外部依赖 | 需要独立中间件 | 无依赖,Jar 内嵌 |
| 脑裂问题 | Redis/MySQL 有风险;ZK 安全 | 多数派机制,天然无脑裂 |
| 状态机能力 | 无,仅能读写数据,无法执行业务逻辑 | 支持自定义状态机,原子执行业务 |
| 数据一致性 | 不保障业务数据一致 | 多副本强一致 |
| 运维成本 | 高(多一套集群) | 极低 |
| 核心能力 | 仅集群互斥选主 | 选主 + 日志同步 + 原子业务计算 |
| 代表项目 | XXL-Job、传统微服务 | Nacos、PowerJob、TiKV、RheaKV |
选型口诀
-
只做定时任务、只需要防重复执行 → 用 MySQL / Redis / ZK(XXL-Job 方案,够用最简单)
-
不想部署中间件、要无脑裂高可用选主 → 用 MicroRaft / JRaft 空状态机
-
需要库存原子扣减、分布式锁、强一致状态流转 → 必须 Raft 状态机 + RocksDB(MySQL/Redis/ZK 完全做不到)
全文一句话总结
分布式集群只有两种架构:
一种是依赖外部中间件抢锁选主,简单轻量化、无业务计算能力;
一种是内嵌 Raft 共识,自带选主+多副本一致+自定义状态机,既能做简单集群控主,也能支撑金融级强一致业务。