MySQL主从复制
本节内容我们联系使用MySQL的主从复制功能配置Master和Slave节点,验证数据MySQL的数据同步功能。
因为要使用多个MySQL数据库,所以不建议在电脑上安装多个MySQL数据库,最好的办法是使用多个绿色版的MySQL数据库。
MariaDB数据库是MySQL创始人Michael创建的MySQL重要分支。由于Oracle持有了MySQL的版权,MySQL存在闭源的隐患,加之Oracle对MySQL的更新不太重视,所以业界许多公司纷纷采用了完全开源的MariaDB数据库。MariaDB建立在MySQL5.5版本上,所以MariaDB与MySQL的兼容性非常好,并且性能上也做出了很大的优化,社区活跃,软件版本更新迅速,包括谷歌、Facebook等企业纷纷改用MariaDB数据库。
Master数据库
首先把安装到C:Program Files里面的MariaDB目录复制一份,放置的路径没有要求,但是尽量把数据库放在C盘或者D盘上面,改名DB1。因为这两个盘符的空间处在硬盘磁碟的外圈,所以线速度很快,数据读写速度也很理想。
DB1将要当做主库使用,创建my.ini文件,然后编辑文件内容。
[mysqld]
#数据库字符集
character_set_server = utf8
#MySQL主机名(只可以是数字)
server_id = 10
#端口号
port = 7001
#开启二进制操作日志(日志内容会发送给Slave数据库执行)
log_bin = mysql_bin
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
创建start.bat文件,编写启动命令。
cd bin
mysqld --defaults-file=../my.ini --user=root
@pause
执行start.bat命令启动DB1数据库,命令行窗口关闭后也不影响MariaDB的运行。
启动MariaDB客户端,用户名为root,密码是安装MariaDB时候设置的,因此输入正确密码登录即可。
在DB1中创建新的用户给Slave主机同步数据使用,由于root用户权限太大而且无法远程访问,所以必须创建一个新的用户才行。
- 用户名为backup
- Slave主机的IP是127.0.0.1
- 密码设置为abc123456
给backup用户设置服务权限(勾选3个权限)然后保存,具备数据同步的权利。
这时候需要关闭数据库,在DB1连接上右键选择“命令界面”,在命令界面中输出shutdown;回车即可。
关闭了DB1,在data文件夹中删除所有以mysql_bin开头的文件。这些文件是二进制操作日志文件,其中包含了在Master数据库创建slave账号和权限的操作,这部分操作不应该同步到Slave数据上面,所以我们就应该把二进制操作文件都删除。
再次启动DB1数据库
Slave服务器
依照DB1的做法,从C盘安装位置再复制一份MariaDB文件夹,起名为DB2。DB2当做备份数据库,所以我们还是要先创建my.ini文件。
[mysqld]
#数据库字符集
character_set_server = utf8
#MySQL主机名(只可以是数字)
server_id = 20
#端口号
port = 7002
#开启二进制操作日志(日志内容会发送给Slave数据库执行)
log_bin = mysql_bin
#Slave从Master等到mysql_bin的日志数据后先写到本地的relay_bin日志中然后在执行
relay_log = relay_bin
#该参数规定Slave的更新操作是否要写入log_bin
#当A时Master,B是Slave,同时还是C的Master,这个时候就需要开启该参数
#本次实验只验证两台数据库的Master和Slave关系,所以不用开启
#log-slave-updates = 1
#该参数定义Master失联后再次连接的间隔时间(默认60秒)
#master-connect-retry = 60
#Slave数据库的数据不可以更改,只能与Master同步
read-only = 1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
创建start.bat文件,然后启动数据库
使用客户端连接7002端口的DB2,用户名root,密码是安装密码。
启动DB2的命令界面,然后执行如下MySQL命令。
stop slave;
-----------------------------------------------------------------------
change master to master_host='127.0.0.1',master_port=7001,master_user='backup',master_password='abc123456';
-----------------------------------------------------------------------
start slave;
取消命令界面的“自动换行”然后执行下面的语句
show slave status;
如果上图两处状态信息都为YES,那么就代表数据库主从同步已经成功。
为了验证主从同步已经成功,我们在Master数据库中创建student表,然后随意插入数据,接着再查看Slave数据库里面的student表和数据是否已经同步。
双Master双Slave
我们已经有了一个Master数据库和一个Slave数据库,但还显得不够。原因要从两个方面分析。其一,Master和Slave的工作状态由谁来管理。比如DB1宕机,DB2接替工作成为新的Master,那么DB1恢复上线之后,DB1就应该自动变成Slave数据库,同步数据。当DB2宕机,DB1重新成为Master,显然我们需要一种管理DB1和DB2的软件。其二,DB1充当Master,所有的SQL读写操作全部由DB1完成,没有读写分离机制,导致DB的负担过重,效率低下,因此我们需要一种读写分离机制。
开源的MyCat数据库集群软件做的不错,非常适合管理许多MySQL数据库集群。因为是阿里巴巴团队出品,所以实际应用起来效果很好。关于MyCat的介绍这里不过多介绍,请各位访问MyCat的官网(http://www.mycat.org.cn/)
我们将使用MyCat管理MariaDB数据库的集群,它将接管数据的读写分离和主从备份的管理工作。必须要跟大家介绍一下我这里采用的双Master双Slave的集群方式,因为这将关系到MyCat的具体配置。下面我们一起推演从Master/Slave发展到双Master双Slave的过程。
之前我们拥有了DB1和DB2两个数据库,一个当作Master,另一个当作Slave。SQL读写操作全部放在DB1上完成,DB1的负担很重,而且速度也很受影响。故此让DB1变成write节点,DB2变成read节点,SQL语句的分发由MyCat完成。DB1写入/更新的数据会及时备份给DB2,DB2执行SELECT语句会查询到这些数据,这样就实现了读写分离的功能,数据的使用速度大大提高了(不明白读写分离机制好处的同学可以利用百度搜索自行学习)。
读写分离实现了,可是目前还有一个棘手的问题急需解决:主从备份。因为DB2是read节点,当DB1宕机之后,DB2是不能转换成write节点的,所以这就没办法保证主从备份的及时切换。于是我们又想出了一个新办法,再创建一个write节点,让DB3接替DB1的工作,DB4充当DB3的read节点。DB1和DB3都有可能宕机,其中一个宕机,另一个必须立即接替工作,所以DB1和DB3必须保证数据的同步: DB1和DB3互为主从备份。
创建DB3数据库,步骤与之前相同,my.ini文件如下:
[mysqld]
#数据库字符集
character_set_server = utf8
#MySQL主机名(只可以是数字)
server_id = 30
#端口号
port = 7003
#开启二进制操作日志(日志内容会发送给Slave数据库执行)
log_bin = mysql_bin
#Slave从Master等到mysql_bin的日志数据后先写到本地的relay_bin日志中然后在执行
relay_log = relay_bin
#该参数规定Slave的更新操作是否要写入log_bin
log-slave-updates = 1
#该参数定义Master失联后再次连接的间隔时间(默认60秒)
#master-connect-retry = 60
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
登录客户端软件,创建backup账户,勾选三个权限,这些操作与之前DB1的完全一致。
关闭DB3数据库,删除data目录中的所有mysql_bin开头的文件,然后重新启动数据。
命令界面执行主从同步的设置命令,如下:
stop slave;
-----------------------------------------------------------------------
change master to master_host='127.0.0.1',master_port=7001,master_user='backup',master_password='abc123456';
-----------------------------------------------------------------------
start slave;
查看主从备份是否成功,如果成功则说明DB3是DB1的Slave数据库。
关闭DB1数据库,重新改写my.ini配置文件。
[mysqld]
#数据库字符集
character_set_server = utf8
#MySQL主机名(只可以是数字)
server_id = 10
#端口号
port = 7001
#开启二进制操作日志(日志内容会发送给Slave数据库执行)
log_bin = mysql_bin
#Slave从Master等到mysql_bin的日志数据后先写到本地的relay_bin日志中然后在执行
relay_log = relay_bin
#该参数规定Slave的更新操作是否要写入log_bin
log-slave-updates = 1
#该参数定义Master失联后再次连接的间隔时间(默认60秒)
#master-connect-retry = 60
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
重新启动DB1,在DB1的命令界面设置主从同步,如下:
stop slave;
-----------------------------------------------------------------------
change master to master_host='127.0.0.1',master_port=7003,master_user='backup',master_password='abc123456';
-----------------------------------------------------------------------
start slave;
查看主从配置是否成功,如果成功则说明DB1是DB3的Slave数据库。
仿照DB2的步骤,创建DB4,my.ini中的端口号设置为7004,server_id设置为40,然后设置成DB3的Slave,至此双Master和双Slave配置成功。
下载最新版本的MyCat软件,目前最新版本是1.5,我们下载对应的windows版MyCat。千万要注意,MyCat压缩文件不能解压缩到含有中文和空格的目录下面,例如桌面和C:Program Files
因为MyCat是用Java语言开发的数据库集群工具,因此我们必须要安装JDK1.7以上的版本。这里省略JDK的安装过程,需要重点声明,必须要配置path变量和JAVA_HOME变量。
修改mycatinstartup_nowrap.bat文件,把-Xms1G和-Xmx2G修改成-Xms128M和-Xmx256M。如果不修改这两处配置,MyCAT很有可能会因为内存空间不够而无法启动。
打开mycatconfserver.xml文件,里面包含了MyCat默认自带的两个账户(内容可以修改),以后我们将使用user账户登录MyCat。
打开mycatconfschema.xml文件,设置数据库连接。
DB1~DB4的用户名为root,我这里的数据库安装密码为112233。<writeHost>是write节点,<readHost>是read节点,意味着读写分离设置完毕。
<dataHost>标签的balance=3意味着所有的读请求随机分发到<readHost>节点。
- 当<writeHost>节点宕机,那么它对应的<readHost>节点将不负责处理读操作。
- 当<readHost>节点宕机,那么读操作将分发给其他的<readHost>节点。
<dataHost>标签的writeType=1意味着<writeHost>节点宕机,MyCat会切换使用其他的<writeHost>。switchType=1代表自动切换从主服务器。
数据切分
至此还没有结束,因为DB1~DB4的双Master双Slave数据库仅仅实现了主从备份和读写分离,数据切分还没有实现。什么是数据切分?比如电商系统的交易记录表数据量就很大,日积月累可能已经到了几千万条记录了。这时候对数据的CRUD操作会很慢,通常情况下MySQL单表数据超过2000万,速度就会迅速下降。像是索引、SQL语句优化等等的作用很不明显,甚至索引会成为一种累赘(海量数据排序)。最根本的解决办法就是缩小MySQL单表数据体积,控制在2000万条以内。超出这个范围就实行切分数据,海量数据保存到不同的数据库数据表中。比如双十一当天产生了5亿条订单,这些记录被切分到50台MySQL数据库中,每个MySQL的订单交易表分得1000万条数据,这样就能保证每台MySQL数据库的性能。
当然了,随着时间的推移,这些MySQL中的数据也会超过2000万条,这时候应该怎么处理?再添加50台MySQL吗?No,No,这时候应该做冷热数据处理。1年内的订单交易的数据最为重要,1年以上的交易数据很少被用到,那么我们编写程序定期将过期的订单转移到几个MySQL数据库中,即便单表数据会超过2000万,由于这些数据极少被用到,所以不用担心速度的问题。冷热数据处理不是我们这篇文章深入讨论的内容,我们要利用MyCat实现数据切分。
DB1~DB4的读写性能和抗风险性都很好,挂掉某个DB节点,其他备用的DB会接替工作。因为DB1和DB3互为主从复制,所以我们不能拿它们做数据切分。如果我们把数据切分到DB1和DB3上,它们的备份机制会保证两个数据库的数据完全相同,这与数据切分的初衷相悖。所以,我们把DB1~DB4当作一个虚拟的切分节点,还需要再创建另外一个虚拟切分节点,当然也需要实现主从复制和读写分离,因此各位同学要创建DB5~DB8数据库,也是采用双Master双Slave的形式,请各位自行完成,请注意DB1~DB4与DB5~DB8没有主从复制关系。
为mycat/conf/schema.xml文件再配置一个<dataHost>,name=localhost2,两个<dataHost>节点用作数据切分。
如下图,修改<dataNode>节点,只保留两个<dataNode>节点。当数据被切分到localhost1上会被保存到db1数据库里面,也就是说DB1~DB4上面都会有db1这个数据库。当数据被切分到localhost2上会被保存到db2数据库里面,意味着DB5~DB6都会有db2数据库。
修改<table>标签,如下图:
执行mycat/bin/ startup_nowrap.bat文件,启动mycat服务器,启动成功界面如下:
在DB1上面创建db1数据库,由于主从备份的缘故,DB2~DB4自动都会创建db1数据库。
在DB5上面创建db2数据库,D6~DB8也会自动创建db2数据库。
用客户端创建一个MyCat连接,端口号为8066,用户名test,密码test
使用MyCat连接到MyCat服务器之后,点击工具栏上面的“查询”,然后再查询窗口中执行SQL语句创建company表。因为schema.xml文件中<table>标签规定了company表是全局表,所以数据会被同样分发到dn1和dn2两个节点。
各位同学在每个数据库连接下面的“表”选项上点击右键刷新就会发现DB1~DB4的db1中存在company表,DB5~DB8的db2中也存在company表。
回到MyCAT的查询面板,接着执行SQL语句插入数据。
然后观察DB1~DB8每个company表是否都包含了插入的数据。
我们再创建一个employee表,如下图:
根据schema.xml文件中<table>标签可知,employee是分片表,数据会被切分。又根据partition-hash-int.txt文件得知,sharding_id列的数据是10000,则记录被切分到dn1节点,DB1~DB4都会保存这条记录,反之保存到dn2节点。
执行插入语句,查看DB1~DB4和DB5~DB8的employee表数据是否是不相同的,完成了数据切分。
为了验证数据库容灾性,我们使用shutdown命令关闭DB1,再次向company和employee插入新数据,检查是否可以执行。然后再启动DB1数据库,观察DB1中的company和employee数据是否已经实时与DB3同步了。这样的话,无论DB1~DB8哪一个数据库宕机都不会影响到数据库集群,也不会损失任何数据。