Mysql主从架构的搭建
一、主从架构原理讲解
熟悉MySQL数据库常见的主从架构
理解MySQL主从架构的实现原理
掌握MySQL主从架构的搭建
1.1 集群概述
什么是集群?
简单地说,集群 就是指一组(若干个)相互独立的计算机,利用高速通信网络组成的一个较大的 计算机服务系统,每个集群节点(即集群中的每台计算机)都是运行各自服务的独立服务器。这些服务器之间可以彼此通信,协同向用户提供应用程序,系统资源和数据,并以单一系统的模式加以管理。当用户请求集群系统时,集群给用户的感觉就是一个单一独立的服务器,而实际上用户请求的是一组集群服务器。
打开谷歌,百度的页面,看起来好简单,也许你觉得用几分钟就可以制作出相似的网页,而实际上,这个页面的背后是由成千上万台服务器集群协同工作的结果。

若要用一句话描述集群,即一堆服务器合作做同一件事,这些机器可能需要统一协调管理,可以分布在一个机房,也可以分布在全国全球各个地区的多个机房。
为什么要使用集群?
一些国家重要的计算密集型应用(如 天气预报,核试验模拟 等),需要计算机有很强的运算处理能力。以全世界现有的技术,即使是大型机器,其计算能力也是有限的,很难单独完成此任务。因为计算时间可能会相当长,也许几天,甚至几年或更久。因此,对于这类复杂的计算业务,便使用了计算机集群技术,集中几十上百台,甚至成千上万台计算机进行计算。

假如你配一个 LNMP 环境,每次只需要服务 10 个并发请求,那么单台服务器一定会比多个服务器集群要快。
只有当并发或总请求数量超过单台服务器的承受能力时,服务器集群才会体现出优势。
通常一套系统集群架构,只需要几台或数十台服务器主机即可。与动辄价值上百万元的专用超级计算机相比便宜了很多。在达到同样性能需求的条件下,采用计算机集群架构比采用同等运算能力的大型计算机具有更高的性价比。
早期的淘宝,支付宝的数据库等核心系统就是使用上百万元的小型机服务器。后因使用维护成本太高以及扩展设备费用成几何级数翻倍,甚至成为扩展瓶颈,人员维护也十分困难,最终使用 PC 服务器集群替换之,比如,把数据库系统从小机结合 Oracle 数据库迁移到 MySQL 开源数据库结合 PC 服务器上来。不但成本下降了,扩展和维护也更容易了。
当服务负载,压力增长时,针对集群系统进行较简单的扩展即可满足需求,且不会降低服务质量。
通常情况下,硬件设备若想扩展性能,不得不增加新的 CPU 和存储器设备,如果加不上去了,就不得不购买更高性能的服务器,就拿我们现在的服务器来讲,可以增加的设备总是有限的。如果采用集群技术,则只需要将新的单个服务器加入现有集群架构中即可,从访问的客户角度来看,系统服务无论是连续性还是性能上都几乎没有变化,系统在不知不觉中完成了升级,加大了访问能力,轻松地实现了扩展。集群系统中的节点数目可以增长到几千乃至上万个,其伸缩性远超过单台超级计算机。
单一的计算机系统总会面临设备损毁的问题,如 CPU,内存,主板,电源,硬盘等,只要一个部件坏掉,这个计算机系统就可能会宕机,无法正常提供服务。在集群系统中,尽管部分硬件和软件还是会发生故障,但整个系统的服务可以是 7 × 24 7×247×24 小时可用的。
集群架构技术可以使得系统在若干硬件设备故障发生时仍可以继续工作,这样就将系统的停机时间减少到了最小。集群系统在提高系统可靠性的同时,也大大减小了系统故障带来的业务损失,目前几乎 100 % 的互联网网站都要求 7 × 24 小时提供服务。
集群的主要类型
计算机集群架构按功能和结构可以分成以下几类:
负载均衡集群,简称
LBC或者LB高可用性集群,简称
HAC高性能计算集群,简称
HPC网格计算集群
提示:负载均衡集群 和 高可用性集群 是互联网行业常用的集群架构模式,也是我们要学习的重点。
负载均衡集群
负载均衡集群 为企业提供了更为实用,性价比更高的系统架构解决方案。
负载均衡集群可以把很多客户集中的访问请求负载压力尽可能平均地分摊在计算机集群中处理。
客户访问请求负载通常包括应用程序处理负载和网络流量负载。
这样的系统非常适合使用同一组应用程序为大量用户提供服务的模式,每个节点都可以承担一定的访问请求负载压力,并且可以实现访问请求在各节点之间动态分配,以实现负载均衡。
负载均衡集群运行时,一般是通过一个或多个前端负载均衡器将客户访问请求分发到后端的一组服务器上,从而达到整个系统的高性能和高可用性。
一般高可用性集群和负载均衡集群会使用类似的技术,或同时具有高可用性与负载均衡的特点。
负载均衡集群的作用为:
分摊用户访问请求及数据流量(负载均衡)。
保持业务连续性,即 7 × 24 7×247×24 小时服务(高可用性)。
应用于 Web 及数据库等服务器的业务。
负载均衡集群典型的开源软件包括 LVS,Nginx,Haproxy 等。

高可用性集群
一般是指在集群中任意一个节点失效的情况下,该节点上的所有任务会自动转移到其他正常的节点上。此过程并不影响整个集群的运行。
当集群中的一个节点系统发生故障时,运行者的集群服务会迅速作出反应,将该系统的服务分配到集群中其他正在工作的系统上运行。
考虑到计算机硬件和软件的容错性,高可用性集群的主要目的是使集群的整体服务尽可能可用。
如果高可用性集群中的主节点发生了故障,那么这段时间内将由备份节点代替它。备节点通常是主节点的镜像。
当它代替主节点时,它可以完全接管主节点(包括 IP 地址及其他资源)提供服务,因此,使集群系统环境对于用户来说是一致的,即不会影响用户的访问。
高可用性集群使服务器系统的运行速度和响应速度会尽可能的快。他们经常利用在多台机器上运行的冗余节点和服务器来相互跟踪。
如果某个节点失败,它的替补者将在几秒钟或更短时间内接管它的职责。因此,对于用户而言,集群里的任意一台机器宕机,业务都不会受影响(理论情况下)。
高可用性集群的作用为:
当一台机器宕机时,另外一台机器接管宕机的机器的IP资源和服务资源,提供服务。
常用于不易实现负载均衡的应用,比如负载均衡器,主数据库,主存储对之间。
高可用性集群常用的开源软件包括 Keepalived,Heartbeat 等,其架构图如下图所示:

如何衡量高可用
| 可用性级别(指标) | 年度宕机时间 | 描述 | 叫法 |
|---|---|---|---|
| 99% | 3.65天/年 | 基本可用系统 | 2个9 |
| 99.9% | 8.76小时/年 | 可用系统 | 3个9 |
| 99.99% | 52.6分钟/年 | 高可用系统 | 4个9 |
| 99.999% | 5.3分钟/年 | 抗故障系统 | 5个9 |
| 99.9999% | 32秒/年 | 容错系统 | 6个9 |
计算方法:
1年 = 365天 = 8760小时 99% = 8760 * 1% = 8760 * 0.01 = 87.6小时 = 3.65天 99.9% = 8760 * 0.1% = 8760 * 0.001 = 8.76小时 99.99% = 8760 * 0.01% = 8760 * 0.0001 = 0.876小时 = 0.876 * 60 = 52.6分钟 99.999% = 8760 * 0.001% = 8760 * 0.00001 = 0.0876小时 = 0.0876 * 60 = 5.26分钟
常用的集群架构
MySQL Replication
MySQL Replication一主多从的结构,主要目的是实现数据的多点备份(没有故障自动转移和负载均衡)。相比于单个的mysql,一主多从下的优势如下:
如果让后台读操作连接从数据库,让写操作连接主数据库,能起到读写分离的作用,这个时候多个从数据库可以做负载均衡。
可以在某个从数据库中暂时中断复制进程,来备份数据,从而不影响主数据的对外服务(如果在master上执行backup,需要让master处于readonly状态,这也意味这所有的write请求需要阻塞)。
就各个集群方案来说,其优势为:
主从复制是mysql自带的,无需借助第三方。
数据被删除,可以从binlog日志中恢复。
配置较为简单方便。
其劣势为:
从库要从binlog获取数据并重放,这肯定与主库写入数据存在时间延迟,因此从库的数据总是要滞后主库。
对主库与从库之间的网络延迟要求较高,若网络延迟太高,将加重上述的滞后,造成最终数据的不一致。
单一的主节点挂了,将不能对外提供写服务。
MySQL Cluster
MySQL Cluster是多主多从结构的
就各个集群方案来说,其优势为:
mysql官方提供的工具,无需第三方插件。
高可用性优秀,99.999%的可用性,可以自动切分数据,能跨节点冗余数据(其数据集并不是存储某个特定的MySQL实例上,而是被分布在多个Data Nodes中,即一个table的数据可能被分散在多个物理节点上,任何数据都会在多个Data Nodes上冗余备份。任何一个数据变更操作,都将在一组Data Nodes上同步,以保证数据的一致性)。
可伸缩性优秀,能自动切分数据,方便数据库的水平拓展。
负载均衡优秀,可同时用于读操作、写操作都都密集的应用,也可以使用SQL和NOSQL接口访问数据。
多个主节点,没有单点故障的问题,节点故障恢复通常小于1秒。
其劣势为:
架构模式和原理很复杂。
只能使用存储引擎 NDB ,与平常使用的InnoDB 有很多明显的差距。比如在事务(其事务隔离级别只支持Read Committed,即一个事务在提交前,查询不到在事务内所做的修改),外键(虽然最新的NDB 存储引擎已经支持外键,但性能有问题,因为外键所关联的记录可能在别的分片节点),表限制上的不同,可能会导致日常开发出现意外。
作为分布式的数据库系统,各个节点之间存在大量的数据通讯,比如所有访问都是需要经过超过一个节点(至少有一个 SQL Node和一个 NDB Node)才能完成,因此对节点之间的内部互联网络带宽要求高。
Data Node数据会被尽量放在内存中,对内存要求大,而且重启的时候,数据节点将数据load到内存需要很长时间。
MySQL Fabirc
这是在MySQL Replication的基础上,增加了故障检测与转移,自动数据分片功能。不过依旧是一主多从的结构,MySQL Fabirc只有一个主节点,区别是当该主节点挂了以后,会从从节点中选择一个来当主节点。
就各个集群方案来说,其优势为:
mysql官方提供的工具,无需第三方插件。
数据被删除,可以从binlog日志中恢复。
主节点挂了以后,能够自动从从节点中选择一个来当主节点,不影响持续对外提供写服务。
其劣势为:
从库要从binlog获取数据并重放,这肯定与主库写入数据存在时间延迟,因此从库的数据总是要滞后主库。
对主库与从库之间的网络延迟要求较高,若网络延迟太高,将加重上述的滞后,造成最终数据的不一致。
2014年5月推出的产品,数据库资历较浅,应用案例不多,网上各种资料相对较少。
事务及查询只支持在同一个分片内,事务中更新的数据不能跨分片,查询语句返回的数据也不能跨分片。
节点故障恢复30秒或更长(采用InnoDB存储引擎的都这样)。
MHA [Keepalived | HeartBeat | LVS,HAProxy等技术构建高可用集群]
MHA(Master High Availability)是多主多从结构,这是日本DeNA公司的youshimaton开发,主要提供更多的主节点,但是缺少VIP(虚拟IP),需要配合keepalived等一起使用。
要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库。

就各个集群方案来说,其优势为:
可以进行故障的自动检测和转移
具备自动数据补偿能力,在主库异常崩溃时能够最大程度的保证数据的一致性。
其劣势为:
MHA架构实现读写分离,最佳实践是在应用开发设计时提前规划读写分离事宜,在使用时设置两个连接池,即读连接池与写连接池,也可以选择折中方案即引入SQL Proxy。但无论如何都需要改动代码;
关于读负载均衡可以使用F5、LVS、HAPROXY或者SQL Proxy等工具,只要能实现负载均衡、故障检查及备升级为主后的读写剥离功能即可,建议使用LVS
总结
集群的好处
高可用性:故障检测及迁移,多节点备份。
可伸缩性:新增数据库节点便利,方便扩容。
负载均衡:切换某服务访问某节点,分摊单个节点的数据库压力。
集群要考虑的风险
网络分裂:群集还可能由于网络故障而拆分为多个部分,每部分内的节点相互连接,但各部分之间的节点失去连接。
脑裂:导致数据库节点彼此独立运行的集群故障称为“脑裂”。这种情况可能导致数据不一致,并且无法修复,例如当两个数据库节点独立更新同一表上的同一行时。
1.2 MySQL复制
什么是MySQL复制
Replication可以实现将数据从一台数据库服务器(master)复制到一台到多台数据库服务器(slave)
默认情况下,属于异步复制,所以无需维持长连接
MySQL复制原理
主从复制是通过重放binlog实现主库数据的异步复制。即当主库执行了一条sql命令,那么在从库同样的执行一遍,从而达到主从复制的效果。
在这个过程中,master对数据的写操作记入二进制日志文件中(binlog),生成一个 log dump 线程,用来给从库的 i/o线程传binlog。
而从库的i/o线程去请求主库的binlog,并将得到的binlog日志写到中继日志(relaylog)中,从库的sql线程,会读取relaylog文件中的日志,并解析成具体操作,通过主从的操作一致,而达到最终数据一致。

当主从同步配置完毕后:
slave端的IO线程发送请求给master端的binlogdump线程
master端binlogdump线程获取二进制日志信息(文件名和位置信息)发送给slave端的IO线程
slave端IO线程获取到的内容依次写到slave端relay log(中继日志)里,并把master端的bin-log文件名和位置记录到master.info里
slave端的SQL线程,检测到relaylog中内容更新,就会解析relaylog里更新的内容,并执行这些操作,从而达到和master数据一致
relaylog中继日志
作用:记录从(slave)服务器接收来自主(master)服务器的二进制日志
场景:用于主从复制
master主服务器将自己的二进制日志发送给slave从服务器,slave先保存在自己的中继日志中然后再执行自己本地的relaylog里的sql达到数据库更改和master保持一致。
如何开启relaylog?
默认中继日志没有开启,可以通过修改配置文件完成开启,如下:
vim my.cnf
[mysqld]
# 指定二进制日志存放位置及文件名
relay-log=/mysql_3306/data/relaylog
MySQL复制架构
一主多从复制架构
在主库读取请求压力非常大的场景下,可以通过配置一主多从复制架构实现读写分离,把大量的对实时性要求不是特别高的读请求通过负载均衡分部到多个从库上(对于实时性要求很高的读请求可以让从主库去读),降低主库的读取压力,如下图所示。
在主库出现异常宕机的情况下,可以把一个从库切换为主库继续提供服务。
默认情况下,master接受读写请求,slave只接受读请求以减轻master的压力。

多级复制架构
一主多从的架构能够解决大部分读请求压力特别大的的场景的需求,考虑到MySQL的复制需要主库发送BINLOG日志到从库的I/O线程,主库的I/O压力和网络压力会随着从库的增加而增长(每个从库都会在主库上有一个独立的BINLOG Dump线程来发送事件),而多级复制架构解决了一主多从场景下的,主库额外的I/O和网络压力。
MySQL的多级复制架构如下图所示。

对比一主多从的架构,多级复制仅仅是在主库Master1复制到从库Slave1、Slave2、Slave3的中间增加了一个二级主库Master2,这样,主库Master1只需要给一个从库Master2发送BINLOG日志即可,减轻了主库Master1的压力。二级主库Master2再发送BINLOG日志给所有的从库Slave1、Slave2和Slave3的I/O线程。
多级复制解决了一主多从场景下,主库的I/O负载和网络压力,当然也有缺点:MySQL的传统复制是异步的,多级复制场景下主库的数据是经历两次复制才到达从库Slave1、Slave2、Slave3的,期间的延迟要比一主多从复制场景下只经历一次复制的还大。
双主复制架构
双主(Dual Master)复制架构适用于DBA做维护时需要主从切换的场景,通过双主复制架构避免了重复搭建从库的麻烦,双主复制架构如下图所示。

主库Master1和Master互为主从,所有Web Client的写请求都访问主库Master1或Master2。加入,DBA需要做日常维护操作,为了避免影响服务,需进行一下操作。
首先,在Master1库上停止Slave线程(STOP SLAVE),避免后续对Master2库的维护操作操作被实时复制到Master1库上对服务造成影响。
其次,在Master2库上停止Slave线程(STOP SLAVE),开始日常维护操作,例如修改varchar字段从长度10增加到200。
然后,在Master2库上完成维护操作之后,打开Master2库上的Slave线程(STRART SLAVE),让Master2的数据和Master1库同步,同步完成后,把应用的写操作切换到Master2库上。
最后,确认Master1库上没有应用访问后,打开Master1的Slave线程(START SLAVE)即可。
通过双主复制架构能够大大减轻一主多从架构下对主库进行维护带来的额外搭建从库的工作。
当然双主架构还能和主从复制联合起来使用:在Master2库下配置从库Slave1、Slave2等,这样既可通过从库Slave1等来分担读取压力,同时在DBA做维护的同时,避免了重建从库的额外工作,但需要注意从库的复制延迟。MySQL双主多级复制架构如下所示。

二、搭建操作讲解
2.1 搭建
第一步:克隆一台虚拟机
第二步:编辑my.cnf配置文件
vim /etc/my.cnf-- 添加进去,两台虚拟机都要
server_id=2
log-bin=/var/lib/mysql/binlog-- 这条语句添加在你的从虚拟机上
relay-log=/var/lib/mysgl/relaylog注意:
server_id 要不一致第三步:将克隆的虚拟机的auto.cnf文件删除
cd /var/lib/mysqlllrm -rf auto.cnf第四步:关闭防火墙和管家
systemctl stop firewalldsetenforce 0第五步:写入参数 - 可写也可不写
vim /etc/my.cnf# 0表示读写 (主机),1表示只读(从机)
read-only=0# 设置日志文件保留的时长,单位是秒
binlog_expire_logs_seconds=6000# 控制单个二进制日志大小。此参数的最大和默认值是1GB
max_binlog_size=20# 设置不要复制的数据库
binlog-ignore-db=test# 设置需要复制的数据库,不写参数则默认全部记录,可以填写多个
binlog-do-db=需要复制的主数据库名字
例如:
binlog-do-db=dbtest01
binlog-do-db=dbtest02第六步:更改mysql密码写入难度
vim /etc/my.cnfvalidate_password.policy=LOW
validate_password.length=6
validate_password.number_count=1
validate_password.special_char_count=1
validate_password.mixed_case_count=1-- 修改后要重启mysql
systemctl restart mysqld第七步:创建普通用户
mysql -uroot -p-- 创建普通用户
create user 'slave'@'%' identified by '123456';-- 授权(可以主从复制的权限)
grant replication slave on *.* to 'slave'@'%';-- 使用mysql_native_password插件认证(密码加密方式)
alter user 'slave'@'%' identified with mysql_native_password by '123456';-- 刷新
flush privileges;第八步:查看从服务器是从哪个bin-log文件复制的
-- 退出使用创建的用户登录
mysql -uslave -p-- 这里需要root登录mysql,slave权限不够
mysql> show master status;-- 例子
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000003 | 1364 | | | |
+---------------+----------+--------------+------------------+-------------------+第九步:指定主服务器(这里切换到从服务器执行)
change master to master_host='192.168.66.143', master_user='slave',master_password='123456', master_port=3306, master_log_file='binlog.000003', master_log_pos=1364;第十步:启动主从(这里也是从服务器)
start slave-- 查询从服务器状态
show slave status\G; 注释:
\G(格式化)注意这里:要两个yes
第一个是是否连上主服务器
第二个表示主服务器代码是否执行成功

2.2 测试
回到主服务器
-- 创建一个数据库
create database test;-- 回到从服务器
show databases;出现了一个数据库为test就主从搭建好了2.3 主从问题修复
-- 将主服务器打包到从服务器
scp -r /var/lib/mysql root@从服务器ip:/var/lib
