MySQL主从复制:半同步、异步

大纲node

  • 前言mysql

  • 如何对MySQL进行扩展?sql

  • MySQL Replication WorkFlow数据库

  • MySQL主从复制模式服务器

  • 实战演练架构

    • MySQL异步复制实现负载均衡

    • MySQL半同步复制实现异步

  • 实验中的思考socket

  • 总结性能

前言

本篇咱们介绍MySQL Replication的相关内容, 咱们首先介绍MySQL CLuster的实现原理和如何一步步构建一个MySQL Replication Cluster

看懂本文须要了解: MySQL基本操做,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主服务器只将数据同步复制给其中一台从服务器,半同步复制给其余的从服务器,来达到其中一台从服务器彻底同步的效果。

MySQL Replication WorkFlow

Master/Slave工做流程

blob.png

创建主从关系后, 主服务器若是有数据修改以后, BINLOG会更新, 从服务经过IO-Thread读取主服务器的BINLOG到本地的Relay Log, 再经过SQL-Thread对其进行重放(replay), 从而同步到本地

MySQL主从复制模式

在不一样的业务模型中咱们能够采用不一样的MySQL主从复制架构, 通常分为如下两种

  • Master/Slave: 指的是一主多从模式, 这种模式下能够有效的分担读请求, 可是写请求并不能完成负载分担、从节点可能数据不一致, 而且若是Master宕机了客户端就没法进行写操做了, 仍是有不少问题的

  • Master/Master: 指的是多主模式, 这种模式中的多台MySQL服务器都是Master, 也就意味着均可以进行读写操做, 可是有着更为严重的问题, 多个客户端同时写入数据时因为复制延迟可能到致使数据冲突等严重问题

经常使用的架构图

咱们可使用keepalived实现Master高可用, 而且使用半同步模式实现数据的彻底同步

blob.png

上面那种方式太占用Master的带宽, 咱们可让一台Slave扮演为Master, 为其余Slave同步数据

blob.png

实战演练

 

MySQL异步复制实现

实验拓扑

blob.png

环境部署

咱们须要在各台服务器上安装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半同步复制在MySQL5.5之后才以插件的形式进行提供, 因此这里咱们的MySQL要换成5.5版本的MariaDB

因为不少步骤和上面重复,我就不写出来了,先配置成M/S而后再按照我下面操做

实验拓扑

blob.png

配置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

相关文章
相关标签/搜索