数据库读写分离对于大型系统或访问量很高的互联网应用来说,是必不可少的一个重要功能。对于MySQL来说,标准的读写分离是主从模式,一个写节点Master后面跟着多个读节点,读节点的数据取决于系统的压力,通常是1-3个读节点的配置。读写分离如果不用mycat的话,就需要配置两套数据源,读的时候用一套数据源,写的时候用另外一套数据源,然后配置数据库主从复制,然而这种做法无法进行分片,也就是说,当数据量很大时,依然会出现读取速度缓慢的问题。但是用mycat的话,我们不用关心数据源的问题,只需配置主从复制,而且可以分片,操作也很简单,优势是很明显的。
下面我们看下主从复制原理图,如下图所示。writeHost专门复制增删改操作,而readHost专门负责读操作,那么当我向负责写的数据库插入一条数据时,读数据库如何知道我插入数据了呢?这其实用到了binlog文件,当有写操作时,会向binlog文件中记录相关操作,而readHost是可以读取到binlog文件的,从而可以根据binlog文件来实现数据同步。那么有个问题,就是当我有数据正在从写数据库同步到读数据库时,用户这时恰好要访问刚才插入的数据,会不会有问题呢?其实mycat帮我们考虑到了这个问题,当有同步正在进行时,mycat会让相关请求进行等待,等到同步完后,再响应数据。我们用户不用操心访问的是哪个数据库,只需要通过mycat进行操作就可以了。
mysql的主从复制与mycat没有什么关系,我们先来看下主从复制原理图,如下图所示。
主从配置需要注意的地方
1、主DB server和从DB server数据库的版本一致
2、主DB server和从DB server数据库数据一致【这里就可以把主的备份在从上还原,也可以直接将主的数据目录拷贝到从的相应数据目录】
3、主DB server开启二进制日志,主DB server和从DB server的server_id都必须唯一
下面我们来学习Mysql的 主从复制
Mysql主服务器的配置
第一步:修改/etc/my.cnf文件:
在[mysqld]段下添加:
#指定binlog文件在哪个数据库上,这里指定在db1上,这里特别需要注意的是,这里只指定了对数据库db1进行主从复制,也就意味着其它数据库是不能主从复制的
binlog-do-db=db1
#binlog忽略的数据库,这里忽略mysql数据库本身带的mysql库
binlog-ignore-db=mysql
#启用二进制日志
log-bin=mysql-bin
#服务器唯一ID,一般取IP最后一段
server-id=41
第二步:重启mysql
service mysqld restart
第三步:建立账户并授权slave
#创建一个用户"backup",并且密码设置为"123456"
mysql>GRANT FILE ON *.* TO 'backup'@'%' IDENTIFIED BY '123456';
#为新建的用户授权,允许主从复制
mysql>GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* to 'backup'@'%' identified by '123456';
#一般不用root帐号,“%”表示所有客户端都可能连,只要帐号,密码正确,此处可用具体客户端IP代替,如192.168.145.226,加强安全。
刷新权限
mysql> FLUSH PRIVILEGES;
查看mysql现在有哪些用户
mysql>select user,host from mysql.user;
第四步:查询master的状态,其中Position的值120(不是固定的)很重要,我们后面会用到。
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 120 | db1 | mysql | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set
Mysql从服务器的配置
第一步:修改/etc/my.cnf文件,在[mysqld]下面添加
[mysqld]
server-id=42
重启mysql
[root@mysql-server2 ~]# service mysqld restart
第二步:配置从服务器
mysql>change master to master_host='192.168.156.41',master_port=3306,master_user='backup',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=120
注意语句中间不要断开,master_port为mysql服务器端口号(无引号),master_user为执行同步操作的数据库账户,“120”无单引号(此处的120就是show master status 中看到的position的值,这里的mysql-bin.000001就是file对应的值)。
第三步:启动从服务器复制功能
mysql>start slave;
如果已经启动了slave,那么需要先关闭slave
mysql>stop slave
然后再启动。
第四步:检查从服务器复制功能状态:最好在mysql工具中执行,因为它的列非常多,工具类查看比较方便。
mysql> show slave status
……………………(省略部分)
Slave_IO_Running: Yes //此状态必须YES
Slave_SQL_Running: Yes //此状态必须YES
……………………(省略部分)
注:Slave_IO及Slave_SQL进程必须正常运行,即YES状态,否则都是错误的状态(如:其中一个NO均属错误)。
错误处理:
如果出现此错误:
Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
因为是mysql是克隆的系统所以mysql的uuid是一样的,所以需要修改。
解决方法:
删除/var/lib/mysql/auto.cnf文件,重新启动服务。
下面我们便来测试下主从复制是否好用,配置
在主服务器的/etc/my.cnf文件当中,在[mysqld]下面我们配置了这么一个配置
binlog-do-db=db1
上面这句配置的意思是主从服务器只针对名称为"db1"的数据库进行主从复制,其它数据库不能进行主从复制。
那么,我们便来在主服务器上新建一个库"db1",并在db1库中新建一张表并在表中插入一条数据。刷新mysql-server(192.168.156.41)和mysql-server2(192.168.156.42),如下图所示,可以看到两个服务器中都有db1数据库了,而且db1库中都有hi_tb表以及表中的数据都一致。这说明主从复制没问题。
注:如果出现不成功的现象,请检查从服务器的从属状态,如下图所示,两个变量必须都是Yes,如果不全是Yes的话,就是错误的。
如果不全是Yes,请参考主服务器的show master status;命令的回显结果,如下图所示。
然后结合从服务器的这条sql命令进行对应的修改即可。
mysql>change master to master_host='192.168.156.41',master_port=3306,master_user='backup',master_password='123456',master_log_file='mysql-bin.000002',master_log_pos=616;
Mycat的配置
Mycat 1.4 支持MySQL主从复制状态绑定的读写分离机制,让读更加安全可靠,Mycat所在的服务器是192.168.156.41,我们配置的文件是schema.xml,该文件所在的位置在/usr/local/software/mycat/conf目录 下。只修改localhost1,其余的与上篇博客一致即可,配置如下:
<!--一个dataHost代表一个数据源-->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="2" slaveThreshold="100">
<heartbeat>show slave status</heartbeat>
<writeHost host="hostM" url="192.168.156.41:3306" user="root"
password="root">
<readHost host="hostS" url="192.168.156.42:3306" user="root"
password="root" />
</writeHost>
</dataHost>
下面是对上面配置的解释
(1) 设置 balance="1"与writeType="0"
Balance参数设置:
1. balance=“0”, 所有读操作都发送到当前可用的writeHost上。
2. balance=“1”,所有读操作都随机的发送到readHost。
3. balance=“2”,所有读操作都随机的在writeHost、readhost上分发
WriteType参数设置:
1. writeType=“0”, 所有写操作都发送到可用的writeHost上。
2. writeType=“1”,所有写操作都随机的发送到readHost。
3. writeType=“2”,所有写操作都随机的在writeHost、readhost分上发。
“readHost是从属于writeHost的,即意味着它从那个writeHost获取同步数据,因此,当它所属的writeHost宕机了,则它也不会再参与到读写分离中来,即“不工作了”,这是因为此时,它的数据已经“不可靠”了。基于这个考虑,目前mycat 1.3和1.4版本中,若想支持MySQL一主一从的标准配置,并且在主节点宕机的情况下,从节点还能读取数据,则需要在Mycat里配置为两个writeHost并设置banlance=1。”
(2) 设置 switchType="2" 与slaveThreshold="100"
switchType 目前有三种选择:
-1:表示不自动切换
1 :默认值,自动切换
2 :基于MySQL主从同步的状态决定是否切换
“Mycat心跳检查语句配置为 show slave status ,dataHost 上定义两个新属性: switchType="2" 与slaveThreshold="100",此时意味着开启MySQL主从复制状态绑定的读写分离与切换机制。Mycat心跳机制通过检测 show slave status 中的 "Seconds_Behind_Master", "Slave_IO_Running", "Slave_SQL_Running" 三个字段来确定当前主从同步的状态以及Seconds_Behind_Master主从复制时延。
保存配置文件并重新启动mycat。这样mycat便具有读写分离及分片功能了。
[root@taotao-mysql mycat]# bin/mycat restart
以上便是mycat主从复制和读写分离。