数据库在任何业务中都是最重要的环节之一,这就对数据库架构提出的较高的要求。单点数据库永远不应该出现在生产环境,我们已经目睹过太多由于单点、备份缺失造成的损失,所以,搭建高可用 MySQL 集群是非常有必要的。

搭建集群有以下几点好处:

  1. 高可用性,在主节失效时自动切换,不需要技术人员紧急处理
  2. 高吞吐,可以多个节点同时提供读取数据服务,降低主节点负载,实现高吞吐
  3. 可扩展性强,支持在线扩容
  4. 无影响备份,在备节点进行备份操作不会对业务产生影响

要说缺点,有以下几点:

  1. 架构复杂,在部署、管理方面对技术人员有要求
  2. 备节点拉取主节点日志时会对主节点服务器性能有一定影响
  3. 如果配置了半同步复制,会对事务提交有一点影响

总的说,集群是一定要搭建的,谁敢把自己的数据跑在一个随时会有风险的数据库上呢。接下来我会以几篇文章介绍怎么从简单地主备模式到高可用架构。本节主要介绍如何搭建 MySQL 主备,注重操作,不会有太多理论讲解。

1 环境准备

1.1 启动数据库

在两台机器分别启动 MySQL 实例, MySQL 搭建方式可以参考 MySQL 安装(二进制版)

IP 系统 端口 MySQL版本 节点
192.168.41.83 Centos6.8 3306 5.7.20 Master
192.168.41.72 Centos6.8 3306 5.7.20 Salve

关键配置:

Master:

[client]
port = 3306
default-character-set=utf8mb4
socket = /data/mysql_db/mysql_seg_3306/mysql.sock [mysqld]
datadir = /data/mysql_db/mysql_seg_3306
basedir = /usr/local/mysql57
tmpdir = /tmp
socket = /data/mysql_db/mysql_seg_3306/mysql.sock
pid-file = /data/mysql_db/mysql_seg_3306/mysql.pid
skip-external-locking = 1
skip-name-resolve = 1
port = 3306
server_id = 833306 default-storage-engine = InnoDB
character-set-server = utf8mb4
default_password_lifetime=0 #### log ####
log_timestamps=system
log_bin = /data/mysql_log/mysql_seg_3306/mysql-bin
log_bin_index = /data/mysql_log/mysql_seg_3306/mysql-bin.index
binlog_format = row
relay_log_recovery=ON
relay_log=/data/mysql_log/mysql_seg_3306/mysql-relay-bin
relay_log_index=/data/mysql_log/mysql_seg_3306/mysql-relay-bin.index
log_error = /data/mysql_log/mysql_seg_3306/mysql-error.log #### replication ####
replicate_wild_ignore_table = information_schema.%,performance_schema.%,sys.% #### semi sync replication settings #####
plugin_dir=/usr/local/mysql57/lib/plugin
plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 5000

Salve

[client]
port = 3306
default-character-set=utf8mb4
socket = /data/mysql_db/mysql_seg_3306/mysql.sock [mysqld]
datadir = /data/mysql_db/mysql_seg_3306
basedir = /usr/local/mysql57
tmpdir = /tmp
socket = /data/mysql_db/mysql_seg_3306/mysql.sock
pid-file = /data/mysql_db/mysql_seg_3306/mysql.pid
skip-external-locking = 1
skip-name-resolve = 1
port = 3306
server_id = 723306
read_only=1 default-storage-engine = InnoDB
character-set-server = utf8mb4
default_password_lifetime=0 #### log ####
log_timestamps=system
log_bin = /data/mysql_log/mysql_seg_3306/mysql-bin
log_bin_index = /data/mysql_log/mysql_seg_3306/mysql-bin.index
binlog_format = row
relay_log_recovery=ON
relay_log=/data/mysql_log/mysql_seg_3306/mysql-relay-bin
relay_log_index=/data/mysql_log/mysql_seg_3306/mysql-relay-bin.index
log_error = /data/mysql_log/mysql_seg_3306/mysql-error.log #### replication ####
replicate_wild_ignore_table = information_schema.%,performance_schema.%,sys.% #### semi sync replication settings #####
plugin_dir=/usr/local/mysql57/lib/plugin
plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 5000

配置解析

  • datadir, basedir, tmpdir 分别为数据文件位置、数据库程序安装位置、临时文件位置
  • server_id 实例id,注意,同一集群机器的 server_id 不能相同
  • read_only 是否只读, 一般在备库设置
  • log_bin, log_bin_index 二进制日志位置、二进制日志索引文件位置
  • binlog_format 二进制日志格式,row 表示记录每条数据变化情况、statement 表示记录相关 sql 语句、mixed 表示两种混用,在搭建集群的时候建议使用 row 格式,如果是用 sql 语句来同步数据很容易出现数据不一致的情况
  • relay_log_recovery slave 宕机后,假如中继日志损坏,则重新拉取日志,为了保证中继日志完整性,建议开启
  • relay_log, relay_log_index 中继日志以及中继日志索引文件位置
  • log_error 错误日志位置
  • replicate_wild_ignore_table 同步时需要忽略的表,这里我们忽略了系统统计表,如果出现奇怪的同步失败情况,可以尝试开启
  • plugin_dir 插件位置
  • plugin_load 启动时需要加载的插件
  • loose_rpl_semi_sync_master_enabled 是否开启无损半同步复制-主库(建议主备都开启,方便主备切换)
  • loose_rpl_semi_sync_slave_enabled 是否开启无损半同步复制-备库(建议主备都开启,方便主备切换)

1.2 插入数据

我们假设 Master 是正在使用的数据库,现在要在线搭建备库,我们往 Master 节点插入一些测试数据

[mysql@mysql-test-83 ~]$ mydb-test_seg
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 29
Server version: 5.7.21-log MySQL Community Server (GPL) Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. db83-3306>>show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec) db83-3306>>create database mytest;
Query OK, 1 row affected (0.00 sec) db83-3306>>use mytest;
Database changed
db83-3306>>create table test1(
-> id int not null primary key auto_increment,
-> name varchar(16) not null default '',
-> age int not null default 0
-> ) engine = InnoDb charset = utf8;
Query OK, 0 rows affected (0.01 sec)
db83-3306>>insert into test1 values (0, 'a', 16), (0, 'b', 17), (0, 'c', 18), (0, 'd', 19);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0 db83-3306>>select * from test1;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | a | 16 |
| 2 | b | 17 |
| 3 | c | 18 |
| 4 | d | 19 |
+----+------+-----+
4 rows in set (0.00 sec)

2 在线搭建主从

现在我们的环境如下

  • 192.168.41.83:3306 Master 节点,正在使用
  • 192.168.41.72:3306 新搭建数据库,要在上面做 192.168.41.83 的备库

2.1 创建同步用户

我们创建一个用户名为 repl 的用户,授予 REPLICATION SLAVE 权限专门用来同步

db83-3306>>CREATE USER 'repl'@'%' IDENTIFIED BY 'repl';
Query OK, 0 rows affected (5.01 sec) db83-3306>>GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
Query OK, 0 rows affected (0.00 sec) db83-3306>>flush privileges;
Query OK, 0 rows affected (0.00 sec)

2.2 备份数据

常用的备份数据的方式有 innobackupexmysqldump,这里数据量少,我们用 mysqldump 进行全备

[mysql@mysql-test-83 ~]$ /usr/local/mysql57/bin/mysqldump -S /data/mysql_db/mysql_seg_3306/mysql.sock -F --opt -R --single-transaction --master-data=2 --default-character-set=utf8 -A > mysql_backup_full.sql

参数解析:

  • -S 选择 socket 文件,本机连接数据库可以用这种方法,也可以指定 ip、端口进行连接
  • -F 开始导出之前刷新日志
  • --opt 如果有这个参数表示同时激活了 mysqldump 命令的 quick,add-drop-table,add-locks,extended-insert,lock-tables 参数
    • --quick 代表忽略缓冲输出,mysqldump 命令直接将数据导出到指定的SQL文件
    • --add-drop-table 就是在每个 CREATE TABEL 命令之前增加 DROP-TABLE IF EXISTS 语句,防止数据表重名
    • --add-locks 在INSERT数据之前和之后锁定和解锁对应的数据表
    • --extended-insert 表示可以多行插入
  • -R 导出存储过程以及自定义函数, 如果有用到存储过程, 需要加这个参数
  • --single-transaction (innodb)设置事务的隔离级别为可重复读,即 REPEATABLE READ,这样能保证在一个事务中所有相同的查询读取到同样的数据, 如果全部表都为 InnoDB 就带上这个参数,保证数据一致性,备份时不会锁表。如果有 MyISAM 的表,需要锁表备份才能保证数据的一致性
  • --lock-all-tables 备份过程加读锁, single-transaction 选项和 lock-all-tables 选项是二选一的
  • --master-data=2 记录当前二进制日志位置, master_data取1和取2的区别,只是后者把 change master ... 命令注释起来了
  • --default-character-set 选择编码, 这个选项非常重要, 编码选不对或者没有设置很容易造成乱码
  • -A 代表备份所有的库

数据备份完毕后,把数据文件直接传输到 Slave 机器上

[mysql@mysql-test-83 ~]$ ll
total 772
-rw-rw-r-- 1 mysql mysql 786921 Nov 17 10:38 mysql_backup_full.sql
[mysql@mysql-test-83 ~]$ rsync -avzP mysql_backup_full.sql 192.168.41.72:/home/mysql/

2.3 数据恢复

在 Slave 机器上直接执行 sql 文件导入数据

[mysql@mysql-test-72 ~]$ ll mysql_backup_full.sql
-rw-rw-r-- 1 mysql mysql 786921 Nov 17 10:38 mysql_backup_full.sql
[mysql@mysql-test-72 ~]$ /usr/local/mysql57/bin/mysql -S /data/mysql_db/mysql_seg_3306/mysql.sock < mysql_backup_full.sql

导入完毕,我们可以看到数据和 Master 的备份数据一致

db72-3306>>show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| mytest |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec) db72-3306>>use mytest;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A Database changed
db72-3306>>show tables;
+------------------+
| Tables_in_mytest |
+------------------+
| test1 |
+------------------+
1 row in set (0.00 sec) db72-3306>>select * from test1;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | a | 16 |
| 2 | b | 17 |
| 3 | c | 18 |
| 4 | d | 19 |
+----+------+-----+
4 rows in set (0.00 sec)

2.4 开启同步

回到备份文件,我们从头部找到 Master 备份时间点的二进制日志位置

[mysql@mysql-test-72 ~]$ head -30 mysql_backup_full.sql | grep 'CHANGE MASTER TO MASTER_LOG_FILE'
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=154;

MASTER_LOG_FILEMASTER_LOG_POS 就是在 Master 执行 show master status 得到的二进制位置信息。现在,我们执行同步命令

-- 重置复制
-- reset slave; -- 同步配置
CHANGE MASTER TO
MASTER_HOST='192.168.41.83',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='repl',
MASTER_LOG_FILE='mysql-bin.000004',
MASTER_LOG_POS=154; -- 开启同步
start slave

实际执行结果如下

db72-3306>>CHANGE MASTER TO
-> MASTER_HOST='192.168.41.83',
-> MASTER_PORT=3306,
-> MASTER_USER='repl',
-> MASTER_PASSWORD='repl',
-> MASTER_LOG_FILE='mysql-bin.000004',
-> MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.20 sec) db72-3306>>start slave;
Query OK, 0 rows affected (0.01 sec)

查看同步状态

db72-3306>>show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.41.83
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 154
Relay_Log_File: mysql-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 154
Relay_Log_Space: 527
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 833306
Master_UUID: 15958368-e9a0-11e8-a98c-ecb1d77febe4
Master_Info_File: /data/mysql_db/mysql_seg_3306/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec) ERROR:
No query specified

我们可以从 Slave_IO_Running, Slave_SQL_Running, Seconds_Behind_Master 这三个参数可以判断出同步状态是否正常

  • Slave_IO_Running 取 Master 日志的线程, Yes 为正在运行
  • Slave_SQL_Running 从日志恢复数据的线程, Yes 为正在运行
  • Seconds_Behind_Master 当前数据库相对于主库的数据延迟, 这个值是根据二进制日志的时间戳计算得到的(秒)

从输出结果可以看到我们的同步是正常的,下面我们来测试一下

2.5 同步测试

在 Master 节点插入新数据

db83-3306>>insert into test1 values(0, 'chengqm', 24);
Query OK, 1 row affected (0.00 sec) db83-3306>>select * from test1;
+----+---------+-----+
| id | name | age |
+----+---------+-----+
| 1 | a | 16 |
| 2 | b | 17 |
| 3 | c | 18 |
| 4 | d | 19 |
| 5 | chengqm | 24 |
+----+---------+-----+
5 rows in set (0.00 sec)

备节点检查数据同步状态

db72-3306>>select * from test1;
+----+---------+-----+
| id | name | age |
+----+---------+-----+
| 1 | a | 16 |
| 2 | b | 17 |
| 3 | c | 18 |
| 4 | d | 19 |
| 5 | chengqm | 24 |
+----+---------+-----+
5 rows in set (0.00 sec)

可以看到数据已经同步到备节点,本次主备搭建完成

MySQL集群搭建(1)-主备搭建的更多相关文章

  1. MySQL集群(三)mysql-proxy搭建负载均衡与读写分离

    前言 前面学习了主从复制和主主复制,接下来给大家分享一下怎么去使用mysql-proxy这个插件去配置MySQL集群中的负载均衡以及读写分离. 注意:这里比较坑的就是mysql-proxy一直没有更新 ...

  2. mysql集群(双主)

    0.安装 所谓双主基本可以理解为两台服务器互为主备,其核心思路与主备配置相同. 服务器A: 内网IP: 10.44.94.219 服务器B: 内网IP: 10.44.94.97 1.配置服务器A lo ...

  3. MySQL集群Percona XtraDB Cluster安装搭建步骤详解

    http://www.linuxidc.com/Linux/2017-05/143501.htm http://blog.csdn.net/thundermeng/article/details/52 ...

  4. MySQL集群(二)之主主复制

    前面介绍了主从复制,这一篇我将介绍的是主主复制,其实听名字就可以知道,主主复制其实就是两台服务器互为主节点与从节点.接下来我将详细的给大家介绍,怎么去配置主主复制! 一.主从复制中的问题 1.1.从节 ...

  5. MySQL集群搭建(6)-双主+keepalived高可用

    双主 + keepalived 是一个比较简单的 MySQL 高可用架构,适用于中小 MySQL 集群,今天就说说怎么用 keepalived 做 MySQL 的高可用. 1 概述 1.1 keepa ...

  6. MySQL集群搭建(2)-主主从模式

    1 环境准备 上次我们搭建了主备架构,如下所示 这次我们的搭建目标是 具体配置信息 IP 系统 端口 MySQL版本 节点 读写 说明 192.168.41.83 Centos6.8 3306 5.7 ...

  7. Docker环境下的前后端分离项目部署与运维(六)搭建MySQL集群

    单节点数据库的弊病 大型互联网程序用户群体庞大,所以架构必须要特殊设计 单节点的数据库无法满足性能上的要求 单节点的数据库没有冗余设计,无法满足高可用 单节点MySQL的性能瓶领颈 2016年春节微信 ...

  8. Mycat搭建负载均衡,读写分离的Mysql集群

    Mycat搭建负载均衡,读写分离的Mysql集群 准备环境 1.mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz 2.Mycat-server-1.6.7.4-te ...

  9. 超详细干货!Docker+PXC+Haproxy搭建高可用强一致性的MySQL集群

    前言 干货又来了,全程无废话,可先看目录了解. MySQL搭建集群最常见的是binlog方式,但还有一种方式是强一致性的,能保证集群节点的数据一定能够同步成功,这种方式就是pxc,本篇就使用图文方式一 ...

随机推荐

  1. Centos7借助docker部署mysql,提供远程链接服务

    Centos7 借助docker部署mysql,并提供远程连接服务 安装docker 运行docker 注意安装docker和运行docker的步骤很简单,可以参考我学习docker的笔记 docke ...

  2. 【做题笔记】CF Edu Round 132

    1. 前言 本人第一次把 Div2. D 切了,开心. C 不会,寄. 后来在场外想到一种奇怪做法 AC 了. 2. 正文(A-D) CF 比赛链接 A. Three Doors 签到题.循环查找手中 ...

  3. Java中类成员访问权限修饰符(public、protected、default、private)

    1.public(公共的): 任何类都可以进行访问(最不严格). 2.protected(保护的): 同一包内的类以及其子类可以进行访问. 3.default(缺省的): 类中不加任何访问权限限定的成 ...

  4. 万答#4,延迟从库加上MASTER_DELAY,主库宕机后如何快速恢复服务

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 当主库宕机后,延迟从库如何才能"取消"主动延迟,以便恢复服务 ...

  5. 你有对象类,我有结构体,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang结构体(struct)的使用EP06

    再续前文,在面向对象层面,Python做到了超神:万物皆为对象,而Ruby,则干脆就是神:飞花摘叶皆可对象.二者都提供对象类操作以及继承的方式为面向对象张目,但Go lang显然有一些特立独行,因为它 ...

  6. 感谢有你!Apache DolphinScheduler 项目 GitHub star 突破 8k

    本周伊始,Apache DolphinScheduler 项目在 GitHub 上的 Github Star 总数首次突破 8K.目前,Apache DolphinScheduler 社区已经拥有 C ...

  7. Git 09 IDEA撤销提交

    参考源 https://www.bilibili.com/video/BV1FE411P7B3?spm_id_from=333.999.0.0 版本 本文章基于 Git 2.35.1.2 如果提交了不 ...

  8. 如何给load average 退烧

    故障现象:top - 14:02:56 up 250 days, 18:33, 7 users, load average: 142.92, 142.85, 142.80Tasks: 731 tota ...

  9. [CF1500C] Matrix Sorting (模拟)

    场上最后十几秒交上去过掉了耶! 题面 这里有两个 N ∗ M N*M N∗M 的 E x c e l \rm Excel Excel 表格 A A A 和 B B B. 我们知道 E x c e l ...

  10. 造数字(数位DP)

    题面 JZM 想要创造两个数字 x 和 y,它们需要满足 x or y = T,且Lx ≤ x ≤ Rx, Ly ≤ y ≤ Ry,JZM 想知道 x and y 有多少种可能的不同的取值.若有多组 ...