目 录
[第一章 自动分片:数据如何被透明打散](#第一章 自动分片:数据如何被透明打散)
[1.1 为什么需要分片](#1.1 为什么需要分片)
[1.2 透明分片:业务零感知](#1.2 透明分片:业务零感知)
[1.3 主键分片逻辑:哈希路由](#1.3 主键分片逻辑:哈希路由)
[1.4 分区与节点的映射](#1.4 分区与节点的映射)
[1.5 自动分片的三大优势](#1.5 自动分片的三大优势)
[第二章 多主写入:所有数据节点同时可写](#第二章 多主写入:所有数据节点同时可写)
[2.1 什么是多主写入](#2.1 什么是多主写入)
[2.2 与"单写多读"的本质区别](#2.2 与"单写多读"的本质区别)
[2.3 多主写入的并发提升逻辑](#2.3 多主写入的并发提升逻辑)
[2.4 多主写入的前提:同步复制](#2.4 多主写入的前提:同步复制)
[第三章 内存存储:速度与持久化的平衡艺术](#第三章 内存存储:速度与持久化的平衡艺术)
[3.1 内存优先:热点数据常驻内存](#3.1 内存优先:热点数据常驻内存)
[3.2 磁盘落地:持久化如何实现](#3.2 磁盘落地:持久化如何实现)
[3.3 定时备份与崩溃恢复](#3.3 定时备份与崩溃恢复)
[3.4 内存存储对业务的启示](#3.4 内存存储对业务的启示)
[第四章 跨节点数据同步与事务一致性](#第四章 跨节点数据同步与事务一致性)
[4.1 同步复制:多副本实时一致](#4.1 同步复制:多副本实时一致)
[4.2 两阶段提交:分布式事务的骨架](#4.2 两阶段提交:分布式事务的骨架)
[4.3 事务隔离级别:READ COMMITTED](#4.3 事务隔离级别:READ COMMITTED)
[4.4 锁机制:行级锁与乐观并发](#4.4 锁机制:行级锁与乐观并发)
[第五章 同步复制的代价与一致性边界](#第五章 同步复制的代价与一致性边界)
[5.1 同步复制的代价:写延迟](#5.1 同步复制的代价:写延迟)
[5.2 一致性窗口:为什么说"提交即一致"](#5.2 一致性窗口:为什么说"提交即一致")
[第六章 毫秒级响应与百万级并发:底层技术支撑](#第六章 毫秒级响应与百万级并发:底层技术支撑)
[6.1 为什么能支撑百万级并发](#6.1 为什么能支撑百万级并发)
[6.2 高性能的适用边界](#6.2 高性能的适用边界)
[7.1 读完本篇,你应该带走什么](#7.1 读完本篇,你应该带走什么)
[7.2 下一步建议](#7.2 下一步建议)
回顾与导读:从"架构长什么样"到"性能从哪里来"
前两篇回答了 NDB"是什么"和"由什么组成":它是 MySQL 内置的分布式集群存储引擎,由管理节点、数据节点、SQL 节点三层架构组成,依靠节点冗余与心跳机制实现无单点故障。
但"高可用"之外,NDB 的另一面是"高性能"------官方定位的典型场景是毫秒级延迟、百万级并发。这一篇就深入引擎内部,讲清楚四件事:数据如何被自动打散(自动分片)、多节点为何能同时写入(多主写入)、数据在内存与磁盘之间如何流转(内存存储)、跨节点的一致性与并发如何保证(同步、事务与锁)。
读完这一篇,你将理解 NDB 高性能、可横向扩容的底层逻辑,也就能明白它"能做什么、不能做什么"的真正原因。
第一章 自动分片:数据如何被透明打散
1.1 为什么需要分片
单机数据库的容量与吞吐受限于一台服务器的内存、CPU 与磁盘。NDB 的解法是"分片":把一张大表的数据拆成多份,分布到集群中的多台数据节点上并行处理。
分片(在 NDB 中称为分区 Partition)并非新鲜概念,真正的差异在于"谁来分、怎么分、业务要不要管"------这正是 NDB 自动分片的价值所在。
1.2 透明分片:业务零感知
NDB 的分片发生在存储引擎内部,对 SQL 完全透明:
- 建表时使用 ENGINE=NDBCLUSTER,无需声明任何分片规则。
- 应用照常写标准 SQL,引擎自动完成数据路由与结果汇总。
- 业务不需要维护分片键、不需要改造查询、不需要引入中间件。
这与分库分表(应用层/中间件层拆表)形成鲜明对比:分库分表需要提前规划分片键、改写 SQL、处理跨片查询;而 NDB 把这一切封装在引擎内部。
1.3 主键分片逻辑:哈希路由
NDB 默认使用主键作为分区键,采用 KEY 分区(按键分区)方式:
- 引擎对主键值调用哈希函数(NDB 使用 MD5)计算散列值。
- 根据散列值将行映射到具体的分区编号。
- 分区再按"节点组分配规则"落到对应的数据节点。
由于哈希函数对输入敏感,相近的主键值会均匀散落到不同分区,天然规避热点------这正是 NDB 各节点负载均衡的根基。
1.4 分区与节点的映射
回顾第二篇的公式:分区数 = 数据节点数 × LDM 线程数;节点组数 = 数据节点数 ÷ 副本数。分区被分配到节点组,组内每个节点保存该分区的一份副本。
以 4 数据节点(2 个节点组)、副本数 2 的经典集群为例,一张 NDB 表会被切成 4 个分区:
|------------|---------------|---------------|----------------|
| 分区 | 所在节点组 | 主副本位置 | 备份副本位置 |
| 分区 0 | 节点组 0 | 节点 1 | 节点 2 |
| 分区 1 | 节点组 1 | 节点 3 | 节点 4 |
| 分区 2 | 节点组 0 | 节点 2 | 节点 1 |
| 分区 3 | 节点组 1 | 节点 4 | 节点 3 |
主备交叉摆放 + 哈希均匀分布,使得任何一个数据节点都只承载约一半分区的主副本,读写负载在集群内均匀展开。
1.5 自动分片的三大优势
- 免改造:业务无需手动分库分表,SQL 语法零变化。
- 免路由维护:分片规则由引擎内置,不存在中间件层面的路由表。
- 免人工搬迁:在线扩容后数据自动重新分布,无需导出导入。
需要提醒的边界:NDB 分区默认基于主键,因此"通过主键/唯一键定位单行"的访问模式最高效;无主键的复杂扫描、大范围 JOIN 则会退化为跨分区操作,性能受限(本篇第六章会展开)。
第二章 多主写入:所有数据节点同时可写
2.1 什么是多主写入
在传统主从架构中,写入只能发生在主库,从库只读;在 MGR 中虽然支持多主,但写入仍需组内协调。NDB 的多主是另一层含义:所有数据节点都是"平级"的,任何节点都能接受写入请求,不存在"主数据节点"与"从数据节点"之分。
更准确地说,NDB 的写入路径是"SQL 节点接入 → 按分区路由 → 分区主副本所在的数据节点执行 → 同步复制到备份副本"。由于分区在节点间均匀分布,写入压力天然被分摊到所有数据节点。
2.2 与"单写多读"的本质区别
|--------------|----------------|-------------------|
| 对比维度 | 主从单写多读 | NDB 多主写入 |
| 写入位置 | 仅主库可写 | 所有数据节点均可写 |
| 写入瓶颈 | 主库单点,写入能力封顶 | 写入随节点数扩展 |
| 数据一致性 | 异步/半同步,有延迟窗口 | 同步复制,事务级一致 |
| 故障影响 | 主库故障需切换,期间写不可用 | 单节点故障,写入自动路由到其他副本 |
| 扩展方式 | 扩展读能力,写难以扩展 | 读写均可横向扩展 |
2.3 多主写入的并发提升逻辑
多主写入带来并发提升的逻辑可以拆成三步:
- 写入请求按主键哈希均匀路由到不同分区,各分区的主副本分散在不同节点上,多个节点的写入互不争抢同一把"全局写锁"。
- 数据节点内部采用多线程(ndbmtd)并行处理不同分区的操作,单节点吞吐进一步放大。
- 集群整体写入吞吐 ≈ 节点数 × 单节点吞吐,因此加数据节点即可近乎线性提升写入能力。
一个形象的类比:主从架构像"只有一个收银台的大型超市"------顾客再多也要排队;NDB 多主像"按商品分区开多个收银台"------客流自动分散,加收银台就能接待更多顾客。
2.4 多主写入的前提:同步复制
多主之所以敢"同时写",是因为每个写入都在所有副本上同步完成后才提交------不存在"主库先写、从库慢慢追"的窗口。这是下一章要展开的核心机制,也是理解 NDB 一致性模型的关键。
第三章 内存存储:速度与持久化的平衡艺术
3.1 内存优先:热点数据常驻内存
NDB 是内存优先(in-memory)存储引擎:表数据主要驻留在数据节点内存中。读取直接命中内存,写入先落内存再异步持久化------这是 NDB 毫秒级延迟的第一来源。
正因如此,NDB 对数据节点内存容量有硬性要求:每个节点必须能容纳其负责分区的全部数据(官方文档明确建议节点配置大内存)。这也是"NDB 不适合海量冷数据"的根本原因。
3.2 磁盘落地:持久化如何实现
内存虽快但易失,NDB 通过三重机制保证数据不丢:
- 重做日志(Redo Log):每次事务提交前,变更记录先写入各数据节点的重做日志缓冲区并落盘(WAL 思路),内存数据即使丢失也可按日志重放恢复。
- 本地检查点(Local Checkpoint):定期把内存中的表数据快照写入磁盘(数据文件),缩短崩溃后需要重放的日志范围,加速恢复。
- 磁盘数据表(Disk Data Tables):对于不常访问或体量大的表,可指定落盘存储,作为内存容量的延伸。
|------------|---------------|------------|
| 机制 | 作用 | 时机 |
| 内存表数据 | 提供毫秒级读写 | 常驻,持续服务 |
| Redo Log | 事务持久化保证,崩溃可重放 | 每次提交,先写日志 |
| 本地检查点 | 数据快照落盘,缩短恢复时间 | 周期性自动执行 |
| 磁盘数据表 | 冷数据/大表延伸存储 | 按表配置启用 |
3.3 定时备份与崩溃恢复
除引擎内部的 Redo Log 与检查点外,NDB 还提供在线备份(Online Backup)能力:通过管理客户端命令对集群进行一致性备份,备份过程业务可正常读写。
崩溃恢复的完整链路是:节点重启 → 从最近检查点加载数据快照 → 重放检查点之后的 Redo Log → 恢复到崩溃前的一致状态 → 重新加入集群并与其他副本完成数据对齐。由于检查点 + Redo Log 的双重机制,恢复时间可控,这也是 NDB 能承诺 99.999% 可用性的技术基础。
3.4 内存存储对业务的启示
理解内存存储机制后,两条选型建议自然浮现:
- NDB 最适合"数据总量可控、实时性要求高"的业务------数据都能放内存,延迟才有保证。
- 若数据体量远超内存、或大量冷数据长期积压,应优先评估磁盘数据表或改用 InnoDB 生态。
第四章 跨节点数据同步与事务一致性
4.1 同步复制:多副本实时一致
NDB 的复制是同步复制(Synchronous Replication),发生在存储引擎内部、数据节点之间:一次写入不仅要写主副本,还要同步写到同节点组内的备份副本,所有副本确认后才算提交成功。
这与主从复制的异步日志回放有本质区别:主从有"从库落后主库"的延迟窗口,NDB 则保证------提交成功那一刻,数据在所有副本上都是一致的,任何节点接管服务都不会丢数据。
4.2 两阶段提交:分布式事务的骨架
当一次事务涉及多个分区(跨节点)时,NDB 使用两阶段提交(2PC)保证原子性:
- 第一阶段(Prepare):事务协调者(发起事务的 SQL 节点)向所有涉及的数据节点发送准备请求,各节点执行操作并锁定资源,返回"准备就绪"。
- 第二阶段(Commit):协调者确认所有节点准备就绪后,广播提交指令;各节点完成提交并释放资源。
两阶段提交确保了"要么全部成功、要么全部回滚",跨节点事务不会出现部分提交的中间状态。这也是 NDB 在分布式环境下保持事务一致性的核心骨架。
4.3 事务隔离级别:READ COMMITTED
NDB 在隔离级别上做了取舍:仅支持 READ COMMITTED(读已提交)。
- 优点:读操作不加长事务锁,读性能高;每个语句看到的是已提交的数据,避免脏读。
- 代价:不支持 REPEATABLE READ / SERIALIZABLE,同一事务内多次查询可能看到不同数据(不可重复读)。
对于大多数高并发实时业务(订单状态、余额查询、计费扣减),READ COMMITTED 是够用且更高效的;但对"一个事务内多次读取必须一致"的报表类场景,则需要应用层自行补偿。
4.4 锁机制:行级锁与乐观并发
- 行级锁:NDB 以行为单位加锁,不同行的并发操作互不阻塞,避免表级锁的全局串行化。
- 主键定位:绝大多数锁都落在"主键/唯一键定位到的行"上,锁范围小、持有时间短。
- 乐观并发:NDB 的部分操作采用乐观策略(冲突检测而非预先加锁),在低冲突场景下显著提升并发吞吐。
锁机制的工程意义:NDB 牺牲了部分隔离性(仅 READ COMMITTED),换取了更小的锁粒度与更高的并发度------这是为"高并发实时业务"做的明确设计取舍。
第五章 同步复制的代价与一致性边界
本章与第四章共同构成"一致性与并发"的完整图景:上一章讲机制骨架,本章补充两个容易混淆的细节。
5.1 同步复制的代价:写延迟
同步复制带来强一致,也带来代价:每次写事务都要等所有副本确认,单次写入的网络往返与落盘开销大于单机 InnoDB。
因此 NDB 的性能画像非常鲜明------读极快(内存 + 无锁化路径)、写延迟稳定但单条开销更高。它擅长的是"高并发、短事务、主键驱动的读写混合"场景,而非"单条超大事务、批量灌数据"场景。
5.2 一致性窗口:为什么说"提交即一致"
在主从架构中,"主库写成功"与"从库看到数据"之间存在时间差;在 NDB 中,事务提交成功的定义本身就包含了"所有副本都已写入"。
这意味着:一旦应用收到提交成功响应,任何数据节点(含刚接管的主副本)都能读到这条数据------不存在"读到旧数据"的窗口。这是 NDB 与异步复制方案最本质的一致性差异,也是电信、支付类业务选择它的理由。
|--------------|----------------|------------------|
| 对比维度 | 主从异步复制 | NDB 同步复制 |
| 提交定义 | 主库落盘即返回 | 所有副本确认才返回 |
| 一致性窗口 | 存在延迟窗口 | 提交即一致,无窗口 |
| 写延迟 | 低(只写主库) | 较高(跨副本确认) |
| 读一致性 | 可能读到旧数据 | 任何副本读取一致 |
第六章 毫秒级响应与百万级并发:底层技术支撑
把前面的机制串起来,NDB 高性能的底层逻辑可以归纳为"五驾马车":
|--------------|----------------|--------------|
| 技术支柱 | 机制说明 | 直接收益 |
| 内存存储 | 数据常驻内存,读写不经过磁盘 | 毫秒级读写延迟 |
| 哈希分片 | 主键哈希均匀分布,多节点并行 | 吞吐随节点线性扩展 |
| 多主写入 | 所有节点可写,写入分摊 | 写入并发不受单点限制 |
| 行级锁 | 细粒度锁 + 短事务 | 高并发下冲突率低 |
| 同步复制 | 提交即一致,无延迟窗口 | 读全部副本都正确 |
6.1 为什么能支撑百万级并发
百万级并发不是单机能力,而是"集群能力":
- 横向扩展:数据自动分片到多节点,每个节点只处理一部分数据的读写,加节点即加吞吐。
- 负载均衡:主备交叉摆放 + 哈希均匀分布,节点间负载自然均衡,不出现"一台累死、其他闲着"。
- 接入层弹性:多个 SQL 节点配合负载均衡,接入并发可随业务量灵活伸缩。
- 并行处理:ndbmtd 多线程数据节点并行处理各分区请求,单节点内再放大一层并发。
6.2 高性能的适用边界
需要清醒认识:NDB 的高性能是有条件的,它最擅长的是"窄表、短行、主键驱动、读写混合、短事务"的访问模式。以下场景性能会明显劣化:
- 无主键/大范围扫描:需跨全部分区聚合,退化为分布式扫描。
- 复杂 JOIN:跨节点关联代价高,官方文档明确指出范围扫描与 JOIN 存在性能问题。
- 超大字段:TEXT/BLOB 处理受引擎限制,访问效率低。
- 超大批量写入:单条写入跨副本确认的开销叠加,批量灌入效率不占优。
一句话总结:NDB 是为"海量短小并发请求"而生的引擎,把它用在对的访问模式上,百万级并发是可达的;用错场景,性能会大打折扣。
读者收获与下一步
7.1 读完本篇,你应该带走什么
- 自动分片 = 主键哈希 + 引擎内路由 + 业务零感知,省掉了分库分表的全部心智负担。
- 多主写入的本质是"分区主副本分散在各节点 + 同步复制兜底",写入吞吐可随节点扩展。
- 内存优先 + Redo Log + 检查点 + 在线备份,构成速度与持久性的完整闭环。
- 同步复制与两阶段提交保证了"提交即一致",代价是写延迟略高、仅支持 READ COMMITTED。
- NDB 高性能有明确边界:擅长主键驱动的短事务高并发,不擅长扫描、JOIN 与批量灌入。
7.2 下一步建议
下一篇将进入实操:从零部署一个 NDB 集群(管理节点、数据节点、SQL 节点完整配置),并演示故障转移与在线扩容实验。届时你会发现,前两篇讲的架构与原理,会在每一步操作中一一得到印证。