第20章 MySQL Cluster高可用架构深度实践:构建分布式数据库集群
MySQL Cluster高可用架构实践详解 摘要:本文深入探讨MySQL Cluster分布式数据库集群的架构设计与部署实践。首先解析了MySQL Cluster的核心概念,包括其Share-Nothing架构、三种节点类型(管理节点、数据节点、SQL节点)的分工协作机制,以及数据自动分片技术。通过电信计费系统等商业案例,展示了该架构在高并发、高可用场景中的优势。随后详细介绍了在Linux环境下
第20章 MySQL Cluster高可用架构深度实践:构建分布式数据库集群
20.1 MySQL Cluster核心概念与商业价值
在当今的互联网和电信级应用中,数据量呈爆炸式增长,对数据库的可用性、扩展性和实时性提出了极高要求。传统的单机数据库或主从复制架构,在面对海量并发和数据分片需求时,往往显得力不从心。MySQL Cluster作为一款分布式数据库系统,通过其独特的Share-Nothing架构和自动分片能力,为这类场景提供了理想的解决方案。
20.1.1 什么是MySQL Cluster:分布式数据库的基石
MySQL Cluster是一款基于NDB(Network DataBase)存储引擎的分布式数据库,它允许将数据分散存储在多台服务器上,并实现99.999%的高可用性。与传统的MySQL主从复制不同,Cluster中的每个数据节点都持有数据的一部分,并且所有节点之间实时同步,任何单点故障都不会导致数据丢失或服务中断。
从商业视角看,MySQL Cluster特别适合以下场景:
- 电信计费系统:需要处理海量呼叫记录,要求实时计费且不容许停机。
- 在线游戏:玩家状态、道具信息需要快速读写,且必须保证数据强一致。
- 金融交易:实时风控、交易流水记录,要求高并发、低延迟。
- 物联网平台:海量设备上报数据的实时处理与存储。
20.1.2 节点类型详解:管理节点、数据节点、SQL节点
MySQL Cluster由三种不同类型的节点组成,每种节点承担不同的职责:
- 管理节点(Management Node):负责管理集群配置、启动/停止节点、备份恢复等。它不存储数据,只维护集群的元信息。通常只需要一个管理节点,但为了高可用可以配置两个。
- 数据节点(Data Node):存储实际数据,运行NDB存储引擎。数据被自动分片(分区)并复制到多个数据节点,以实现高可用和负载均衡。每个数据节点保存一部分数据,并且可以有多个副本(片段副本)。
- SQL节点(SQL Node):提供标准的MySQL接口,应用程序通过SQL节点访问集群。SQL节点本质上是运行了mysqld进程的服务器,它使用NDB引擎连接数据节点。SQL节点不存储数据,只负责解析SQL并路由到数据节点。
理解这三种节点的分工是部署MySQL Cluster的基础。在实际部署中,可以将不同节点部署在同一台物理服务器上(测试环境),但生产环境建议分开部署,避免资源竞争。
20.1.3 共享无共享架构与数据自动分片
MySQL Cluster采用Share-Nothing架构,即每个数据节点拥有自己的内存和磁盘,节点之间通过网络通信。数据自动分片:当创建表时,可以指定分区键(通常是主键或唯一键),Cluster会根据分区键自动将数据均匀分布到所有数据节点上。同时,每个数据片段会在集群中自动同步到另一个数据节点(副本),形成数据冗余。例如,设置两个片段副本,那么每个分区会在两个不同的数据节点上各存一份,确保任意一个数据节点故障,数据仍然可用。
这种架构带来的好处:
- 水平扩展:通过增加数据节点,可以线性提升集群的存储容量和处理能力。
- 高可用:节点故障自动切换,应用无感知。
- 实时性:所有节点数据同步,无复制延迟。
20.1.4 商业场景:电信计费系统为何选择MySQL Cluster
以某省级电信运营商的计费系统为例,该系统需要处理全省3000万用户的实时话单,高峰时每秒处理10万条呼叫记录。要求:
- 数据不能丢,账单必须准确。
- 系统全年停机时间不超过5分钟。
- 随着用户增长,能够平滑扩展。
传统架构无法满足:单机数据库扛不住并发;主从复制有延迟,可能造成计费不实时。MySQL Cluster凭借其高吞吐、强一致、自动分片特性,完美匹配了需求。该运营商最终采用4个数据节点(每个节点256GB内存)、2个SQL节点、2个管理节点的集群架构,稳定运行多年。
20.2 Linux环境下MySQL Cluster部署实战
接下来,我们以四台Linux服务器为例,详细演示MySQL Cluster 5.7的部署过程。假设服务器IP分配如下:
- 管理节点:192.168.1.10
- 数据节点1:192.168.1.11
- 数据节点2:192.168.1.12
- SQL节点1:192.168.1.13
- SQL节点2:192.168.1.14(可选,可先部署一个)
所有服务器操作系统为CentOS 7.6,MySQL Cluster版本选择mysql-cluster-gpl-7.4.30(MySQL 5.7对应的NDB版本为7.4/7.5,我们以7.4为例)。
20.2.1 环境规划与准备工作
在开始前,确保所有服务器:
- 关闭防火墙或开放必要的端口(管理节点:1186,数据节点和SQL节点之间通信端口动态,通常全部开放)。
- 设置主机名并配置/etc/hosts,确保互相能通过主机名解析。
例如在每台机器上添加:
192.168.1.10 mgm
192.168.1.11 ndb1
192.168.1.12 ndb2
192.168.1.13 sql1
192.168.1.14 sql2
- 创建mysql用户和组,用于运行集群进程。
- 下载MySQL Cluster二进制包并解压到/usr/local/mysql。
20.2.2 MySQL Cluster软件安装
在所有节点上执行相同步骤:
# 创建mysql用户
groupadd mysql
useradd -g mysql -s /sbin/nologin mysql
# 解压软件包到/usr/local/mysql
tar -zxvf mysql-cluster-gpl-7.4.30-linux-glibc2.12-x86_64.tar.gz -C /usr/local/
cd /usr/local
ln -s mysql-cluster-gpl-7.4.30-linux-glibc2.12-x86_64 mysql
# 设置目录权限
chown -R mysql:mysql /usr/local/mysql
注意:二进制包包含了所有节点所需的可执行文件,因此所有节点都可以使用同一套软件。
20.2.3 管理节点配置步骤
管理节点只需要配置文件config.ini。创建目录/var/lib/mysql-cluster,并编辑config.ini:
mkdir -p /var/lib/mysql-cluster
vi /var/lib/mysql-cluster/config.ini
内容如下:
[ndbd default]
NoOfReplicas=2 # 每个片段副本数,通常为2
DataMemory=512M # 每个数据节点用于存储数据的内存
IndexMemory=128M # 用于索引的内存
LockPagesInMainMemory=0
MaxNoOfConcurrentOperations=100000
TimeBetweenWatchDogCheck=60000
[ndb_mgmd]
NodeId=1
HostName=192.168.1.10 # 管理节点IP
DataDir=/var/lib/mysql-cluster
PortNumber=1186
[ndbd]
NodeId=2
HostName=192.168.1.11
DataDir=/usr/local/mysql/data
[ndbd]
NodeId=3
HostName=192.168.1.12
DataDir=/usr/local/mysql/data
[mysqld]
NodeId=4
HostName=192.168.1.13
[mysqld]
NodeId=5
HostName=192.168.1.14
参数说明:
- NoOfReplicas=2:每个数据分片有两个副本,即数据冗余两份。
- DataMemory/IndexMemory:数据节点内存分配,根据实际物理内存调整。
- [ndb_mgmd]:管理节点定义,指定主机和端口。
- [ndbd]:数据节点定义,每个数据节点一个段,指定主机和数据目录。
- [mysqld]:SQL节点定义,只需指定主机即可。
注意:NodeId必须唯一,范围1-48(管理节点通常用1,数据节点2-…,SQL节点…)。
20.2.4 配置数据节点
数据节点不需要单独的配置文件,只需确保目录/usr/local/mysql/data存在且属主为mysql,并在启动时通过–ndb-connectstring指定管理节点地址。但为了方便,可以创建一个my.cnf文件,指定连接信息。
在数据节点(192.168.1.11和192.168.1.12)上创建/etc/my.cnf:
[mysqld]
ndbcluster
ndb-connectstring=192.168.1.10:1186
[MYSQL_CLUSTER]
ndb-connectstring=192.168.1.10:1186
同时,初始化数据目录(虽然NDB引擎的数据不存储在本地文件,但系统表空间仍需初始化):
cd /usr/local/mysql
./bin/mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
20.2.5 配置SQL节点
SQL节点需要配置my.cnf,启用NDB引擎,并指定连接管理节点。
在SQL节点(192.168.1.13)上创建/etc/my.cnf:
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/tmp/mysql.sock
port=3306
user=mysql
ndbcluster
ndb-connectstring=192.168.1.10:1186
character-set-server=utf8mb4
[mysql]
default-character-set=utf8mb4
[MYSQL_CLUSTER]
ndb-connectstring=192.168.1.10:1186
同样初始化数据目录:
cd /usr/local/mysql
./bin/mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
注意:这里使用–initialize-insecure生成一个无密码的root用户(仅用于测试,生产需设置密码)。
20.2.6 启动集群
启动顺序:先启动管理节点,再启动数据节点,最后启动SQL节点。
20.2.6.1 启动管理节点
在管理节点(192.168.1.10)上执行:
cd /usr/local/mysql
./bin/ndb_mgmd -f /var/lib/mysql-cluster/config.ini --initial --configdir=/var/lib/mysql-cluster/
–initial参数只在首次启动或修改配置文件时使用,会重建配置缓存。正常启动可省略。
查看管理节点是否正常运行:
ps aux | grep ndb_mgmd
20.2.6.2 启动数据节点
在两个数据节点上分别执行:
cd /usr/local/mysql
./bin/ndbd --initial
–initial参数会清除该节点上的数据文件,只在首次启动或重建时使用。后续启动无需加–initial。
20.2.6.3 启动SQL节点
在SQL节点上启动mysqld:
cd /usr/local/mysql
./bin/mysqld_safe --defaults-file=/etc/my.cnf &
20.2.7 集群状态验证
在任意节点上,使用ndb_mgm客户端连接管理节点,查看集群状态。
cd /usr/local/mysql
./bin/ndb_mgm
在ndb_mgm提示符下执行show:
ndb_mgm> show
Connected to Management Server at: 192.168.1.10:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=2 @192.168.1.11 (mysql-5.7.21 ndb-7.4.30, Nodegroup: 0, *)
id=3 @192.168.1.12 (mysql-5.7.21 ndb-7.4.30, Nodegroup: 0)
[ndb_mgmd(MGM)] 1 node(s)
id=1 @192.168.1.10 (mysql-5.7.21 ndb-7.4.30)
[mysqld(API)] 2 node(s)
id=4 @192.168.1.13 (mysql-5.7.21 ndb-7.4.30)
id=5 @192.168.1.14 (mysql-5.7.21 ndb-7.4.30)
看到所有节点状态为“已连接”且数据节点后有星号(表示主节点),说明集群启动成功。
登录SQL节点,测试NDB引擎是否可用:
mysql -u root
执行:
SHOW ENGINES;
应该看到ndbcluster引擎支持为YES。
创建测试表:
CREATE DATABASE test;
USE test;
CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(20)) ENGINE=NDB;
INSERT INTO t1 VALUES (1, 'Cluster Test');
SELECT * FROM t1;
如果成功,说明集群可以正常读写。
20.3 MySQL Cluster日常管理与监控
20.3.1 启动与关闭的正确流程
关闭集群时应遵循与启动相反的顺序:先关SQL节点,再关数据节点,最后关管理节点。
关闭SQL节点:在SQL节点上执行mysqladmin shutdown:
/usr/local/mysql/bin/mysqladmin -u root shutdown
关闭数据节点:在ndb_mgm中执行:
ndb_mgm> 2 STOP
2是数据节点的ID。或使用ndbd --stop命令。
关闭管理节点:在ndb_mgm中执行shutdown或直接kill进程。
20.3.2 使用ndb_mgm监控集群状态
ndb_mgm提供了丰富的命令:
show:显示节点状态。all status:查看所有节点状态。节点号 report memory:查看数据节点内存使用情况。节点号 report backup:查看备份状态。
例如,查看节点2的内存使用:
ndb_mgm> 2 REPORT MEMORY
Node 2: Data usage is 12%(24 32-bit words)
Node 2: Index usage is 5%(1024 32-bit words)
20.3.3 节点故障处理与恢复
当某个数据节点宕机,集群会标记其为“down”,但业务仍可继续,因为数据副本在其他节点上。恢复步骤:
- 修复故障节点(如重启服务器)。
- 启动该节点的ndbd进程,它会自动从其他节点同步数据(无需手动干预)。
- 在ndb_mgm中查看状态,应变为“starting”然后“started”。
如果数据节点永久损坏,需添加新节点替换,操作较复杂,涉及节点ID回收等,建议参考官方文档。
20.3.4 在线添加数据节点(扩容)
随着业务增长,需要增加数据节点以提升容量和性能。MySQL Cluster支持在线添加数据节点(NDB 7.4开始支持)。步骤如下:
- 在管理节点的config.ini中增加新的[ndbd]段。
- 重启管理节点(使用
ndb_mgmd --reload重新加载配置)。 - 在新服务器上启动ndbd(使用–initial),它会自动加入集群。
- 使用
ndb_mgm的create nodegroup命令将新节点加入节点组。 - 对需要重新分区的表执行
ALTER TABLE ... REORGANIZE PARTITION来重新分布数据。
注意:数据重新分布会影响性能,建议在低峰期执行。
20.3.5 集群日志分析与管理
集群日志包括管理节点日志和数据节点日志。管理节点日志位于启动时指定的目录(如/var/lib/mysql-cluster/ndb_cluster.log)。数据节点日志位于数据目录(如/usr/local/mysql/data/ndb_out.log)。
查看错误信息:例如节点连接失败,可在日志中查找“ERROR”或“WARNING”。常见错误:
- 通信超时:检查网络。
- 内存不足:调整DataMemory/IndexMemory。
可以通过ndb_mgm设置日志级别:
ndb_mgm> SET LOGLEVEL 8;
20.4 数据备份与恢复策略
20.4.1 联机备份(使用ndb_mgm START BACKUP)
MySQL Cluster支持在线热备,无需停止服务。在ndb_mgm中执行:
ndb_mgm> START BACKUP [备份ID] [SNAPSHOTEND]
例如:
ndb_mgm> START BACKUP 1
备份过程会记录当前数据的一致性快照,备份文件生成在数据节点的BACKUP目录下(通常在数据目录的BACKUP子目录)。备份ID用于标识。
查看备份进度:
ndb_mgm> ALL REPORT BACKUP
20.4.2 备份文件管理与恢复
备份文件包括元数据文件和控制文件。恢复时使用ndb_restore命令。步骤如下:
- 如果集群正在运行,可能需要关闭部分节点。
- 在每个数据节点上执行恢复命令,按顺序恢复备份数据。
例如,在数据节点2上恢复备份ID为1的数据:
/usr/local/mysql/bin/ndb_restore -c 192.168.1.10:1186 -n 2 -b 1 -r ./BACKUP/BACKUP-1/
其中 -n 指定节点ID,-b 指定备份ID,-r 指定备份目录。
注意:恢复必须在集群所有数据节点停止的状态下进行,且要确保备份来自相同架构的集群。
20.4.3 使用mysqldump逻辑备份
虽然NDB引擎的表也可以使用mysqldump备份,但mysqldump是逻辑备份,速度较慢,适合少量数据。用法与普通MySQL相同:
mysqldump -h sql1 -u root -p --all-databases > cluster_backup.sql
但mysqldump无法备份NDB引擎特有的表空间信息,恢复时只能重建表结构,数据通过INSERT导入。
20.4.4 恢复数据到集群
使用ndb_restore恢复物理备份后,集群数据即可恢复。若使用mysqldump恢复,则执行:
mysql -h sql1 -u root -p < cluster_backup.sql
注意:如果集群中有多个SQL节点,任意一个节点执行恢复即可,因为数据会同步到所有数据节点。
20.5 Windows环境下配置MySQL Cluster
虽然生产环境多用Linux,但开发测试可能需要在Windows下搭建Cluster。Windows版本的MySQL Cluster与Linux配置类似,但有一些差异。
20.5.1 Windows下的安装步骤
- 下载Windows版本的MySQL Cluster ZIP包(如mysql-cluster-gpl-7.4.30-win64.zip)。
- 解压到目标目录,如C:\mysql-cluster。
- 以管理员身份打开命令提示符,进入bin目录。
- 初始化管理节点、数据节点、SQL节点的配置文件。
20.5.2 配置差异与注意事项
- 路径使用反斜杠或正斜杠均可,但需注意转义。
- Windows下服务管理:可以使用
mysqld --install将SQL节点安装为Windows服务。 - 防火墙需开放相应端口。
- 启动命令类似,但需使用
ndb_mgmd.exe等可执行文件。
示例管理节点config.ini:
[ndbd default]
NoOfReplicas=2
DataMemory=256M
IndexMemory=64M
[ndb_mgmd]
NodeId=1
HostName=127.0.0.1
DataDir=C:/mysql-cluster/mgmd-data
[ndbd]
NodeId=2
HostName=127.0.0.1
DataDir=C:/mysql-cluster/ndb-data1
[ndbd]
NodeId=3
HostName=127.0.0.1
DataDir=C:/mysql-cluster/ndb-data2
[mysqld]
NodeId=4
HostName=127.0.0.1
在一台机器上模拟多节点时,需注意端口冲突,通常数据节点之间会自动协商。
20.5.3 测试集群运行
启动管理节点:
C:\mysql-cluster\bin> ndb_mgmd.exe -f C:\mysql-cluster\config.ini --initial
启动数据节点(开两个命令行窗口分别执行):
C:\mysql-cluster\bin> ndbd.exe --initial --connect-string="host=127.0.0.1:1186"
启动SQL节点(正常mysqld启动):
C:\mysql-cluster\bin> mysqld.exe --console --ndbcluster --ndb-connectstring=127.0.0.1:1186
连接测试:
C:\mysql-cluster\bin> mysql.exe -u root
20.6 综合案例:构建高可用电信计费系统
我们模拟一个电信计费系统,要求:
- 实时记录用户通话详单(CDR)。
- 支持在线充值、余额查询。
- 日处理话单量1亿条,峰值TPS 5万。
- 系统可用性99.999%,即年故障时间小于5分钟。
20.6.1 需求分析与集群设计
- 数据分片:以用户号码(手机号)为分区键,将用户数据和话单数据自动分布到多个数据节点。
- 副本设置:NoOfReplicas=2,保证任意一个数据节点故障,数据不丢失。
- 硬件规划:初期4个数据节点,每个节点配置256GB内存(DataMemory+IndexMemory),满足半年内数据内存化存储。后续可在线扩容。
- SQL节点:部署2个SQL节点做负载均衡,应用程序通过LVS或F5连接。
20.6.2 分片策略与表设计
创建核心表:用户表(user)、话单表(cdr)。
用户表:
CREATE TABLE user (
msisdn VARCHAR(20) NOT NULL PRIMARY KEY, -- 手机号
balance DECIMAL(10,2) NOT NULL DEFAULT 0.00,
status TINYINT NOT NULL DEFAULT 1,
last_update TIMESTAMP
) ENGINE=NDB COMMENT='用户表';
话单表:
CREATE TABLE cdr (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
msisdn VARCHAR(20) NOT NULL,
call_time DATETIME NOT NULL,
duration INT UNSIGNED NOT NULL,
fee DECIMAL(10,2) NOT NULL,
PRIMARY KEY (id, msisdn) -- 使用复合主键,以msisdn为分区键
) ENGINE=NDB
PARTITION BY KEY (msisdn)
COMMENT='话单表';
注意:NDB表必须显式指定分区键,通常用主键或唯一键的第一部分。这里cdr表使用(msisdn, id)复合主键,分区键为msisdn,确保同一个用户的话单落在同一数据节点,便于事务和查询。
20.6.3 应用连接配置
应用通过SQL节点连接,可以使用连接池。在SQL节点上创建业务用户并授权:
CREATE USER 'billing'@'%' IDENTIFIED BY 'Billing@2024';
GRANT SELECT, INSERT, UPDATE ON billing.* TO 'billing'@'%';
应用JDBC连接串示例:
jdbc:mysql://sql1:3306,billing?user=billing&password=Billing@2024&useUnicode=true&characterEncoding=utf8
20.6.4 故障模拟与切换演练
模拟数据节点2故障:在数据节点2上执行 pkill ndbd。观察ndb_mgm状态:
ndb_mgm> show
...
[ndbd] Node 2: down
...
此时,用户查询、插入应仍正常,因为数据节点3上存有副本。使用ndb_mgm查看节点3角色是否变为“主”。
恢复节点2:启动ndbd,它会自动从节点3同步数据,状态变为starting→started。
模拟SQL节点故障:应用自动重连到另一个SQL节点(通过LVS或配置多个地址)。需确保应用连接池支持故障转移。
20.7 专家解惑:常见问题与优化建议
20.7.1 节点通信问题排查
- 症状:节点连接不上,ndb_mgm显示“not connected”。
- 排查:检查网络ping,防火墙规则,管理节点端口(1186)是否监听。查看节点日志是否有“Connection refused”错误。
- 解决:确保所有节点可以互相解析主机名,关闭防火墙或开放端口。
20.7.2 内存配置与性能调优
- DataMemory不足:如果数据量超过配置,插入会失败。需监控内存使用,及时扩容或调整NoOfReplicas。
- IndexMemory不足:导致索引创建失败。
- 调优参数:MaxNoOfConcurrentOperations、MaxNoOfLocalOperations等,参考官方文档。
经验:将DataMemory设置为物理内存的70%-80%,IndexMemory设置为DataMemory的20%-30%。
20.7.3 网络延迟影响
MySQL Cluster节点之间频繁通信,对网络延迟敏感。建议使用万兆网络,同一数据中心部署。跨数据中心部署会导致性能急剧下降。
20.7.4 数据分布不均问题
如果分区键选择不当,可能导致某些节点数据量远大于其他节点。应选择访问频率均匀的列作为分区键,如用户ID。如果必须用手机号,注意手机号前几位有地域属性,可能导致数据倾斜,可采用hash处理。
20.7.5 事务限制
NDB引擎不支持跨节点的事务(即一个事务涉及多个数据节点上的数据),因此设计时应尽量将相关数据放在同一分区。例如,用户表和其话单表通过相同分区键关联,确保同一用户的数据在同一节点,支持事务。
20.7.6 备份恢复失败处理
如果ndb_restore报错“Failed to connect”,检查管理节点地址是否正确。如果恢复过程中出现数据不一致,可尝试重新恢复。
20.8 经典习题与实战思考
- 简述MySQL Cluster中管理节点、数据节点、SQL节点的作用。
- 如何计算一个4节点数据集群的总可用内存(假设每个节点DataMemory=512M,NoOfReplicas=2)?
- 写出在Linux环境下启动MySQL Cluster的正确顺序。
- 如何在线添加一个新的数据节点?请写出简要步骤。
- 使用ndb_mgm进行联机备份的命令是什么?备份文件存放在哪里?
- 假设某个数据节点永久损坏,需要更换为新服务器,请设计恢复流程。
- 在电信计费案例中,为什么cdr表要使用复合主键(msisdn, id)?如果只用id做主键会有什么问题?
- NDB引擎和InnoDB的主要区别有哪些?
- 如何监控MySQL Cluster的内存使用情况?
- 如果集群出现网络分区,会发生什么?如何预防?
本章从理论到实践,全面讲解了MySQL Cluster的架构、部署、管理和维护,并结合电信计费案例展示了其在高可用、高并发场景下的应用。掌握MySQL Cluster,你将有能力构建出电信级、金融级的大规模分布式数据库系统,为企业关键业务提供坚实的数据底座。
更多推荐
所有评论(0)