一主一从架构切主的两种方案

可靠性优先:
先等seconds_behind_master小于一个阈值;
设置Master为只读;
等待Slave完全同步了Master的数据;
设置Slave可写;
切写的流量到Slave;

这中间,当设置Master为只读时,整个系统不可写,所以又不可用的时间。这也是为什么一开始就最好等seconds_behind_master很小时在做这个事情,不然主从延迟很大,不可用的窗口期就很久。

可用性优先:
不等Slave完全同步,直接设置Slave可写,并且切流量。
这个方案系统几乎没有不可用的窗口期,但是因为Slave同时接收了业务写请求以及之前Master未同步过来的数据,就会造成数据不一致。
简单的理解就是执行顺序可能有问题。比如a操作先在Master上执行,然后b操作发生在切主以后,也就是在Slave上执行,并且由于主从延迟,之前的a操作还没有同步到Slave,那么就会出现对于Slave而言,b先执行,a后执行,但是对于Master而言,a先执行,b后执行的不一致问题。
比如a和b都是插入有自增主键的表的操作,那么如果是row模式,可能发生主键冲突,如果是statement模式,可能发生数据不一致;其实冲突还是比较好的,起码可以暴露问题。如果数据不一致,后面修复数据可能相当难。
这两种方案用哪个,取决于具体的场景,对一致性有要求的,必须可靠性优先;如果没有要求,比如离线日志类的,可用性优先也无妨。

 

其实从这里我们也可以理解到,双活架构的难点,如果同时有多个Master节点,在同时接受写请求和binlog时,就很难保证执行时序了,进而会发生数据不一致问题。