数据库主从同步的作用是什么,如何解决数据不一致问题?

数据库主从同步的作用是什么,如何解决数据不一致问题?
leorain, 09-25 23:35
zjusw

Redis是一种高性能的内存数据库;而MySQL是基于磁盘文件的关系型数据库,相比于Redis来说,读取速度会慢一些,但是功能强大,可以用于存储持久化的数据。在实际工作中,我们常常将Redis作为缓存与MySQL配合来使用,当有数据访问请求的时候,首先会从缓存中进行查找,如果存在就直接取出,如果不存在再访问数据库,这样就提升了读取的效率,也减少了堆后端数据库的访问压力。可以说使用Redis这种缓存架构是高并发架构中非常重要的一环。

在这里插入图片描述

当然我们也可以对MySQL做主从架构并且进行读写分离,让主服务器(Master)处理写请求,从服务器(Slave)处理读请求,这样同样可以提升数据库的并发处理能力。不过主从架构的作用不止如此,我们今天就从下面几个方面了解一下它:

1、为什么需要主从同步,设置主从同步有什么样的作用?
2、主从同步的原理是怎样的?在进行主从同步的同时会引入哪些问题?
3、为了保证主从同步的数据一致性,都有哪些方案?

为什么需要主从同步

首先不是所有的应用都需要对数据库进行主从架构的设置,毕竟设置架构本身是有成本的,如果我们的目的在于提升数据库高并发访问的效率,那么首先需要考虑的应该是如何优化你的SQL和索引,这种方式简单有效,其次才是采用缓存的策略,比如使用Redis,通过Redis高性能的优势把热点数据保存在内存数据库中,提升读取的效率,最后才是对数据库采用主从架构,进行读写分离。

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

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

首先是可以读写分离,我们可以通过主从复制的方式来同步数据,然后通过读写分离提升数据库的并发处理能力。

简单来说就是同一份数据被放在了多个数据库中,其中一个数据库是Master主库,其余的多个数据库是Slave从库。当主库进行更新的时候,会自动将数据复制到从库中,而我们在客户端读取数据的时候,会从从库进行读取,也就是采用读写分离的方式。互联网的应用往往是“读多写少”的需求,采用读写分离的方式,可以实现更高的并发访问。原本所有的读写压力都由一台服务器承担,现在有多个“兄弟”帮忙处理读请求,这样就减少了对后端大哥(Maste)的压力。同时,我们还能对从服务器进行负载均衡,让不同的读请求按照策略均匀的分配到不同的从服务器中,让读取更加顺畅。读取顺畅的另一个原因,就是减少了锁表的影响,比如我们让主库负责写,当主库出现写锁的时候,不会影响到从库进行SELECT操作。

第二个作用就是数据备份。我们通过主从复制将主库上的数据复制到了从库上,相当于是一种热备份机制,也就是在主库正常运行下进行备份,不会影响到服务。

第三个作用是具有高可用性。我刚才讲的数据备份实际上是一种冗余的机制,通过这种冗余的方式可以换取数据库的高可用性,也就是当服务器出现故障或者宕机的情况下,可以切换到从服务器上,让从服务器充当主服务器,保证服务的正常运行。

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

事实上,更高的高可用性,意味着需要付出更高的成本代价,在现实中我们需要结合业务需求和成本来进行选择。

主从同步的原理是怎样的

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

二进制日志转储线程是一个主库线程。当从库线程连接的时候,主库可以将二进制日志发送到从库,当主库读取事件的时候,会在Binglog上加锁,读取完成之后,再将锁释放掉。

从库IO线程会连接到主库,向主库发送请求更新Binlog,这时从库的IO线程就可以读取到主库的二进制日志转储线程发送的Binlog更新部分,并且拷贝到本地形成中继日志(Relay log)。

从库SQL线程会读取从库中的中继日志,并且执行日志中的事件,从而将从库中的数据与主库保持同步。

在这里插入图片描述

你能看到主从同步的内容就是二进制日志(Binlog),它虽然叫二进制日志,实际上存储的是一个又一个的事件(Event),这些事件分别对应着数据库的更新操作,比如INSERT、UPDATE、DELETE等。另外我们还需要注意的是,不是所有版本的MySQL都默认开启了服务器的二进制日志,在进行主从同步的时候,我们需要先检查服务器是否已经开启了二进制日志。

进行主从同步的内容是二进制日志,它是一个文件,在进行网络传输的过程中就一定会存在延迟,比如500ms,这样就可能造成用户在从库上读取的数据不是最新的数据,也就是主从同步中的数据不一致问题。比如我们对一条记录进行更新,这个操作是在主库上完成的,而在很短的时间内,比如100ms,又对同一个记录进行读取,这时候从库还没有完成数据的读取,那么,我们通过从库读取到的数据就是一条旧的数据。

这种情况下该怎么办呢?

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

可以想象下,如果我们想要操作的数据都存储在同一个数据库中,那么对数据进行更新的时候,可以对记录进行加写锁,这样在读取的时候就不会发生数据不一致的情况了。但这时从库的作用就是备份数据,没有做到读写分离,分担主库的压力。

在这里插入图片描述

因此我们还需要想办法,在进行读写分离的时候,解决主从同步中数据不一致的问题,也就是解决主从之间数据复制方式的问题,如果按照数据一致性从弱到强来进行划分,有以下三种复制方式。

方式1:异步复制

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

在这里插入图片描述

方式2:半同步复制

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

在MySQL5.7版本中还增加了一个rpl_semi_sync_master_wait_for_slave_count参数,我们可以对应搭的从库数量进行设置,默认为1,也就是说只要有一个从库进行了响应,就可以返回给客户端。如果将这个参数调大,可以提升数据一致性的强度,但也会增加主库等待从库响应的时间。

在这里插入图片描述

方式3:组复制

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

我刚才介绍的异步复制和半同步复制都无法最终保证数据的一致性问题,半同步复制是通过判断从库响应的个数来决定是否返回给客户端,虽然数据一致性相比于异步复制有提升,但仍然无法满足对数据一致性要求高的场景,比如金融领域。MGR 很好地弥补了这两种复制模式的不足。

下面我们来看下 MGR 是如何工作的(如下图所示)。

首先我们将多个节点共同组成一个复制组,在执行读写(RW)事务的时候,需要通过一致性协议层(Consensus)的同意,也就是读写事务想要进行提交,必须要经过组里“大多数人”(对应Node节点)的同意,大多数指的是同意的节点数量要大于N/2+1,这样才可以进行提交,而不是一方说了算。而针对只读(RO)事务则不需要经过组内同意,直接COMMIT即可。

在一个复制组内有多个节点组成,它们各自维护了自己的数据副本,并且在一致性协议层实现了源自消息和全局有序消息,从而保证组内数据的一致性。(具体原理点击这里可以参考)。

在这里插入图片描述

MGR将MySQL带入了数据强一致性的时代,是一个划时代的创新,其中一个重要原因是MGR是基于paxos协议的。PAxos算法是由2013 年的图灵奖获得者 Leslie Lamport 于 1990 年提出的,有关这个算法的决策机制你可以去网上搜下。

事实上,Paxos算法提出来之后就作为分布式一致性算法被广泛使用,比如Apache的Zookeeper也是基于paxos算法实现的。

总结

我今天讲解了数据库的主从同步,如果你的目标仅仅是数据库的高并发,那么可以先从 SQL 优化,索引以及 Redis 缓存数据库这些方面来考虑优化,然后再考虑是否采用主从架构的方式。

在主从架构的配置中,如果想要采取读写分离的策略,我们可以自己编写程序,也可以通过第三方的中间件来实现。

自己编写程序的好处就在于比较自主,我们可以自己判断哪些查询在从库上来执行,针对实时性要求高的需求,我们还可以考虑哪些查询可以在主库上执行。同时,程序直接连接数据库,减少了中间件层,相当于减少了性能损耗。

采用中间件的方法有很明显的优势,功能强大,使用简单。但因为在客户端和数据库之间增加了中间件层会有一些性能损耗,同时商业中间件也是有使用成本的。我们也可以考虑采取一些优秀的开源工具,比如 MaxScale。它是 MariaDB 开发的 MySySQL 数据中间件。比如在下图中,使用 MaxScale作为数据库的代理,通过路由转发完成了读写分离。同时我们也可以使用 MHA 工具作为强一致的主从切换工具,从而完成 MySQL的高可用架构。

在这里插入图片描述

在这里插入图片描述

以上就是本文的全部内容啦,有什么疑问欢迎在下方评论区留言嗷,收到通知会及时回复~
文章浏览总量:598 (非即时 )
跳转到顶部