随着技术的发展,在实际的生产环境中,由单台MySQL数据库服务器不能满足实际的需求。此时数据库集群就很好的解决了这个问题。采用MySQL分布式集群,能够搭建一个高并发、负载均衡的集群服务器。在此之前我们必须要保证每台MySQL服务器里的数据同步。数据同步我们可以通过MySQL内部配置就可以轻松完成,主要有主从复制和主主复制。
MySQL数据库自身提供的主从复制功能可以方便的实现数据的多处自动备份,实现数据库的拓展。多个数据备份不仅可以加强数据的安全性,通过实现读写分离还能进一步提升数据库的负载性能。
下图就描述了一个多个数据库间主从复制与读写分离的模型(来源网络):
在一主多从的数据库体系中,多个从服务器采用异步的方式更新主数据库的变化,业务服务器在执行写或者相关修改数据库的操作是在主服务器上进行的,读操作则是在各从服务器上进行。如果配置了多个从服务器或者多个主服务器又涉及到相应的负载均衡问题,关于负载均衡具体的技术细节还没有研究过,今天就先简单的实现一主一从的主从复制功能。
MySQL的主从复制是一个异步的复制过程(虽然一般情况下感觉是实时的),数据将从一个MySQL数据库(Master)复制到另一个MySQL数据库(Slave),在Master和Slave之间实现整个主从复制的过程是由三个线程参与完成的。其中两个线程(SQL线程和IO线程)在Slave端,另一个线程(I/O线程)在Master端。
要实现MySQL的主从复制,首先必须打开Master端的binlog记录功能,否则就无法实现。binlog: binary log,是主库中保存所有更新事件日志的二进制文件。因为整个复制过程实际上就是Slave从Master端获取binlog日志,然后在Slave上以相同顺序执行获取的binlog日志中的记录的各种SQL操作。
我们根据上图来分析一下整个主从复制的过程:
(1)在Slave服务器上执行start slave命令开启主从复制开关,开始进行主从复制。
(2)此时,Slave服务器的IO线程会通过在master上已经授权的复制用户权限请求连接Master服务器,并请求从执行binlog日志文件中的指定位置(日志文件名和位置就是在配置主从复制服务时执行change master命令指定的)之后开始发送binlog日志内容。
(3)Master服务器接收来自Slave服务器的IO线程的请求后,其上负责复制的IO线程会根据Slave服务器的IO线程请求的信息分批读取指定binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的IO线程。返回的信息中除了binlog日志内容外,还有在Master服务器端记录的IO线程。返回的信息中除了binlog中的下一个指定更新位置。
(4)当Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件(Mysql-relay-bin.xxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容
(5)Slave服务器端的SQL线程会实时检测本地Relay Log 中IO线程新增的日志内容,然后及时把Relay LOG 文件中的内容解析成sql语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行应用这样sql语句,并在relay-log.info中记录当前应用中继日志的文件名和位置点
延时
主从同步延迟原理和解决方案:
https://www.cnblogs.com/cnmenglang/p/6393769.html
注意:MySQL版本号最好一致,为了方便学习测试,建议关闭防火墙
我的mysql安装过程是在一台虚拟机上安装好MySQL后,克隆虚拟机得到的两个环境,所以在后面会报一个错:Fatal error: The slave I/O thread stops because master and slave have equal MySQL server
原因是:mysql 5.6的复制引入了uuid的概念,各个复制结构中的server_uuid得保证不一样,但是查看到直接copy data文件夹后server_uuid是相同的,show variables like ‘%server_uuid%’;
解决方法:
mysql 5.6的复制引入了uuid的概念,各个复制结构中的server_uuid得保证不一样,但是查看到server_uuid是相同的,
show variables like '%server_uuid%';
找到/var/lib/mysql文件夹下的auto.cnf文件,修改里面的uuid值,保证各个db的uuid不一样,重启db即可
systemctl restart mysqld.service
https://blog.csdn.net/cug_jiang126com/article/details/46846031
MySQL的主从复制并不完美,存在着几个由来已久的问题,首先一个问题是复制方式:
基于SQL语句的方式是最古老的方式,也是目前默认的复制方式,后来的三种是MySQL 5以后才出现的复制方式。
SBR的优点
SBR的缺点:
RBR的优点
RBR 的缺点:
混合方式就是有mysql自动选择RBR方式和SBR方式,能够充分发挥两种方式的优点,一般情况下都使用该种方式实现主从复制
这种方式虽然能够大大提高主从复制的效率,减小主从复制的延时,但也存在问题,具体请参看下面的博客。
https://blog.csdn.net/guotao521/article/details/45483833
http://hamilton.duapp.com/detail?articleId=47
开启二进制日志 binlog
配置唯一的server-id
获得master二进制文件名及位置
创建一个用于slave和master通信的用户账号
配置唯一的server-id
使用master分配的用户账号读取master二进制日志
启动slave服务
主数据库
的配置文件my.cnf(或者my.ini),我的在/etc/my.cnf,在[mysqld]部分插入如下:[mysqld]
#开启二进制日志
log-bin=mysql-bin
#设置server-id,建议使用ip最后3位
server-id=140
从数据库
的配置文件my.cnf(或者my.ini),我的在/etc/my.cnf,在[mysqld]部分插入如下:#开启中继日志
relay-log=mysql-relay
#设置server-id,建议使用ip最后3位
server-id=141
systemctl restart mysqld.service
GRANT REPLICATION SLAVE ON *.* TO 'mysql141'@'192.168.131.141' IDENTIFIED BY 'mysql141';
flush privileges;
--查询master的状态
show master status\G
记录上图结果中File和Position的值。
注意:执行完此步骤后不要再操作主服务器MySQL,防止主服务器状态发生状态值变化。
这里要根据上面主服务器的状态来填写,不要直接用下面的SQL,需要根据实际值修改。
CHANGE MASTER TO master_host = '192.168.131.140',
master_user = 'mysql141',
master_password = 'mysql141',
master_log_file = 'mysql-bin.000001',
master_log_pos = 120;
//开启复制
start slave;
//查看主从复制是否配置成功
SHOW SLAVE STATUS\G
当看到Slave_IO_State:Waiting for master ot send event 、Slave_IO_Running: YES、Slave_SQL_Running: YES才表明状态正常。
SHOW DATABASES;
create database test;
use test;
create table tab1(id int auto_increment,name varchar(10),primary key(id));
insert into tab1(id,name) values (1,'why');
至此,MySQL主从复制就实现了。
show master status: 查看master的状态,尤其是当前的日志及位置
show slave status 查看slave的状态
reset slave 重置slave状态
start slave 启动slave状态
stop slave 暂停slave状态
绝大多数的企业的应用场景对于数据库来说都是读多写少,比如微博,明星发一条微博,上千万人读。所以为了分担数据库压力,做负载均衡,首先考虑到的就是读写分离,读写分离基于上面实现的主从复制,使用主库作为写库,从库为读库,提高数据库性能,提高IO性能。
为了实现读写分离,出现了很多解决方案,其中比较流行的是采用中间件做为Proxy,保持应用层代码不随数据库的变动而发生变化,这里包括Amoeba、Atlas、Cobar、Mycat、MySQL Proxy等,而Mycat是目前开源的数据库中间件中比较成熟的解决方案。可以说Mycat真的非常强大,但是建议慎重考虑使用,具体原因请自行百度mycat发起人和Mycat社区现状。
但我们以学习的目的进行使用还是非常好的,Mycat确实非常强大,我们可以学习他的思想和技术。所以我们使用Mycat中间件作为读写分离的实现方式。
《Mycat权威指南》和《分布式数据库架构及企业实践-基于mycat中间件》两本书都介绍的非常详细。
原文链接:https://www.cnblogs.com/joylee/p/7513038.html
Mycat官网:http://www.mycat.io/
可以了解下Mycat的背景和应用情况,这样使用起来比较有信心。
Mycat下载地址:http://dl.mycat.io/
官网有个文档,属于详细的介绍,初次入门,看起来比较花时间。
下载:
建议大家选择 1.6-RELEASE 版本,毕竟是比较稳定的版本。
安装:
根据不同的系统选择不同的版本。包括linux、windows、mac,作者考虑还是非常周全的,当然,也有源码版的。
Mycat的安装其实只要解压下载的目录就可以了,非常简单。
安装完成后,目录如下:
目录 | 说明 |
---|---|
bin | mycat命令,启动、重启、停止等 |
catlet | catlet为Mycat的一个扩展功能 |
conf | Mycat 配置信息,重点关注 |
lib | Mycat引用的jar包,Mycat是java开发的 |
logs | 日志文件,包括Mycat启动的日志和运行的日志。 |
配置
Mycat的配置文件都在conf目录里面,这里介绍几个常用的文件:
文件 | 说明 |
---|---|
server.xml | Mycat的配置文件,设置账号、参数等 |
schema.xml | Mycat对应的物理数据库和数据库表的配置 |
rule.xml | Mycat分片(分库分表)规则 |
Mycat的架构其实很好理解,Mycat是代理,Mycat后面就是物理数据库。和Web服务器的Nginx类似。对于使用者来说,访问的都是Mycat,不会接触到后端的数据库。
我们现在做一个主从、读写分离,简单分表的示例。结构如下图:
Mycat作为主数据库中间件,肯定是与代码弱关联的,所以代码是不用修改的,使用Mycat后,连接数据库是不变的,默认端口是8066。连接方式和普通数据库一样,如:jdbc:mysql://192.168.0.2:8066/。
我们只针对mycat实现简单的读写分离,更多其他特性如分库分表切片的功能请参看上面推荐的书,这里只针对简单的读写分离的配置。
我们真实的物理数据库名称为 itoo_cloud
,包含一个表 ta_user
,以免大家对后面的配置不明白。
<user name="root">
<property name="password">rootproperty>
<property name="schemas">itooproperty>
<property name="readOnly">falseproperty>
user>
重点关注下面这段,其他默认即可
我这里配置了一个账号root密码也是root,针对逻辑数据库itoo(自己定义别名,不是真实的物理数据库),读写权限都有,没有针对表做任何特殊的权限。
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="itoo" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"/>
<dataNode name="dn1" dataHost="auth" database="itoo_cloud" />
<dataHost name="auth" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()heartbeat>
<writeHost host="hostM" url="192.168.131.140:3306" user="root" password="root">
<readHost host="hostS1" url="192.168.131.141:3306" user="test" password="test" />
writeHost>
dataHost>
mycat:schema>
注意:读库的用户test是添加的mysql用户,只具有读权限的用户:
GRANT Select ON *.* TO 'test'@'%' IDENTIFIED BY "test"
Mycat的启动也非常简单,进入到bin目录下:
##启动
./mycat start
##停止
./mycat stop
##重启
./mycat restart
如果在启动时发现异常,在logs目录中查看日志。
mycat启动后,执行命令不成功,可能实际上配置有错误,导致后面的命令没有很好的执行。
使用navicat连接mycat,如下图所示,注意端口为8066。