MySQL InnoDB Cluster搭建高可用数据库集群(centos7.x)

时间:2022-09-19 20:12:15

MySQL官方在4月终于推出了一套完整的、高可用的Mysql解决方案--MySQL InnoDB Cluster。这绝对是程序员的福音。以往做mysql主从高可用非常繁琐,很多坑。现在利用官方的解决方案--MySQL InnoDB Cluster可以比较方便的搭建mysql高可用集群,虽然也挺多坑的。


至于--MySQL InnoDB Cluster有什么优点缺点,这里不比较了,可以到官网直接看就好。

最近刚好项目需要搭建数据库高可用,于是便尝试使用官方推荐的方案--MySQL InnoDB Cluster。

因为这个是新推出的,网上这方面的资料比较少,官方的文档也介绍太简单,我在搭建过程中也遇到很多问题。

最后还是成功搭建,这里把搭建过程给大家分享一下,希望对需要的朋友有所帮助。


开始:

1、准备需要的环境

我使用的系统版本:centos7.x

首先下载搭建需要的软件:

mysql 下载地址:

https://dev.mysql.com/downloads/mysql/

mysql-shell 下载地址:

https://dev.mysql.com/downloads/shell/

mysql-router 下载地址:

https://dev.mysql.com/downloads/router/

都选择 Linux Generic 版本即可

准备3台服务器,node01、node02、node03 

node01作为 cluster 节点,负责创建 cluster,并作为 cluster 的路由


2、环境配置

在各台服务器中配置好 hosts,这一步很重要,否则可能会出现无法同步的情况,因为数据库需要根据member_host同步,如果不配置,默认就是localhost,这样时无法通信的。

# vim /etc/hosts

如:

172.30.12.20 node03 
172.30.12.17 node02 
172.30.12.14 node01 

让hosts文件生效

# source /etc/hosts

然后重启服务器:

# reboot -f 

通过命令 hostnamectl  查看瞬态主机名称是否是设置的名称

 Static hostname: localhost.localdomain
Transient hostname: node01  #这个就是瞬态主机名称,mysql会根据这个来设置host
         Icon name: computer-desktop
           Chassis: desktop
        Machine ID: 9ac67df3c56f4ff18f0a7855490589bc
           Boot ID: f6f4356539884b8ba2ee79774b918359
  Operating System: CentOS Linux 7 (Core)
       CPE OS Name: cpe:/o:centos:centos:7
            Kernel: Linux 3.10.0-514.el7.x86_64
      Architecture: x86-64

如果你不想重启服务器,也可以通过下面的命令动态设置:

hostnamectl --transient set-hostname node01

(1)安装基础软件

node 01、02、03 上安装好 mysql  mysql-shell

node01 上安装 mysql-router

mysql怎么安装这里不介绍了,请移步另外一篇博文:http://blog.csdn.net/kokjuis/article/details/78215020


2. shell

# 直接解压即可
tar zxf mysql-shell-1.0.9-linux-glibc2.12-x86-64bit.tar.gz mysql-shell

3. router

# 直接解压即可
tar zxf mysql-router-2.1.3-linux-glibc2.12-x86-64bit.tar.gz mysql-router

在node01的mysql配置文件加入高可用和集群配置(根据自己的情况设置目录):

[mysql]  
# 设置mysql客户端默认字符集  
default-character-set=utf8   
socket=/usr/mysql/mysql/lib/mysql.sock  
  
[mysqld]  
#skip-name-resolve  
#设置3306端口  
port = 3306   
socket=/usr/mysql/mysql/lib/mysql.sock  
# 设置mysql的安装目录  
basedir=/usr/mysql/mysql 
# 设置mysql数据库的数据的存放目录  
datadir=/usr/mysql/mysql/data
# 允许最大连接数  
max_connections=200  
# 服务端使用的字符集默认为8比特编码的latin1字符集  
character-set-server=utf8  
# 创建新表时将使用的默认存储引擎  
default-storage-engine=INNODB  

max_allowed_packet=16M  

#高可用
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

transaction_write_set_extraction=XXHASH64

#主从复制配置
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
#注意:这里的地址不能用 node01:24901 这种写法,要用IP,否则无法通信
loose-group_replication_local_address= "172.30.12.14:24901"
loose-group_replication_group_seeds= "172.30.12.14:24901,172.30.12.17:24901,172.30.12.20:24901"
loose-group_replication_single_primary_mode=TRUE

#loose-group_replication_bootstrap_group= off
#loose-group_replication_enforce_update_everywhere_checks= FALSE
#loose-group_replication_start_on_boot=off

disabled_storage_engines = MyISAM,BLACKHOLE,FEDERATED,CSV,ARCHIVE
report_port = 3306

然后重启mysql。


进到 mysql-shell 的安装目录,登录 shell ,执行配置

bin/mysqlsh

连接到本机MySQL,执行配置命令

# 连接,需要输入密码(123456)
mysql-js> shell.connect('root@localhost:3306');

# 执行配置命令,也需要密码
mysql-js> dba.configureLocalInstance();
Please provide the password for 'root@localhost:3306':

Detecting the configuration file...
Default file not found at the standard locations.
Please specify the path to the MySQL configuration file: /etc/my.cnf
MySQL user 'root' cannot be verified to have access to other hosts in the network.
Detecting the configuration file...
Found configuration file at standard location: /etc/my.cnf
Do you want to modify this file? [Y|n]:  [Y|n]: y
Validating instance...

The instance 'localhost:3306' is valid for Cluster usage
You can now use it in an InnoDB Cluster.

{
    "status": "ok"
}

status  ok 说明配置没问题了,可以用来创建cluster

  • 通过 mysql-shell 连接 node01 创建 cluster

  • 登录 shell,连接 node01,创建 cluster

bin/mysqlsh 

# 连接01
mysql-js> shell.connect('root@node01:3306');

# 创建一个 cluster,命名为 'myCluster'
mysql-js> var cluster = dba.createCluster('myCluster');

# 创建成功后,查看cluster状态
mysql-js> cluster.status();

{
    "clusterName": "myCluster", 
    "defaultReplicaSet": {
        "name": "default", 
        "primary": "node01:3306", 
        "status": "OK_NO_TOLERANCE", 
        "statusText": "Cluster is NOT tolerant to any failures. 1 member is not active", 
        "topology": {
            "node01:3306": {
                "address": "node01:3306", 
                "mode": "R/W", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }        
        }
    }
}

(3)添加实例节点 node02

  • 配置 node02 的 mysql 并启动

编辑配置文件 my.cnf,内容与 node01 上的一样,只有2行不同

server_id=2
改成本机的IP:loose-group_replication_local_address= "172.30.12.17:24901"
  • 通过本机 mysql-shell 对 mysql 进行配置

登录 shell ,执行配置

bin/mysqlsh 

mysql-js> shell.connect('root@localhost:3306');
mysql-js> dba.configureLocalInstance();
  • 停掉 mysql,修改 my.cnf,添加配置项

# 在末尾添加
group_replication_allow_local_disjoint_gtids_join=ON

重启MySQL

  • 通过 node01 的 mysql-shell 添加 node02 到 cluster

# 添加实例
cluster.addInstance('root@node02:3306');

# 创建成功后,查看cluster状态
mysql-js> cluster.status();

(4)添加实例节点 node03

过程与 node02 完全相同,只需要注意 my.cnf 中的 'server_id' 值改为 3,

也是改成node03的ip:loose-group_replication_local_address= "172.30.12.20:24901"

重启MySQL

  • 通过 node01 的 mysql-shell 添加 node03 到 cluster

# 添加实例
cluster.addInstance('root@node03:3306');

# 创建成功后,查看cluster状态
mysql-js> cluster.status();

(5)安装 router

进入 node01 中 mysql-router 安装目录执行命令

./bin/mysqlrouter --bootstrap root@node01:3306 -d myrouter --user=root 

这里会在mysql-router 目录生成router配置文件,我们把配置文件修改一下:

# File automatically generated during MySQL Router bootstrap
[DEFAULT]
user=root
logging_folder=/usr/mysql/mysql-router/myrouter/log
runtime_folder=/usr/mysql/mysql-router/myrouter/run
data_folder=/usr/mysql/mysql-router/myrouter/data
keyring_path=/usr/mysql/mysql-router/myrouter/data/keyring
master_key_path=/usr/mysql/mysql-router/myrouter/mysqlrouter.key

[logger]
level = INFO

[routing:read_write]
#指定mysql router绑定的服务器
bind_address = 172.30.12.14
#指定绑定的端口
bind_port = 7001
#读写模式(read-write, read_only)
mode = read-write
#指定mysql server 列表 (ip:port 格式,使用逗号分隔)
destinations = 172.30.12.14:3306
#最大连接数
max_connections = 1000
#最大错误连接数
#max_connect_errors = 100
#连接超时时间
connect_timeout = 9

[routing:read_only]
bind_address = 172.30.12.14
bind_port = 7002
mode = read-only
destinations = 172.30.12.17:3306,172.30.12.20:3306
max_connections = 1000
#max_connect_errors = 100
connect_timeout = 9

然后启动

mysqlrouter --config /usr/mysql/mysql-router/myrouter/mysqlrouter.conf &

然后把mysql连接端口改成7001(配置文件中配置的读写端口)即可。


可能遇到的问题:

一般可以这样解决,停止集群:

在数据库上执行:

STOP GROUP_REPLICATION;

RESET MASTER;
RESET SLAVE;

登录 shell ,执行

bin/mysqlsh 

mysql-js> shell.connect('root@localhost:3306');
mysql-js> dba.rebootClusterFromCompleteOutage('myCluster');#上面配置的名称
一般就会恢复,然后重新

cluster.addInstance('root@node02:3306');
cluster.addInstance('root@node03:3306');


在数据库中查看:

SELECT * FROM performance_schema.replication_group_members;

MySQL InnoDB Cluster搭建高可用数据库集群(centos7.x)

这样就表示集群成功了。


如果你的主从不同步,一般可以这样解决:

从master中导出数据库,到slave中导入数据。

在master通过命令:SHOW MASTER STATUS; 

记下 file 和 position


在slave中执行:

CHANGE MASTER TO MASTER_HOST = '172.30.12.14',MASTER_PORT = 3306,MASTER_USER = 'root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='master-bin.000001',MASTER_LOG_POS=1172;

然后从新enjoin一下即可。


添加一个新的从机,可以有两种方式:从 master 机器复制; 另一种是直接从 slave 复制.


复制主库要步骤:
====================
1.将内存中的数据同步到表中.
2.锁定表,不让出现脏数据
3.备份
4.解锁
5.在另一台机器上同步数据,并且设置 master_log_file 和 master-log_pos

命令:
a.同步数据,并锁表: mysql>  flush tables with read lock;
b.记住当前 binlog 的偏移值,后面设置 slave 上的值.  show master status; 记下 file 和 position
命令: [root@li387-161 ~]  mysqldump --all-databases --host=master-1 > backup.sql
d.解锁 mysql>  unlock tables;
e.同步从机.将 backup.sql 复制到从机上.[root@li387-161 ~]  mysql --host=slave-1 < backup.sql
设置从机: 
mysql>change master to master_host = '192.168.3.119',master_port = 3306,master_user = 'repl_user',master_password='root', master_log_file='master-bin.000005', master_log_pos=194244;
这里的 master_log_file 和 master_log_pos 就是前面第 2 步中记下来的两个值.
开启从机
start slave;


复制从库要步骤:
====================
可以看到,从主库复制会有段时间锁表,这段时间会影响主库的使用。如果我们能直接从从库进行复制,就不会对主库产生影响了。但是,从从库复制要保证的是复制过程中从库上的数据不会发生变化,所以要先停掉从库。
1.停止从库: mysql> stop slave;
2.看当前从库的状态。和前面的看主库状态一样。但现在是从从库复制,所以查看从库状态:mysql> show slave status;
记下 Relay_Master_Log_file 和 Exec_Master_Log_Pos, 用处和前面一样.
3.备份从库数据.用 mysqldump
4.在新的从库上还原数据
5.设置新从库的 slave 参数.change master to master_host = '192.168.3.119',master_port = 3306,master_user = 'repl_user',master_password='root',master_log_file='master-bin.000005',master_log_pos=194244;
可以看到,虽然新从库是从从库复制的数据,但实际上 binlog 的 master 还是指向的主库。
另外,这里将 master_log_file 和 master_log_pos 设置成第 2 步中的 Relay_Master_Log_file 和 Exec_Master_Log_Pos
start slave;