MySQL集群搭建

不知道mysql5.7从什么时候加入了innodb cluster,于是mysql就有了2种集群路线,一个是使用NDB的mysql cluster,一个是用innodb 的mysql innodb cluster。

MySQL Cluster

NDB意思是Network DataBase,是mysql cluster(非mysql)专用引擎,离开集群无法工作。NDB是一个shared nothing的内存数据库,不过官网说他会存储部分数据在硬盘上(猜测是blob类型,可能还有text类型)。NDB数据与mysqld进程分离,存储在专门的数据节点中,名为ndbd或ndbmtd(ndbd的多线程版本)的进程。NDB集群还自带数据分片功能,他通过数据交叉冗余提供高可用性。

详见NDB集群概述NDB集群核心概念NDB集群节点、副本、分区

NDB大致使用限制如下

1、NDB的创建索引的字段最大3072byte
2、NDB不能在text上建索引
3、NDB唯一索引字段不能为空
4、NDB最大索引条数配置项 MaxNoOfOrderedIndexes,每表最大16个
5、NDB最大数据节点为48个,整个集群(管理节点、sql节点、配置节点)最大255个
6、NDB只支持READ COMMITTED事务级别(一般够用了)
7、NDB集群锁表操作(alter table)存在不能全锁的问题

详见NDB使用限制

mysql官网还提供了一个innodb与ndb集群的性能对比表格。大致在集群同步和故障恢复有些差异,大致如下:

Feature InnoDB (MySQL 5.7) NDB 7.5/7.6
Storage Limits 64TB 128TB (as of NDB 7.5.2)
Transactions All standard types READ COMMITTED
MVCC Yes No
Data Compression Yes No (NDB checkpoint and backup files can be compressed)
Large Row Support (> 14K) Supported for VARBINARY, VARCHAR, BLOB, and TEXT columns Supported for BLOB and TEXT columns only (Using these types to store very large amounts of data can lower NDB performance)
Replication Support Asynchronous and semisynchronous replication using MySQL Replication; MySQL Group Replication Automatic synchronous replication within an NDB Cluster; asynchronous replication between NDB Clusters, using MySQL Replication

(Semisynchronous replication is not supported)

Time for Node Failure Recovery 30 seconds or longer Typically < 1 second
Real-Time Performance No Yes
In-Memory Tables No Yes (Some data can optionally be stored on disk; both in-memory and disk data storage are durable)
Concurrent and Parallel Writes Yes Up to 48 writers, optimized for concurrent writes
Hash Indexes No Yes

MySQL InnoDB Cluster

innodb集群则更普通一些,mysql5.7自带了group repliction插件,再配合mysql-shell(集群控制)、mysql-router(高可用代理,故障恢复)一起提供集群功能。

在windows上安装可以直接在装server的时候选择sandbox(似乎5.7.21的安装包开始提供sandbox功能)安装配置好的测试样本体验mysql集群。sandbox的安装路径为

C:\Users\Administrator\MySQL\mysql-sandboxes

若需要在单机上进行多实例模拟集群,则可以这样安装服务。

1、按配置同步副本组增加my.ini中配置

# Replication Framework
server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
log_bin=binlog
binlog_format=ROW

# Group Replication Settings
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "127.0.0.1:24901"
loose-group_replication_group_seeds= "127.0.0.1:24901,127.0.0.1:24902,127.0.0.1:24903"
loose-group_replication_bootstrap_group=off

2、创建数据库、安装服务

mysqld --initialize-insecure --basedir="c:\Program Files\MySQL\MySQL Server 5.7" --datadir="d:\ProgramData\MySQL\MyS
QL Server 5.7\data\1"
mysqld --initialize-insecure --basedir="c:\Program Files\MySQL\MySQL Server 5.7" --datadir="d:\ProgramData\MySQL\MyS
QL Server 5.7\data\2"
mysqld --initialize-insecure --basedir="c:\Program Files\MySQL\MySQL Server 5.7" --datadir="d:\ProgramData\MySQL\MyS
QL Server 5.7\data\3"
mysqld --install MySQL57_1 --defaults-file="d:\ProgramData\MySQL\MySQL Server 5.7\config\my_1.ini"
mysqld --install MySQL57_2 --defaults-file="d:\ProgramData\MySQL\MySQL Server 5.7\config\my_2.ini"
mysqld --install MySQL57_3 --defaults-file="d:\ProgramData\MySQL\MySQL Server 5.7\config\my_3.ini"

3、开启副本组同步添加从库副本组同步

-- 创建同步用户
SET SQL_LOG_BIN=0; --关闭同步(创建用户操作可能会导致同步出错)
CREATE USER rpl_user@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;
CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';

-- 安装插件
INSTALL PLUGIN group_replication SONAME 'group_replication.dll';

-- 在主库上执行
SET GLOBAL group_replication_bootstrap_group=ON; --在副本同步开始前创建新的副本组
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;

-- 在从库上执行
START GROUP_REPLICATION;

4、使用mysql shell 建立、配置集群

--给集群管理账户(root)加集群元信息表权限
GRANT ALL PRIVILEGES ON mysql_innodb_cluster_metadata.* TO cluster_admin@'%' WITH GRANT OPTION;
GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO cluster_admin@'%' WITH GRANT OPTION;
GRANT SELECT ON *.* TO cluster_admin@'%' WITH GRANT OPTION;
//mysql shell 下配置集群(会提示localhost/172.0.0.1只能用于sandbox测试集群,可以配到其他ip上)
//连接主库
shell.connect('root@172.31.35.109:3316')
//查看是否可以建立集群,根据提示更改配置
dba.configureLocalInstance('root@172.31.35.109:3316')

//创建集群
var cluster = dba.createCluster('TestCluster')
//添加从库
cluster.addInstance('root@172.31.35.109:3317')

//获取集群实例
var cluster = dba.getCluster()
var cluster = dba.getCluster('TestCluster')
//查看集群状态
cluster.status()

//mysql shell具体参考帮助在mysql官网文档上并不清楚
//可以参考github上源代码 https://github.com/mysql/mysql-shell/tree/1.0

5、配置mysql router

windows上直接在mysql installer里点击 Reconfiguration进行配置就可以了,会生成一个windows服务。

6、修改配置

将配置文件中group_replication_start_on_boot=off
改为group_replication_start_on_boot=on
这样就能在数据库重启后自动加入同步组(集群)

 

mysql innodb cluster大致限制如下

1、表锁、命名锁等特殊锁无法使用
2、基本只支持READ COMMITTED事务级别
3、并发ddl和dml的冲突
4、外键冲突
5、大型事务可能导致同步失败(超时)
6、多主模式下可能产生脑裂问题。一台主服务在失败恢复后可能竞争主服务地位,可能造成所有写入等待。

其实很多跟ndb集群差不多。脑裂问题可能比较麻烦,可能mysql官方没用raft等选举算法解决主库选举问题。

一些问题的解决方案

1、mysql部分同步失败

可能存在部分语句无法同步或者无法执行(比如说创建用户),导致集群数据库状态为error或者missing。

如果是部分sql无法同步,比如说从库数据比主库更新,可以参考这个

--现象可见于mysql错误日志
--2018-01-19T06:54:43.700510Z 0 [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: f072afc8-6b82-4c16-aed8-d44c94758dea:1-6:1000003-1000006 > Group transactions: 03b5beed-fc36-11e7-a9b9-00ffa83c6c25:1-21,
--2d25a444-fce0-11e7-b9ed-00ffa83c6c25:1-15,
--f072afc8-6b82-4c16-aed8-d44c94758dea:1-7'

--各库查看同步过的事务
SELECT @@global.gtid_executed;

--找到没同步过的事务在没同步的库里执行
SET GTID_NEXT='f072afc8-6b82-4c16-aed8-d44c94758dea:1';
BEGIN;
COMMIT;
--...
SET GTID_NEXT='f072afc8-6b82-4c16-aed8-d44c94758dea:7';
--重置游标?
SET GTID_NEXT='AUTOMATIC';

--各库重启同步
START GROUP_REPLICATION;

如果是sql无法执行。还有第二种方案

--在同步失败的数据库里重置
RESET MASTER;
-启动同步
START GROUP_REPLICATION;

第三种方案方案

//mysql shell 重新检查
var cluster = dba.getCluster()
cluster.rescan()
//按提示修复/忽略sql

2、集群恢复

dba.rebootClusterFromCompleteOutage()

3、脑裂问题

cluster.forceQuorumUsingPartitionOf('root@172.31.35.109:3316')

其余参考

mysql故障情景

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注