大纲node
前言mysql
如何对MySQL进行扩展?sql
MySQL Replication WorkFlow数据库
MySQL主从复制模式服务器
实战演练架构
MySQL异步复制实现负载均衡
MySQL半同步复制实现异步
实验中的思考socket
总结性能
本篇咱们介绍
MySQL Replication
的相关内容, 咱们首先介绍MySQL CLuster
的实现原理和如何一步步构建一个MySQL Replication Cluster
看懂本文须要了解:
MySQL基本操做
,MySQL日志类型及其做用
你们以前应该了解; 在单台服务器性能不足时, 有两种方式进行扩展
Scale Up: 垂直扩展,指的是提高单台服务器的性能(硬件)来提高服务的性能
Scale Out: 水平扩展,指的是添加服务器经过负载均衡的方式来分担单台服务器的负载, 从而提高服务的性能
咱们能够经过LVS, HAProxy, Nginx等软件实现一些服务的负载均衡, 可是若是要用到
MySQL
上就会有一些问题, 以下
如何保证多台
MySQL
服务器数据的一致性如何保证多台服务器同时提交事务致使数据的完整性
如何保证一台服务器宕机时, 其的事务可以正常提交或ROLLBACK
…
咱们须要考虑的问题比扩展
WEB
服务多太多了, 毕竟你们都知道,数据无价
, 在不少重要场景中, 数据不能有半点闪失, 可是MySQL
对这方面作得并非很好, 而Oracle
数据库在这方面特别的厉害, 因此众多的银行都采用Oracle
数据库存储客户的帐户信息等, 这么说, 难道咱们就不用MySQL
了么? 这显然不可能, 咱们首先来介绍一下MySQL Replication Cluster
的几种同步数据方式
Synchronous Replication 同步复制
Asynchronous Replication 异步复制
Semisynchronous Replication 半同步复制
同步复制: 指的是客户端链接到
MySQL主服务器
写入一段数据,MySQL主服务器
同步给MySQL从服务器
,须要等待从服务器发出同步完成的响应才返回客户端OK,这其中等待同步的过程是阻塞的, 若是有N台从服务器, 效率极低。
异步复制: 指的是客户端链接到MySQL主服务器
写入一段数据,在主库写入Binlog日志后便可成功返回客户端OK,无需等待Binlog日志传送给从库。在一段时间内MySQL主服务器
会将写入的数据发送给MySQL从服务器
,在这段时间以内,从服务器的数据可能会和主服务不一致,一旦主库宕机,有可能会丢失日志。
半同步复制: 指的是客户端链接到MySQL主服务器
写入一段数据,MySQL主服务器
只将数据同步复制给其中一台从服务器,半同步复制给其余的从服务器,来达到其中一台从服务器彻底同步的效果。
Master/Slave工做流程
创建主从关系后, 主服务器若是有数据修改以后,
BINLOG
会更新, 从服务经过IO-Thread
读取主服务器的BINLOG
到本地的Relay Log
, 再经过SQL-Thread
对其进行重放(replay), 从而同步到本地
在不一样的业务模型中咱们能够采用不一样的
MySQL
主从复制架构, 通常分为如下两种
Master/Slave: 指的是一主多从模式, 这种模式下能够有效的分担读请求, 可是写请求并不能完成负载分担、从节点可能数据不一致, 而且若是
Master
宕机了客户端就没法进行写操做了, 仍是有不少问题的Master/Master: 指的是多主模式, 这种模式中的多台
MySQL
服务器都是Master
, 也就意味着均可以进行读写操做, 可是有着更为严重的问题, 多个客户端同时写入数据时因为复制延迟可能到致使数据冲突等严重问题
经常使用的架构图
咱们可使用keepalived实现Master高可用, 而且使用半同步模式实现数据的彻底同步
上面那种方式太占用Master的带宽, 咱们可让一台Slave扮演为Master, 为其余Slave同步数据
实验拓扑
环境部署
咱们须要在各台服务器上安装
MySQL
, 这里使用的是rpm包安装, 版本为5.1
[root@node1 ~]# yum install mysql-server -y [root@node2 ~]# yum install mysql-server -y [root@node3 ~]# yum install mysql-server -y
配置文件
node1配置文件(master) [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 innodb_file_per_table = 1 log_bin=master-log #开启二进制日志 log_bin_index=1 server_id=1 #设置serverid [mysqld_safe] log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid node2配置文件(slave1) [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 relay-log=relay-log #开启relay日志 innodb_file_per_table = 1 read-only = 1 #设置只读 server_id = 2 #设置serverid [mysqld_safe] log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid node3配置文件(slave2) [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 relay-log=relay-log innodb_file_per_table = 1 read-only = 1 server_id = 3 [mysqld_safe] log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid ##启动mysql
注意: server_id是表明这台服务器的id,在全部master和slaver中必须是惟一的,默认是1,推荐使用该服务器IP的最后一个冒号后面的数字,便于区分和记忆。
配置Master
Slave节点进行同步须要经过一个特定权限的用户进行, 因此咱们须要建立一个用户并赋予
REPLICATION SLAVE, REPLICATION CLIENT
权限
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'rpuser'@'%' IDENTIFIED BY 'passwd'; Query OK, 0 rows affected (0.00 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.00 sec) mysql> SHOW MASTER STATUS; +-------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-------------------+----------+--------------+------------------+ | master-log.000005 | 523 | | | +-------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
注意: 咱们要记录下Master的日志File的名称和pos的数值,在配置Slaver的时候须要用到。
这里的语句: GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'rpuser'@'%' IDENTIFIED BY 'passwd';
咱们来逐步分析下:
GRANT 授予
REPLICATION SLAVE权限:
The REPLICATION SLAVE privilege should be granted to accounts that are used by slave servers to connect to the current server as their master. Without this privilege, the slave cannot request updates that have been made to databases on the master server.
REPLICATION SLAVE是一个必须而基本的权限,它直接授予slave服务器以该帐户链接master后能够执行replicate操做的权利。
REPLICATION CLIENT权限:
The REPLICATION CLIENT privilege enables the use of SHOW MASTER STATUS and SHOW SLAVE STATUS.
REPLICATION CLIENT 使得用户可使用SHOW MASTER STATUS和SHOW SLAVE STATUS命令,也就是说这个权限是用于授予帐户监视Replication情况的权力。
通常来讲,咱们会单独在主服务器建立一个专门用于Replication的帐户。这个帐户必须具备REPLICATION SLAVE权限,除此以外没有必要添加没必要要的权限,保证该用户的职责单一。
ON *.*: 权限加载到的对象上,*.*表示全部;
TO: 把权限赋予给谁;
'rpuser'@'%' INDENTIFIED BY 'passwd': 用户名为rpuser的用户,且该用户的服务器ip为%,这里用了通配符,就是不限ip,若是是@'192.168.1.%'则表示192.168.1.1到192.168.1.255之间的全部ip,用'passwd'做为密码进行校验。
这样作的好处:一方面使用同一帐户对Replication进行监视管理会很方便,没必要区分slave,master,另外一方面,repl帐户在slave和master上的配置是同样的,这样若是咱们切换slave和master,帐户不须要作任何改动。
配置Slave(1)
mysql> CHANGE MASTER TO -> MASTER_HOST='172.16.1.2', -> MASTER_USER='rpuser', -> MASTER_PASSWORD='passwd', -> MASTER_LOG_FILE='master-log.000005', -> MASTER_LOG_POS=523; Query OK, 0 rows affected (0.01 sec mysql> SHOW SLAVE STATUS\G; #查看相应信息 #########省略################## Master_Log_File: master-log.000005 Read_Master_Log_Pos: 523 Relay_Log_File: relay-log.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: master-log.000005 Slave_IO_Running: No #IO-thread没有启动 Slave_SQL_Running: No #SQL-thread没有启动 #########省略################## mysql> START SLAVE; #启动sql-thread和io-thred mysql> SHOW SLAVE STATUS\G; #查看相应信息 Query OK, 0 rows affected (0.00 sec) #########省略################## Master_Log_File: master-log.000005 Read_Master_Log_Pos: 523 Relay_Log_File: relay-log.000002 Relay_Log_Pos: 252 Relay_Master_Log_File: master-log.000005 Slave_IO_Running: Yes #IO-thread启动 Slave_SQL_Running: Yes #SQL-thread启动 #########省略##################
注意这里的几项配置:
-> MASTER_HOST='172.16.1.2',
-> MASTER_USER='rpuser',
-> MASTER_PASSWORD='passwd',
-> MASTER_LOG_FILE='master-log.000005',
-> MASTER_LOG_POS=523;
必须和MASTER上执行的命令配置相符。
配置slave(2)
过程和配置slave(1)相同, 不作演示
测试主从复制
##在主服务器上建立数据库和表 [root@node1 ~]# mysql mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | test | +--------------------+ 3 rows in set (0.00 sec) mysql> CREATE DATABASE replication; Query OK, 1 row affected (0.00 sec) mysql> USE replication; Database changed mysql> CREATE TABLE t1 (id int unsigned auto_increment primary key, name char(30)); Query OK, 0 rows affected (0.01 sec) mysql> DESC t1; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | char(30) | YES | | NULL | | +-------+------------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> SHOW MASTER STATUS; +-------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-------------------+----------+--------------+------------------+ | master-log.000005 | 765 | | | +-------------------+----------+--------------+------------------+ 1 row in set (0.00 sec)
##在slave服务器测试 [root@node2 ~]# mysql mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | replication | | test | +--------------------+ 4 rows in set (0.00 sec) mysql> use replication; 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 mysql> DESC t1; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | char(30) | YES | | NULL | | +-------+------------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> SHOW SLAVE STATUS\G; #########省略################## Master_Log_File: master-log.000005 Read_Master_Log_Pos: 765 #已经同步 Relay_Log_File: relay-log.000002 Relay_Log_Pos: 494 Relay_Master_Log_File: master-log.000005 Slave_IO_Running: Yes Slave_SQL_Running: Yes #########省略##################
因为
MySQL
半同步复制在MySQL
5.5之后才以插件的形式进行提供, 因此这里咱们的MySQL
要换成5.5版本的MariaDB
因为不少步骤和上面重复,我就不写出来了,先配置成M/S而后再按照我下面操做
实验拓扑
配置master
半同步的插件在/usr/lib64/mysql/plugin下, master用的semisync_master.so,slave用的semisync_slave.so, MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> SET GLOBAL rpl_semi_sync_master_enabled = 1; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> SET GLOBAL rpl_semi_sync_master_timeout = 2000; #设置超时时间为2S Query OK, 0 rows affected (0.00 sec)
配置slave
MariaDB [(none)]> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; Query OK, 0 rows affected (0.00 sec) MariaDB [(none)]> SET GLOBAL rpl_semi_sync_slave_enabled=1; Query OK, 0 rows affected (0.00 sec)
正常状况下,这两个PLUGIN在master和slave上都应该被标准安装,谁知道哪天备库会不会被切换成主库呢。
安装完PLUGIN后,咱们能够根据拓扑结构来定义主库和备库的配置,主要包括如下几个配置项;
1.rpl_semi_sync_master_enabled
—控制主库上是否开启semisync, 打开或关闭,马上生效
2.rpl_semi_sync_slave_enabled
—控制备库是否开启semisync,
当主库打开semisync时,则必须至少要有一个连接的备库是打开semisync的,不然主库线程每次都会去等待,直至超时;所以若是想关闭semisync必需要先关闭主库配置,再关闭备库配置
3.rpl_semi_sync_master_timeout
—控制主库上客户端的等待时间,当超过这么长时间等待后,客户端返回,同步复制退化成原生的异步复制
单位为毫秒,默认值为10000,即10秒
4.rpl_semi_sync_master_wait_no_slave
默认打开,表示当备库起来后,并跟上主库时,自动切换到同步模式,若是关闭,即便备库起来并跟上了,也不会启用半同步;
5.rpl_semi_sync_master_trace_level 以及 rpl_semi_sync_slave_trace_level
— 输出监控信息的级别,详细点击见文档,不一样的级别,可能输出更详细的信息,用于DEBUG
运行状态变量也比较丰富,不细说了,网上介绍的不少,官方文档也很详细
验证
由于在个人环境中,即便是半同步复制,也是直接就完成,看不出效果,因此咱们故意将slave节点关闭 [root@node2 ~]# service mysql stop ##master建立数据库 MariaDB [(none)]> CREATE DATABASE TEST3; Query OK, 1 row affected (2.00 sec) #等待2s, 超时再也不等待,直接建立 MariaDB [(none)]> CREATE DATABASE TEST4; Query OK, 1 row affected (0.00 sec) ##完成,这个可能不是特别直观,可是因为我这边环境实在作不出效果,望你们理解
若是主从服务器数据相差较大, 最好先使用主服务器的二进制日志在从服务器上replay一遍, 而后再进行同步
这篇其实还打算写SSL复制的,可是由于时间比较紧,就没有写了,整体来讲不是特别的满意,有不少地方没有说明白,还望你们谅解。
做者水平很低, 若是有错误及时指出, 若是你以为本文写的好请点一波赞~(≧▽≦)/~ 做者: AnyISaIln QQ: 1449472454 感谢: MageEdu