本文进一步分析引入从库后需要保证主从的数据一致性需要考虑哪些方面。
  原生复制架构

  MySQL 的原生复制架构原理如上图所示。从库的 I/O Thread 线程负责不断读取主库的 binlog 日志文件并写入本地的 Relay log 临时缓存。从库的 SQL Thread 线程则不断读取 Relay log 重放事件入库。整个过程看起来是比较简单清晰的,但其中有几个点对主从数据一致性有关键影响,我们下面逐一分析。
  主从复制的场景下,产生数据不一致的现象有两种:
  1、数据丢失
  2、数据重复

  从库的 I/O Thread 是通过网络读取主库的 binlog 的,若出现网络故障,有可能产生数据丢失。为避免网络故障导致的数据丢失,网络恢复后从库重新连接上来需要知道从主库 binlog 的哪个位置重新传输数据。从库需要记住中断发生时 binlog 的位置,并从该断点处重新读取,这个断点我们称为从库的重传检查点。一个可靠的重传检查点必须是在从库读到数据并写入到本地 Relay log 持久化之后才可建立,否则都有丢失数据的可能。
  由于主从复制过程的分布式特征,需要保证复制过程的幂等性,也是重复复制同一条数据终不会产生重复的数据。防重策略是必须的,一般符合范式特征的数据库表设计通过主键来防重,而无主键表数据可以通过所有字段联合索引来防重。有了防重策略可以任意回溯复制过程,而不必考虑从库产生重复数据。
  为了保证主从数据一致性,复制过程不仅要保证不丢失、不重复,还需要保证操作顺序一致。binlog 的事件日志反应了主库并发事务的操作序列,终这种序列也要原样反应到从库上。所以原生复制架构为了做到这点,采用了单线程模型的串行化操作。这也是没办法的,因为在数据库层面是无法知道不同数据之间的因果和依赖关系,因此无法并行入库。
  原生的复制架构做到了无丢失、无重复和顺序一致性,普通场景下基本可用,但也存在一些不足:
  · 可监控性、可管理性相对较弱。
  · 对于异构数据无能为力。
  · 通用的单线程模型可能成为性能瓶颈,导致复制延时过高。
  · 一对多场景下对主库形成过大复制压力,影响主库可用性。
  一些特殊场景下的数据库复制分布,使用原生复制架构则不一定合适,可能的场景有:
  · 大型库,数据量大,写入量大,还需要跨地域、跨机房的复制,而且对复制延时长短比较敏感,比如大型电商的订单、交易类数据库。
  所以我们才需要考虑针对特殊场景自定义复制架构,下面我们看一个自定义复制架构的概念原理图。
  自定义复制架构

  如上,自定义复制架构参考原生架构模拟成一个 MySQL 从库,它内部包括三个主要角色: