最近在研究异地多活双写的方案,自己实现Master-Master同步,实现是可以实现,但是有很多限制。目前双写主要有以下几个问题:
研究了很多方案,都不如意,于是研究了下官方的方案。MariaDB支持Master-Master同步,但是由于不支持数据一致性检测,所以异地的两个库不能有相同的库名,所以在这种场景下不可用。MySQL官方在5.7.17后以插件的形式支持了Group replication
,支持数据一致性检测。但是特性归特性,我们必须得了解底层的实现才能对整体有所把控。这方面的资料很少,所以自己在这里做了个总结。
Group replication的特性看着非常吸引人,支持单master集群,多master集群,集群最多9个实例,支持在多master集群上同时读写数据。这应该是高可用最终的特性了。我们来仔细看一下,MySQL是通过何种方式来实现GR的。我们首先来解释一下几个名词:
在多master模式下,理论上可以在任意master上操作,也就是存在多个master的并发问题,牵扯到并发,那么数据冲突是必须要解决的。我们来看一下,在GR模式下,提交事务的流程:
gtids_executed
、操作的记录的PK信息等,并把这些信息提交给广播线程,用户线程休眠。所以以上流程的核心为,并发提交的事务,最终会通过一致性协议来产生一个全局有序的事务列表,该列表会在所有的节点中存在,无论如何并发,所有的节点都会有一样顺序的事务提交记录,同时由apply线程进行certify和apply。
只要所有的事务全局有序,那么所有的节点按照同一个顺序进行应用,整个集群肯定可以保证一致性。剩下的就是冲突检测了。上面说过,在commit之前,事务提交记录有以下几个用于冲突判断的信息:
gtids_executed
假设在数据版本号一致的情况下,多个master节点同时更新一行数据,那么后提交的事务会被回滚,先提交的事务会被接受。
假设在数据版本号不一致的情况下,多个master节点同时更新一行数据,假设版本号旧的先执行,再执行新的版本,那么不会冲突,因为新版本的数据已经包含了老的,是在老的基础上执行而来;反之则会丢弃老的事务。