再谈binlog
mysql的高可用架构都是基于binlog来实现的,binog是归档所用,主要两种格式,分别是statements和rows格式,两个格式的区别如下:
-
statements
该格式下的binlog记录的是我们直接执行的语句,比如执行
delete * from t where id = 1;
这是产生的binlog记录的就是这条执行的语句。但是这类binlog存在一个问题就是我们的语句在主库和从库中有可能会通过不同的索引执行,这样就可能会导致主库和从库的不一致性
-
rows
该格式下的binlog记录的是我们对哪个表的哪一行做了什么样的修改,比如上面的那条delete语句,在生成rows格式的binlog时就是记录了删除表t的id=1的行。这种格式的binlog记录的信息更加完整。
M-S架构实现
所谓的MS架构就是主备架构,一个主库A可以用来读写,一个从库B只能接受客户端的读请求,并与主库A保持同步,B要与A保持同步的步骤如下:
-
备库B设置主库A的相关属性
-
备库B上执行start slave命令,然后会开启两个线程,一个线程用来接受主库A的binlog,一个线程用来写relay log
-
主库A在进行一些校验后,开始按照备库B传过来的位置,从本地读取binlog,发送给从库B
-
从库B在接受到主库A传来的binlog后会将其转换为relay log,称为中转日志
-
从库B后台线程读取中转日志后解析其中的命令并执行
M-M架构实现
所谓的M-M架构就是两个库互为主从,也就是说A是B的主库,B也是A的主库,在这种架构中就会存在两个库之间的叫唤呢,比如某时刻A为主库,B为从库(只读),一段时间后,因为某些原因需要发生切换,这时就变成A为从库(只读),B为主库。下面就来说一下MM架构中主备切换的流程:
-
主备延迟
先说以下主备延迟,我们的主库A在完成一个事务后,将binlog传给从库B,B在执行传来的binlog后才能达到和A一样的状态,也就是说我们的从库B和主库A是存在一定的同步延迟的,这个就是我们的主备延迟
-
主备切换流程
主备切换共有两种方法,分别是可靠性优先策略与可用性优先策略
-
可靠性优先策略
-
判断备库B当前的主备延迟,当小于某一个值时就开始下一步,否则重复判断
-
将主库A改为只读状态
-
反复判断B的主备延迟,直到降为0
-
将B改为读写状态
-
将业务请求转到B
-
-
可用性优先策略
可靠性优先策略保证了我们数据的一致性,不会出错,但是中间会存在一段时间系统只能读不能写,因此又有了可用性优先策略,该策略就是将4和5步骤提前,即不等主备数据同步就强行将业务请求移到B上
-
-
存在的问题
由于二者互为主库,那么A中binlog在B中执行后B会生成binlog再传给A这样就可能会导致命令重复执行,所以我们可以给binlog再加上一个server_id属性,实例只执行其他主机传过来的和自己server_id不同的binlog
一主多从架构实现
所谓一主多从,就是有一个MM架构,然后还有若干个从库,当MM中的主库崩溃掉时,所有从库都将主库设置为MM中的另外一个主库。
当系统崩溃时,从库切换主库是基于GTID实现的。所谓的GTID就是一个全局事务id。我们的每个实例中都有一个GTID集合,里面维护了当前实例已经执行完了的事务id集合。系统中的从数据库重新设置主库时就是基于这个GTID实现的,具体过程如下:
-
从库将重新设置主库
-
从库把自己的GTID集合发送给主库
-
主库接受到这个GTID集合后会与自己的GTID集合进行比较,若从库的GTID集合中有主库没有的,则直接返回错误;若从库的GTID集合包含在主库的GTID集合之内,则主库会从第一条自己的GTID集合中第一条不在从库GTID集合中的事务开始,将其binlog发送给从库
-
从库接受binlog并解析其中命令执行
读写分离
对于读写分离的架构,我们直到由于存在主备延迟,所以我们的读请求到达从库的时候可能会存在过期读的问题,对于这个问题,有以下几种解决方案
-
强制走主库的方案
我们将请求进行分类,将那些只能读取最新数据的请求直接分配给主库,将那些允许过期读的请求分配给从库
-
sleep(1)方案
我们认为查询请求到达主库后最多1s后从库和主库就能同步,所以我们的查询请求到达从库时先等待1s,1s后再进行查询
-
判断有无主备延迟
查询请求到达从库后,先对从库中主备延迟的参数进行判断,如果该参数不为0则等待,直至该参数降为0时再进行查询
-
半同步方案
要说这个方案就得先看一下binlog同步从库的过程,一般情况下,同步过程如下:
-
主库写完数据后,写binlog并发送,然后就返回给客户端执行成功了
-
从库接受binlog
-
从库解析binlog并执行
半同步方案就是主库待从库解析binlog并执行完成返回给主库一个ack后主库再成功返回给客户端
-
-
等位点方案
查询到达从库后,会将从库的位点与主库进行比较,在允许时间内二者达到一致则成功返回,否则返回一个错误
-
等GTID方案
查询到达从库后,会将从库的GTID与主库进行比较,在允许时间内二者达到一致则成功返回,否则返回查询错误