Redis 这种缓存架构是高并发架构中非常重要的一环。

image.png

为什么需要主从同步

  1. 首先需要考虑的应该是如何优化你的 SQL 和索引,这种方式简单有效
  2. 其次才是采用缓存的策略, 比如使用 Redis
  3. 最后才是对数据库采用主从架构,进行读写分离。

按照上面的方式进行优化,使用和维护的成本是由低到高的。

主从同步设计不仅可以提高数据库的吞吐量,还有以下 3 个方面的作用:

  • 首先是可以读写分离。我们可以通过主从复制的方式来同步数据,然后通过读写分离提高数据库并发处理能力。
  • 第二个作用就是数据备份。我们通过主从复制将主库上的数据复制到了从库上,相当于是一种热备份机制,也就是在主库正常运行的情况下进行的备份,不会影响到服务。
  • 第三个作用是具有高可用性。我刚才讲到的数据备份实际上是一种冗余的机制,通过这种冗余的方式可以换取数据库的高可用性,也就是当服务器出现故障或宕机的情况下,可以切换到从服务器上,保证服务的正常运行。

关于高可用性的程度,我们可以用一个指标衡量,即正常可用时间 / 全年时间。比如要达到全年 99.999% 的时间都可用,就意味着系统在一年中的不可用时间不得超过 5.256 分钟,也就 3652460*(1-99.999%)=5.256 分钟,其他时间都需要保持可用的状态。需要注意的是,这 5.256 分钟包括了系统崩溃的时间,也包括了日常维护操作导致的停机时间。

主从同步的原理是怎样的

提到主从同步的原理,我们就需要了解在数据库中的一个重要日志文件,那就是 Binlog 二进制日志,它记录了对数据库进行更新的事件。实际上主从同步的原理就是基于 Binlog 进行数据同步的。在主从复制过程中,会基于 3 个线程来操作,一个主库线程,两个从库线程。

  1. 二进制日志转储线程(Binlog dump thread)是一个主库线程。当从库线程连接的时候,主库可以将二进制日志发送给从库,当主库读取事件的时候,会在 Binlog 上加锁,读取完成之后,再将锁释放掉。
  2. 从库 I/O 线程会连接到主库,向主库发送请求更新 Binlog。这时从库的 I/O 线程就可以读取到主库的二进制日志转储线程发送的 Binlog 更新部分,并且拷贝到本地形成中继日志(Relay log)。
  3. 从库 SQL 线程会读取从库中的中继日志,并且执行日志中的事件,从而将从库中的数据与主库保持同步。

image.png

在进行主从同步的时候,我们需要先检查服务器是否已经开启了二进制日志。

如何解决主从同步的数据一致性问题

解决主从同步中数据不一致的问题,也就是解决主从之间数据复制方式的问题,如果按照数据一致性从弱到强来进行划分,有以下 3 种复制方式。

方法 1:异步复制

异步模式就是客户端提交 COMMIT 之后不需要等从库返回任何结果,而是直接将结果返回给客户端,这样做的好处是不会影响主库写的效率,但可能会存在主库宕机,而 Binlog 还没有同步到从库的情况,也就是此时的主库和从库数据不一致。这时候从从库中选择一个作为新主,那么新主则可能缺少原来主服务器中已提交的事务。所以,这种复制模式下的数据一致性是最弱的。

原文说的不清楚, 建议看分布式数据库相关资料.

image.png

方法 2:半同步复制

MySQL5.5 版本之后开始支持半同步复制的方式。原理是在客户端提交 COMMIT 之后不直接将结果返回给客户端,而是等待至少有一个从库接收到了 Binlog,并且写入到中继日志中,再返回给客户端。这样做的好处就是提高了数据的一致性,当然相比于异步复制来说,至少多增加了一个网络连接的延迟,降低了主库写的效率。

image.png

方法 3:组复制

组复制技术,简称 MGR(MySQL Group Replication)。是 MySQL 在 5.7.17 版本中推出的一种新的数据复制技术,这种复制技术是基于 Paxos 协议的状态机复制。

  • 异步复制和半同步复制都无法最终保证数据的一致性问题

MGR 是如何工作的:

  1. 首先我们将多个节点共同组成一个复制组,在执行读写(RW)事务的时候,需要通过一致性协议层(Consensus 层)的同意,也就是读写事务想要进行提交,必须要经过组里“大多数人”(对应 Node 节点)的同意,大多数指的是同意的节点数量需要大于(N/2+1),这样才可以进行提交,而不是原发起方一个说了算。而针对只读(RO)事务则不需要经过组内同意,直接 COMMIT 即可。
  2. 在一个复制组内有多个节点组成,它们各自维护了自己的数据副本,并且在一致性协议层实现了原子消息和全局有序消息,从而保证组内数据的一致性。(具体原理点击这里可以参考)

image.png

总结

image.png