复制拓扑
Mysql的复制机制非常简单和灵活,因此拓扑模型非常多。简单讨论几种常见的复制拓扑结构。
Top1. 一主一备
一主一备是最常见的拓扑模型,中等规模应用一主一备完全足够了。
Top2. 一主多备
一主多备是第二常见的拓扑模型,大规模乃至超大规模的应用一主多备应付起来也是绰绰有余。一主多备是最实用的模型之一:
- 应用规划读/写分离后可以通过添加备库来水平扩展读容量。
- 添加一台冗余备库(即平时啥都不做的备库)做待用的主库。
- 添加一台冗余备库(即平时啥都不做的备库)做测试、分析或数据拷贝等用途。
- 为不同的备库设置不同的存储引擎或索引,能满足不同的业务场景。
- 添加位于其他数据中心的备库,用于防止整个数据中心瘫痪。
级联主备是一主多备的变种之一。其优点是减轻主库复制的性能损耗,缺点是复制链最远端的备库延时较大。
主-主复制
该拓扑模型由两台服务器构成,每一个都被配置成对方的主库和备库。两台机器的角色对等,皆可读也可写。优点是角色对等带来的便利性,当一台主库挂掉后切到另一台即可。同时写容量也得到了扩展。
该模型有些缺陷:
-
主键冲突:
Server1
插入一条数据id
为1,同时Server2
也插入一条数据id
为1。当双方开始互相复制是便会造成主键冲突。目前的解决方案是通过设置auto_increment_increment
和auto_increment_offset
来解决,将Server1
的起始id
设为1,Server2
的起始id
设为2,并将自增长步长设为2。那么两台机器同时插入时id
正好隔开。 - 主键容量浪费:由于步长设为2,因此主键容量为平时的一半。
-
复制无限循环:
Server2
宕机后替换为Server3
,于是Server2
的语句会在Server1
和Server3
之间无限循环复制,这是互相复制导致的。Mysql会根据binlog操作日志里的Server信息来判断是否要中止复制,一旦Server2
移除那么相当于丢失了中止条件。解决方案是替换Server3
时要小心的设置偏移量,不要复制带有Server2语句的binlog。 -
数据不一致:
Server1
执行UPDATE foo SET col=col+1 WHERE id=200
,同时Server2
执行UPDATE foo SET col=col*2 WHERE id=200
。复制后两边数据会发生不一致。因为先+再x
和先x再+
结果是不一样,解决方案还是有的~
主-主复制(主动/被动模式)
主动/被动模式顾名思义,一台主库为主动写入即应用客户端可写,另一台主库为被动写入即应用客户端不可写,仅靠复制来写入数据。该模式无需设置自增起点和自增步长,做到真正的角色对等。
主动/被动模式的优势是:
- 高可用:主动模式的主库宕机后,应用立刻将写切换到另一台主即可。主动/被动角色交换。
- 主键不冲突:因为同一时刻只有其中一台主库可写。
- 主键容量无浪费:因为同一时刻只有其中一台主库可写。
- 数据一致:还是因为同一时刻只有其中一台主库可写。
可以看到主动/被动模式几乎解决了主-主复制的所有难题。
Top3. 拥有备库的主-主复制(主动/被动模式)
在主-主复制(主动/被动模式)的基础上融合了一主多备的所有优点,可以说该模式是Mysql复制拓扑的究极态。唯一的缺点是增加了一定的复杂度。
环形复制
环形复制拓扑不具备双主复制的优点。最大的缺点有两个:
-
不对称:
Server2
宕机后,Server1
和Server3
无法相互复制,处理起来特别麻烦。 -
脆弱:只要环形中有一个节点挂了集群就故障,故障概率大大增加。
生产中应该避免这种脆弱的拓扑设计。
总结
Mysql复制拓扑种类非常多,有些非常好用,有些不那么好用。
随着业务量从简单到复杂,Mysql的最佳拓扑实践是:
一主一备 => 一主多备 => 拥有备库的主-主复制(主动/被动模式)