在实际的生产环境中,如果对mysql数据库的读和写都在一台数据库服务器中操作,无论是在安全性、高可用性,还是高并发等各个方面都是不能满足实际需求的。因此,一般通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。
Mysql主从复制和读写分离
MySql自带主从复制(执行二进制文件的时候主从服务器之间同步会有延迟,但基本可以忽略不计(内网),而且主从复制也会有重试机制,如果备机拿不到主机二进制执行文件,备机会不断地重新连接,直到获取到文件),读写分离一般使用第三方(例如:sarding)
Maven:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
l 主从复制:
Mysql的主从复制和mysql的读写分离两者有紧密的联系,首先要部署主从复制,只有主从复制完成了,才能再此基础上进行数据的读写分离。
Mysql支持的复制类型:
1、 基于语句的复制:在主服务器上执行的sql语句,在从服务器上会执行同样的语句。Mysql默认采用基于语句的复制,效率比较高,但是有时不能实现精准复制。
2、 基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍。
3、 混合类型的复制:默认采用基于语句的复制,一旦发现基于语句的复制不能精准复制时,就会采用基于行的复制。
l 主从复制的过程:
1、 在每个事物更新数据完成之前,master在二进制日志记录这些改变,写入二进制日志完成后,master通知存储引擎提交事物。
2、 Slave将master的binary log复制到其中的中继日志。首先从mysql服务器开始一个工作线程I/O线程,I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master。他会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。
3、 Sql从线程处理该过程的最后一步。Sql线程从中继日志中读取事件,并重放其中的事件而更新slave的数据,使其与master的数据一致。
二 ································································································································································
主从复制的形式:
l 一主一从
l 主主复制(互为主从)
l 一主多从---扩展系统读取的性能,因为读是在从库读取的;
l 多主一从---从5.7开始支持
使用环境、用途、优点、缺点:
l 实时灾备,用于故障切换
l 热备份,避免影响业务
l mysql主从复制是mysql高可用性,高性能(负载均衡)的基础
l 简单,灵活,部署方式多样,可以根据不同业务场景部署不同结构
l 在业务复杂的系统中,有这么一个情景,有一句sql语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。
l 架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
l 复制过程中应该时刻监控复制状态,复制出错或延时可能给系统造成影响
l 如果单做主从复制,可能造成一定的资源浪费
l 主从复制并不是完美的架构,根据业务量或者其他因素的不同,可能会有各种误差出现
主从原理:
主从复制的基础是主库记录数据库的所有变更记录到binlog。binlog是数据库中保存配置中过期时间内所有修改数据库结构或内容的一个文件。如果过期时间是10d的话,那么就是最近10d的数据库修改记录。
mysql主从复制是一个异步的复制过程,主库发送更新事件到从库,从库读取更新记录,并执行更新记录,使得从库的内容与主库保持一致。在主库里,只要有更新事件出现,就会被依次地写入到binlog里面,是之后从库连接到主库时,从主库拉取过来进行复制操作的数据源。
binlog输出线程:每当有从库连接到主库的时候,主库都会创建一个线程然后发送binlog内容到从库。对于每一个即将发送给从库的sql事件,binlog输出线程会将其锁住。一旦该事件被线程读取完之后,该锁会被释放,即使在该事件完全发送到从库的时候,该锁也会被释放。
从库生成两个线程,一个I/O线程,一个SQL线程;
I/O线程:去请求主库 的binlog(二进制日志),并将得到的binlog日志写到relay log(中继日志) 文件中;主库会生成一个 log dump 线程,用来给从库 i/o线程传binlog;
SQL 线程:会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致;
大概步骤:
l 步骤一:主库db的更新事件(update、insert、delete)被写到binlog
l 步骤二:从库发起连接,连接到主库
l 步骤三:此时主库创建一个binlog dump thread,把binlog的内容发送到从库
l 步骤四:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log
l 步骤五:还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db