小笙's Blog

简要剖析Mysql主从复制2014.09.22 18:40

1.1 产生背景

随着系统数据量的不断增加,由单台Mysql作为独立数据库无法满足业务需求,无论是在安全性(数据备份),高可用性(容错能力)及高并发(负载均衡)等各个方面。

因此,针对查询为主系统(select查询),可以采用主从复制策略。通过Mysql的主从复制(Master-Slave)来同步数据,再通过读写分离来提升数据库的并发负载能力,这样就可以得到更好的客户端响应时间。

1.2 工作原理

主从复制通过三个过程实现,其中一个发生在主服务器上,另外两个发生在从服务器上。

1.主服务器将用户对数据库的更新操作以二进制文件保存到BinaryLog日志文件中,然后由BinlogDump线程将BinaryLog日志文件传输给从服务器。

2.从服务器通过一个I/O线程将主服务器的BinaryLog日志文件中的更新操作复制到一个叫RelayLog的中继日志文件中。

3.从服务器通过另一个SQL线程将RelayLog中继日志文件中的操作依次在本地执行,从而实现主从之间数据的同步。

三个线程

1.BinLog Dump线程

BinLog Dump线程运行在主服务器上,主要工作是把BinaryLog二进制文件的数据发送到从服务器。使用SHOWPROCESSLIST语句查看该线程状态。

2.I/O线程

从服务器执行STARTSLAVE语句后,创建一个I/O线程。此线程运行在从服务器上,与主服务器建立连接,然后向主服务器发送更新请求。之后,I/O线程将主服务器的BinLogDump线程发送的更新操作,复制到本地RelayLog日志文件中。

3.SQL线程

SQL线程运行在从服务器上,主要工作是读取RelayLog日志文件中的更新操作,将这些操作依次执行,从而使主从服务器数据得到同步。

当有多台从服务器时,主服务器为每个当前连接的从服务器创建一个线程,每个从服务器有自己的I/O线程和SQL线程。关于这三个线程运行过程中可能出现的一些状态,可以参考Mysql参考手册:6.3.复制实施细节

2.1 Mysql兼容性

Mysql5.x与4.x版本使用的日志文件格式大大不同,所以主从库最好采用相同版本,如果达不到要求,必须保证主服务器版本不高于从服务器版本。

2.2 配置Master

在主服务器上为从服务器设置一个连接账户,授予REPLICATIONSLAVE权限。假定你想要创建用户名为slave1的一个账户,从服务器可以使用该账户从你的域内的任何主机使用密码passwd来访问主服务器。要创建该账户,可使用GRANT语句:

1
2
mysql>GRANTREPLICATION SLAVEON *.*
->TO'slave1'@'%'IDENTIFIED BY'passwd';

接着打开my.ini(my.cnf)配置文件,指定log-bin及唯一的serverid。

1
2
3
[mysqld]
log-bin = mysql-bin
server-id = 1

重启mysql服务器,运行SHOWMASTER STATUS查看

File表示主服务器正在使用的binlog文件,如果是第一次配置,则此处显示为mysql-bin.000001,并且每次重启服务器都会递增生成新文件;Position的值与binlog文件的大小相同,表示下一个被记录事件的位置;Binlog_Ignore_DB与Binlog_Do_DB是主服务器控制写入binlog文件内容的过滤选项,默认为空,表示不做任何过滤。

File和Position两列指明从服务器将从哪个binlog文件中复制,以及复制的开始位置,也是用来配置从服务器的参数。

2.3 配置Slave

从服务器的配置与主服务器类似,必须提供唯一的server-id(不能跟主服务器ID相同),配置完成后重启服务器。

1
2
3
[mysqld]
log-bin = mysql-bin
server-id = 2

接下来需要使用CHANGEMASTER TO语句指定主服务器的信息。

1
2
3
4
5
CHANGE MASTER TOMASTER_HOST=’192.168.191.1’,
MASTER_USER=’slave1’,
MASTER_PASSWORD=’passwd’,
MASTER_LOG_FILE=’mysql-bin.000005’,
MASTER_LOG_POS=825

使用SHOW SLAVESTATUS语句查看从服务器的设置是否正确

2.4 运行操作

1.在从服务器上执行STARTSLAVE开始复制:

1
mysql > START SLAVE;

运行SHOWSLAVE STATUS查看输出结果:

从结果看出,从服务器的I/O线程和SQL线程都已经成功开始运行。

在主服务器上运行SHOWPROCESSLIST查看BinlogDump进程:

在从服务器上执行SHOWPROCESSLIST查看:

2.row为I/O线程,3.row为SQL线程。

2. 测试主从复制

在主服务器上执行数据库的更新操作:

1
2
3
4
5
6
7
8
mysql>createdatabasems_test;
Query OK, 1 row affected (0.00 sec)
mysql> use ms_test;
Databasechanged
mysql>createtabletest(idint);
Query OK, 0 rowsaffected (0.25sec)
mysql>insertintotestvalues(1), (2), (3);
Query OK, 3 rowsaffected (0.08sec)

在从服务器上,执行查询,可以看到数据已经成功更新到了从服务器上。

3. 读写分离性能提升测试

由于网络、服务器等的环境差异,以及测试工具的局限性,无法做严格的测试,所以此处使用apache的ab工具测试在高并发情况下,使用读写分离对主库执行更新操作的效率变化。

1.准备好测试代码和测试工具

采用表复制的方法,预先向test表插入300W+条数据,数据分散为1,2,3.

1
insertintotest select* fromtest;

ms.php连接主库执行插入操作。

1
2
3
$conn_m= newMysqli('192.168.191.1', 'root', '123456', 'ms_test');
$conn_m->query('INSERTINTO `test` values('. rand(1, 1000) . ')');
$conn_m->close();

ms2.php连接主库执行耗时查询.

1
2
3
$conn_s= newMysqli('192.168.191.1, 'root', '123456', 'ms_test');
$conn_s->query('SELECTcount(*) FROM `test` WHERE id='.$i);
$conn_s->close();

2.同时启动两个ab进程,测试同时连接主库执行查询和更新。

1
ab.exe-n2000 -c200 http://localhost/ms2.php(请求2000次,每次并发200个)

1
ab.exe-n100 -c10 http://localhost/ms2.php(请求100次,每次并发10个)

3.将ms2.php的连接指向从库。

1
$conn_s= newMysqli('192.168.191.2’, 'root', '123456', 'ms_test');
1
ab.exe-n2000 -c200 http://localhost/ms2.php(请求2000次,每次并发200个)

1
ab.exe-n100 -c10 http://localhost/ms2.php(请求100次,每次并发10个)

可以看到在查询时间无太大变化的情况下(并发的更新操作较少),更新时间是有了较快的提升。

4. 总结

Mysql主从复制可以较好的解决高并发情况下数据库锁的性能瓶颈,不过在数据及时同步方面稍显不足,如果主服务器宕机,会导致从服务器不能及时更新到数据,这种情况下可以考虑半同步复制和主主复制。

架构在演变,技术在更新,唯有保持一颗永不懈怠之心,才能跟上时代的步伐。


  • 正在加载用户留言,请稍后~
点击这里取消回复

  • 请选择邮箱类型
  • @qq.com
  • @163.com
  • @sina.com
  • @126.com
  • @vip.qq.com
  • @sina.com.cn

:love: :kiss: :twist: :top: :shake: :bye: :han: :sleep: :lula: :rou: :happy: