单台MySQL在安全性、高可用性和高并发性方面都无法满足实际的需求。配置多台主从数据库服务器以实现读写分离
一、主从复制原理
MySQL主从复制和MySQL的读写分离两者有着紧密的联系,首先要部署主从复制,只有主从复制完成了,才能在此基础上进行数据的读写分离。
1.1 MySQL支持的复制类型
基于语句的复制(STATEMENT) 在主服务器执行的SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率较高。 基于行的复制(ROW) 把改变的内容复制过去,而不是把命令在从服务器上执行一遍 混合类型的复制(MIXED) 默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
1.2 主从复制的工作过程
核心:两个日志,三个线程
两个日志:二进制日志、中继日志
三个线程:I/O、dump、sql
主从原理:Master将数据保存在二进制日志中,I/O向dump发出同步请求,dump把数据发送给I/O线程,I/O写入本地的中继日志数据,同步到自己数据库中,完成同步。
-
主MySQL服务器做的增删改操作吗,都会写入自己的二进制日志(Binary log)
-
然后从MySQL从服务器打开自己的I/O线程连接主服务器,进行读取主服务器的二进制日志
-
I/O去监听二进制日志,一旦有新的数据会发起请求连接
-
这时候会触发dump线程,dump thread响应请求,传送数据给I/O,通过tp的方式发送给I/O(dump 线程要么处于等待,要么处于休眠)
-
I/O接收到数据后存放于中继日志
-
SQL thread线程会读取中继日志里的数据,存放在自己的服务器中
-
在每个事务更新数据完成之后,Master在二进制日志(Binary log)记录这些改变。写入二进制日志完成后,Master通知存储引擎批叫事务。
-
Slave将Master复制到其中继日志(Relay log),首先Slave开启一个工作线程I/O,I/O线程在Master上打开一个普通的连接,然后开始Binlog dump process。Binlog dump process从Master二进制日志中读取事件,如果已经跟上Master,如果已经跟上Master他会睡眠并等待Master产生新的事件,I/O线程将这些事件写入从服务器的中继日志
-
SQL Slave thread(SQL 从线程)处理该过程的最后一步,SQL线程从中继日志中读取事件,并重新执行事件而更新Salve中的数据,使其与Master中的数据一致,只有该线程和I/O线程保持一致。
注: 中继日志通常会位于OS缓存中,所以中继日志的开销很小
复制过程有一个很重要的限制,所有复制操作都是串行化的,也就是说在Master上的并行更新操作不能在Slave上并行操作
1.3 MySQL四种同步方式
MySQL有四种同步方式:
-
同步复制
-
半同步复制
-
异步复制
-
增强半同步复制、无损复制
同步复制:
主库将更新写入Binlog日志文件后,需要等待数据更新已经复制到从库中,并且已经在从库中执行成功,然后才能返回继续处理其他请求。同步复制提供了最佳安全性,保证数据安全,数据不会丢失,但对性能有一定的影响。
半同步复制:
写入一条数据到Master,从服务器只要有一台收到写入自己的中继日志,会给客户端返回一条接收成功的信息。 主服务器提交更新写入二进制日志文件后,等待数据更新写入了从服务器中继日志后,然后才能再继续处理其他请求。该功能确保至少有一个从服务器接收完主服务传递过来的binlog内容写入到自己的中继日志中,然后才能继续处理其他请求。 半同步复制在最近性能和最佳安全性之间的一个折中。
MySQL 5.5版本之后引入的半同步复制功能,主从服务器必须安装半同步复制插件,才能开启该复制功能。如果等待超时,超过rpl_semi_sync_master_timeout参数设置的时间(默认值10000,即10秒),则关闭半同步复制,并自动转换为异步复制模式。当Master dump线程发送完一个事务的所有事件之后,如果在rpl_semi_sync_master_timeout内,收到了从库的响应,则主从又恢复为半同步复制。
会出现的问题:幻读
异步复制:
主库将更新写入Binlog日志文件后,不需要等待数据更新是否已经复制奥从库中,就可以继续处理更多的请求。如果Master宕机,事务在Master上已经提交,但很可能这些事务没有传到Slave。假设有Master->Slave故障转移的机制,此时Slave也可能丢失事务。MySQL复制默认是异步复制,异步复制提供了最佳性能
增强半同步复制、无损复制:
Master将每个事务写入binlog,传递给slave刷新到磁盘(中继日志relaylog),master等待slave反馈接收到relaylog的ack之后,再在引擎层提交事务并返回commit OK结果给客户端。即使主库 宕机,所有主库上已经提交的事务都能保证已经同步到从库的relaylog中
二、读写分离原理
读写分离就是只在主服务上写,只在从服务器上读。基本的原理就是主服务器处理事务性操作,而从服务器处理select查询。数据库的复制被用来把主服务器上事务性操作导致的变更同步到集群中的从服务器。
2.1 什么事读写分离
读写分离,基本原理就是让主服务器处理事务性增、删、改操作(INSERT、UPDATE、DELETE),而从服务器处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从服务器。
2.2 为什么要读写分离
因为数据库的“写”(写10000条数据 可能需要3分钟)操作比较耗时 但是数据库的“读”(读10000条数据可能需要5秒)操作很快 所以读写分离,解决的是数据库的写入影响了查询效率问题
2.3 什么时候读写分离
数据库不一定要读写分离,如果程序使用数据库更新少、查询多的情况下可以考虑使用。主要利用数据主从同步,再通过读写分离来分担数据库压力,提高性能。
2.4 主从复制和读写分离
在实际的生产环境中,数据库的读和写都在同一个数据库服务器中,是无法满足实际需求的。无论是安全性、高可用性还是高并发等各个方面都是完全不能满足需求的。因此,通过主从复制方式来同步数据,再通过读写分离来提高数据的鬓发负载能力。有点类似于rsync,但是不同的是rsync是对磁盘文件做备份,而主从复制是对数据库中的数据、语句做备份。
2.5 读写分离类型
2.5.1 基于程序代码内部实现
2.5.2 基于中间代理层实现
-
MySQL-Proxy
-
Atlas
-
Amoeba
三、主从复制延迟
-
Master服务器高并发,形成大量事务
-
网络延迟
-
主从硬件设备导致
-
不是同步复制,而是异步复制