使用两个或两个以上的数据库,一部分数据库当作主数据库,而另外一部分数据库当作从数据库。系统在主数据库中进行写操做,从数据库记录在主库上全部的写操做,使得主从数据库的数据保持一致。mysql
一旦主数据库出现问题时,使用从数据库代替主数据库,能够避免服务中断。sql
读写分离是基于主从复制的。系统操做数据库中的数据时,将对数据的增删改也就是写操做,发送到主数据库,将查询的任务交给从数据库。docker
写操做通常相比读操做更耗时,而系统在大多数状况下都是读多写少。进行读写分离,减小读写操做相互影响,既能提升查询效率,也能减轻主数据库的压力,提升系统性能。数据库
下图为网上找的一张介绍主从复制的原理图。bash
简单来说,有如下四个关键点:网络
一、主数据库开启bin-log,将全部写操做的sql语句记录到日志文件中。异步
二、每当有从库链接到主库的时候,主库都会建立一个线程(master bin-log输出线程),用于发送bin-log内容到从库。ide
三、从数据库开启中继日志relay-log,用于同步回来的主数据库bin-log。性能
四、从数据库中运行2个线程,一个线程(slave I/O线程)链接到主库,获取主数据库bin-log日志文件里的SQL,记录到本机的中继日志relay-log文件里,另外一个线程(slave SQL线程)执行本机relay-log文件里的SQL语句,在从数据库从新执行一遍数据操做,保持主从数据库的数据一致。线程
异步复制
说明:MySQL默认的复制模式。主库在执行完客户端提交的事务后,当即将结果返回给客户端,而不等待从库接收处理。
问题:一旦主数据库宕机,已经提交的事务可能并无传到从数据库上,此时若是进行主备切换,会致使新主库上的数据不完整,牺牲了数据的一致性。
全同步复制
说明:当主库和从库执行完客户端提交的事务后,才返回结果给客户端。
问题:虽然保证了在任何状况下的数据一致性,当因为须要等待全部数据库执行完该事务才能返回结果,操做耗时长,牺牲了性能。
半同步复制
说明:主库在执行完客户端提交的事务后,等待至少一个从库接收到并写到中继日志后,才返回结果给客户端。
相对于异步复制和半同步复制,是保证数据一致性和性能的折中方案。须要注意的是,半同步须要等待从库响应,所以对于网络要求高,仅适用于低延时的网络。
下图为常见的主从复制的方案。
一主一从:从机能够做为数据的热备,当主节点宕机,备节点顶替。但须要注意的是,并不能代替数据备份,由于错误的操做,也会同步到备节点,数据仍会丢失。
一主多从:适用于读多写少的系统,但从库不可过多,过多会致使响应速度变慢。能够指定一个从库做为备用库,当主节点宕机,备节点顶替。也能够指定一个从库,将报表统计之类的慢查询语句都发到该从库,不至于影响其余查询操做。也能够指定一个从库,供开发人员排障使用,即便不当心删除数据,也不至于影响总体系统业务数据准确性,达到隔离效果。
双主:当大部分业务都为写,而写入性能还不够理想,能够采起双主模式。同时在两个主库写数据,并互相同步。业务上能够经过id取模、哈希计算等方法,奇数往主库1插数据,偶数往主库2插数据,保证主键不重复。
级联同步:为了减低主库的压力,主库只向一个从库同步数据,其余从库同步这个从库的数据。若是主库宕机,同步主库的从库能够直接做为主库使用。但若是这个从库挂了,问题会比较严重,会致使其余从库变为孤儿节点。
环形多主:性能强,但一旦挂了一个,会致使整个系统不可用。
如下演示使用Docker,搭建一主一从的数据库系统。
一、运行docker pull mysql:5.7
下载mysql镜像。
二、在/opt
目录下建立三个文件夹,分别为/opt/mysql_cluster
、/opt/mysql_cluster/master
和/opt/mysql_cluster/slave1
。其中master和slave1文件夹用于保存须要持久化到宿主机上mysql容器的数据文件、日志文件等。
三、在/opt/mysql_cluster/master
编写my.cnf文件,内容以下。须要注意的是,开启bin-log日志后默认记录全部库全部表的操做,能够经过配置来指定须要记录操做的数据库或者表,或指定不记录操做的数据库或者表。
[mysqld] #实例ID,不能和集群中的其余实例相同 server-id=1 #bin log 文件前缀 log-bin=mysql-prefix # 须要同步的数据库 binlog-do-db=tuling #不须要同步的数据库 binlog-ignore-db=information_schema binlog-ignore-db=mysql binlog-ignore-db=performance_schema binlog-ignore-db=test
四、在/opt/mysql_cluster/slave1
编写my.cnf文件,内容以下:
[mysqld] #实例ID,不能和集群中的其余实例相同 server-id=2 skip-slave-start=true #限定用户进行数据修改的操做 read_only=ON #中继日志前缀 relay-log=relay-bin
五、运行如下命令,启动主数据库。向外暴露的端口号为3307,默认的密码为123456,而且挂载宿主机目录到容器中,用于将数据保存到宿主机,保证数据不丢失。
docker run -p 3307:3306 --name mysql_master \-v /opt/mysql_cluster/master/conf:/etc/mysql \-v /opt/mysql_cluster/master/logs:/var/log/mysql \-v /opt/mysql_cluster/master/data:/var/lib/mysql \ -v /opt/mysql_cluster/master/my.cnf:/etc/my.cnf \-e MYSQL_ROOT_PASSWORD=123456 \-d mysql:5.7
六、运行docker exec -it mysql_master /bin/bash
,进入主数据库容器。
七、运行mysql -uroot -p
,输入密码,登陆数据库。
八、运行如下命令,添加访问权限,刷新受权表信息,方便后续在其余机器操做该数据库。
grant all privileges on *.* to root@'%' identified by "123456";flush privileges;
九、运行如下命令,添加主库复制帐号,刷新受权表信息。用户名和密码都是slave
。后续从库使用该帐号,获取相关bin-log。
CREATE USER 'slave'@'%' IDENTIFIED BY 'slave';GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%';flush privileges;
十、运行命令show master status;
,获取主库当前bin-log文件名(File)和位置(Position)。
十一、运行如下命令,启动从数据库。向外暴露的端口号为3308,默认的密码为123456,而且挂载宿主机目录到容器中,用于将数据保存到宿主机,保证数据不丢失。
docker run -p 3308:3306 -m 300M --memory-reservation 200M --name mysql_slave \-v /opt/mysql_cluster/slave1/conf:/etc/mysql \-v /opt/mysql_cluster/slave1/logs:/var/log/mysql \-v /opt/mysql_cluster/slave1/data:/var/lib/mysql \ -v /opt/mysql_cluster/slave1/my.cnf:/etc/my.cnf \-e MYSQL_ROOT_PASSWORD=123456 \-d mysql:5.7
十二、运行docker exec -it mysql_slave /bin/bash
,进入从数据库容器。
1三、运行mysql -uroot -p
,输入密码,登陆数据库。
1四、运行如下命令,添加访问权限,刷新受权表信息。方便后续在其余机器操做该数据库。
grant all privileges on *.* to root@'%' identified by "123456";flush privileges;
1五、运行如下命令,配置从库复制信息。其中,master_host
为docker宿主机的ip,master_user
和master_slave
为主库复制帐号,master_log_file
是主库运行命令show master status
获取的File
字段值,master_log_pos
为Position
字段值。master_port
为主数据库向外暴露的端口号。
change master to master_host='192.168.255.167',master_user='slave',master_password='slave',master_log_file='mysql-prefix.000004',master_log_pos=1824,master_port=3307;
1六、运行start slave;
,启动slave服务。
1七、运行show slave status\G;
,查看slave状态。当参数"Slave_IO_Running"和"Slave_SQL_Running"值都是Yes,主从配置完成。
1八、能够经过在主库建立表、插入修改数据后,查看从库是否同步成功,验证是否搭建成功。
1九、当须要从新配置主从时,能够在从库上运行如下两条命令,取消当前的主备复制。
stop slave;reset master;