您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
MySql主从同步介绍
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
MySql主从同步介绍
自猿其说Tech
2022-08-02
IP归属:未知
33080浏览
Sql
MySQL
数据库
### 1 引言 大家好,Mysql是大家最常用的数据库,下面为大家带来mysql主从同步知识点的分享,以便巩固mysql基础知识,如有错误,还请各位大佬们指正。 ### 2 MySql主从同步概述 MySQL主从同步,即MySQL Replication,可以实现将数据从一台数据库服务器同步到多台数据库服务器。MySQL数据库自带主从同步功能,经过配置,可以实现基于库、表结构的多种方案的主从同步。 Redis是一种高性能的内存数据库,但不是今天的主角;MySQL是基于磁盘文件的关系型数据库,相比于Redis来说,读取速度会慢一些,但是功能强大,可以用于存储持久化的数据。在实际工作中,我们常将Redis作为缓存与MySQL配合来使用,当有数据访问请求的时候,首先会从缓存中进行查找,如果存在就直接取出,如果不存在再访问数据库,这样就提升了读取的效率,也减少了后端数据库的访问压力。使用Redis这种缓存架构是高并发架构中非常重要的一环。 ![](//img1.jcloudcs.com/developer.jdcloud.com/edce694c-586b-4070-8259-c1e0860270ac20220802141548.png) 随着业务量的不断增长,数据库的压力会不断变大,缓存的频繁变更也强依赖于数据的查询结果,导致数据查询效率低,负载很高,连接过多等问题。对于电商场景来说,往往存在很多典型的读多写少场景,我们可以对MySQL做主从架构并且进行读写分离,让主服务器(Master)处理写请求,从服务器(Slave)处理读请求,这样可以进一步提升数据库的并发处理能力。如下图: ![](//img1.jcloudcs.com/developer.jdcloud.com/fef69172-6148-4db3-b6d6-d855f79f787620220802141559.png) 上图中,可以看到,我们增加了2个从库,这2个从库可以一起抗下大量的读请求,分担主库压力。从库会通过主从复制,从主库中不断的同步数据,以此来保证从库的数据和主库数据的一致。 接下来,我们看看主从同步有哪些作用,以及主从同步具体是怎么实现的。 ### 3 主从同步的作用 一般来说,不是所有的系统都需要对数据库进行主从架构的设计,因为架构本身是有一定成本的,如果我们的目的在于提升数据库高并发访问的效率,那么我们首先应该优化SQL语句及索引,充分发挥数据库的最大性能;其次是采用缓存的策略,如使用Redis、Magodb等缓存工具,通过其高性能的优势把数据保存在内存数据库中,提升读取的效率,最后才是对数据库采用主从架构,进行读写分离。系统的使用和维护成本是根据架构的升级逐渐升高的。 言归正传,主从同步不仅可以提升数据库的吞吐量,还有以下三个方面的作用: #### 3.1 读写分离 我们可以通过主从复制的方式来同步数据,然后通过读写分离提升数据库的并发处理能力。简单来说就是我们的数据被放在了多个数据库中,其中一个是Master主库,其余的是Slave从库。当主库数据变化时,会自动将数据同步到从库中,而我们程序可以从从库读取数据,也就是采用读写分离的方式。电商的应用往往是“读多写少”,采用读写分离就实现了更高的并发访问。原本所有的读写压力都由一台服务器承担,现在有多个服务器共同处理读请求,减少了对主库的压力。另外还可以对从服务器进行负载均衡,让不同的读请求按照策略均匀的分配到不同的从服务器中,让读取更加顺畅。读取顺畅的另一个原因,就是减少了锁表的影响,比如我们让主库负责写,当主库出现写锁的时候,不会影响到从库的查询操作。 #### 3.2 数据备份 主从同步也相当于是一种数据热备份机制,在主库正常运行下进行备份,不影响提供数据服务。 #### 3.3 高可用性 数据备份实际就是一种冗余的机制,通过这种冗余的方式可以换取数据库的高可用性,当服务器出现故障、宕机等无可用的情况下,可以迅速进行故障切换,让从库充当主库,保障服务正常运行。大家可以了解下电商系统数据库高可用SLA指标。 ### 4 主从同步的原理 说到主从同步的原理,我们就需要了解在数据库中的一个重要日志文件,就是Binlog二进制文件,它记录了对数据库进行更新的事件,事实上主从同步的原理就是基于Binlog进行数据同步的。 在主从复制的过程中,会基于三个线程来操作,一个是binlog dump线程,位于master节点上,另外两个线程分别是I/O线程和SQL线程,它们都分别位于slave节点上,如下图: ![](//img1.jcloudcs.com/developer.jdcloud.com/ff32776b-c43a-4609-9054-8fc31eecdeb220220802142128.png) 结合以上图片,我们一起来了解主从复制的核心流程: 1. 当master节点接收到一个写请求时,这个写请求可能是增删改操作,此时会把写请求的更新操作都记录到binlog日志中。 2. master节点会把数据复制给slave节点,如图中的slave01节点和slave02节点,这个过程,首先得要每个slave节点连接到master节点上,当slave节点连接到master节点上时,master节点会为每一个slave节点分别创建一个binlog dump线程,用于向各个slave节点发送binlog日志。 3. binlog dump线程会读取master节点上的binlog日志,然后将binlog日志发送给slave节点上的I/O线程。当主库读取事件的时候,会在Binglog上加锁,读取完成之后,再将锁释放掉。 4. slave节点上的I/O线程接收到binlog日志后,会将binlog日志先写入到本地的relaylog中,relaylog中就保存了binlog日志。 5. slave节点上的SQL线程,会来读取relaylog中的binlog日志,将其解析成具体的增删改操作,把这些在master节点上进行过的操作,重新在slave节点上也重做一遍,达到数据还原的效果,这样就可以保证master节点和slave节点的数据一致性了。 主从同步的数据内容其实是二进制日志(Binlog),它虽然叫二进制日志,实际上存储的是一个又一个的事件(Event),这些事件分别对应着数据库的更新操作,比如INSERT、UPDATE、DELETE等。 另外我们还需要注意的是,不是所有版本的MySQL都默认开启了服务器的二进制日志,在进行主从同步的时候,我们需要先检查服务器是否已经开启了二进制日志。 二进制日志,它是一个文件,在进行网络传输的过程中就一定会存在一些延迟,比如200ms,这样就可能造成用户在从库上读取的数据不是最新的数据,也就会造成主从同步中的数据不一致的情况发生。比如我们对一条记录进行更新,这个操作是在主库上完成的,而在很短的时间内,比如100ms,又对同一个记录进行读取,这时候从库还没有完成数据的同步,那么,我们通过从库读取到的数据就是一条旧的数据。这种情况下该怎么办呢? ### 5 如何解决主从同步的数据一致性问题 可以想象下,如果我们想要操作的数据都存储在同一个数据库中,那么对数据进行更新的时候,可以对记录进行加写锁,这样在读取的时候就不会发生数据不一致的情况了。但这时从库的作用就是备份数据,没有做到读写分离,分担主库的压力。 因此我们还需要想办法,在进行读写分离的时候,解决主从同步中数据不一致的问题,也就是解决主从之间数据复制方式的问题,如果按照数据一致性从弱到强来进行划分,有以下三种复制方式。 #### 5.1 全同步复制 首先,全同步复制,就是当主库执行完一个事务之后,要求所有的从库也都必须执行完该事务,才可以返回处理结果给客户端;因此,虽然全同步复制数据一致性得到保证了,但是主库完成一个事物需要等待所有从库也完成,性能就比较低了。如下图: ![](//img1.jcloudcs.com/developer.jdcloud.com/36280c73-1dde-4bdb-b2dc-33e55b41fc6220220802142357.png) ##### 5.2 异步复制 而异步复制,就是当主库提交事物后,会通知binlog dump线程发送binlog日志给从库,一旦binlog dump线程将binlog日志发送给从库之后,不需要等到从库也同步完成事务,主库就会将处理结果返回给客户端。 因为主库只管自己执行完事务,就可以将处理结果返回给客户端,而不用关心从库是否执行完事务,这就可能导致短暂的主从数据不一致的问题了,比如刚在主库插入的新数据,如果马上在从库查询,就可能查询不到。 而且,当主库提交事物后,如果宕机挂掉了,此时可能binlog还没来得及同步给从库,这时候如果为了恢复故障切换主从节点的话,就会出现数据丢失的问题,所以异步复制虽然性能高,但数据一致性上是最弱的。 mysql主从复制,默认采用的就是异步复制这种复制策略。 ![](//img1.jcloudcs.com/developer.jdcloud.com/ad4cab4d-1bbe-4eeb-bdc3-b3cffd49b71720220802142841.png) #### 5.3 半同步复制 MySQL5.5版本之后开始支持半同步复制的方式。原理是在客户端提交COMMIT之后不直接将结果返回给客户端,而是等待至少有一个从库收到了Binlog,并且写入到中继日志中,再返回给客户端。这样做的好处就是提高了数据的一致性,当然相比于异步复制来说,至少多增加了一个网络连接的延迟,降低了主库写的效率。 在MySQL5.7版本中还增加了一个rpl_semi_sync_master_wait_for_slave_count参数,我们可以对需要响应的从库数量进行设置,默认为1,也就是说只要有一个从库进行了响应,就可以返回给客户端。如果将这个参数调大,可以提升数据一致性的强度,但也会增加主库等待从库响应的时间。 ![](//img1.jcloudcs.com/developer.jdcloud.com/df634204-fbdf-49cd-a778-b0a3041c83f720220802142759.png) 但是,半同步复制也存在以下几个问题: - 半同步复制的性能,相比异步复制而言有所下降,相比于异步复制是不需要等待任何从库是否接收到数据的响应,而半同步复制则需要等待至少一个从库确认接收到binlog日志的响应,性能上是损耗更大的。 - 主库等待从库响应的最大时长是可以配置的,如果超过了配置的时间,半同步复制就会变成异步复制,那么,异步复制的问题同样也就会出现了。 - 在MySQL 5.7.2之前的版本中,半同步复制存在着幻读问题的。 当主库成功提交事物并处于等待从库确认的过程中,这个时候,从库都还没来得及返回处理结果给客户端,但因为主库存储引擎内部已经提交事务了,所以,其他客户端是可以到从主库中读到数据的。 但是,如果下一秒主库突然挂了,此时正好下一次请求过来,因为主库挂了,就只能把请求切换到从库中,因为从库还没从主库同步完数据,所以,从库中当然就读不到这条数据了,和上一秒读取数据的结果对比,就造成了幻读的现象了。 #### 5.4 增强半同步复制 增强半同步复制,是mysql 5.7.2后的版本对半同步复制做的一个改进,原理上几乎是一样的,主要是解决幻读的问题。 主库配置了参数 rpl_semi_sync_master_wait_point = AFTER_SYNC 后,主库在存储引擎提交事务前,必须先收到从库数据同步完成的确认信息后,才能提交事务,以此来解决幻读问题。参考下图: ![](//img1.jcloudcs.com/developer.jdcloud.com/a82c06b0-607e-42e9-9131-1a652a51f68a20220802142926.png) ### 6 总结 通过上述内容,我们了解了Mysql数据库的主从同步,如果你的目标仅是数据库的高并发,那么可以先从 SQL 优化,索引以及 Redis 缓存数据等这些方面来考虑优化,然后再考虑是否采用主从架构的方式。 在主从架构的配置中,如果想要采取读写分离的策略,我们可以自己编写程序,也可以通过第三方的中间件来实现。 自己编写程序的好处就在于比较自主,我们可以自己判断哪些查询在从库上来执行,针对实时性要求高的需求,我们还可以考虑哪些查询可以在主库上执行。同时程序直接连接数据库,减少了中间件层,可以减少一些性能损耗。 而采用中间件的方法有很明显的优势,功能强大,使用简单。但因为在客户端和数据库之间增加了中间件层会有一些性能损耗,同时商业中间件价格较高,有一定学习成本。另外,我们也可以考虑采用一些优秀的开源工具,比如 MaxScale。它是 MariaDB 开发的 MySQL 数据中间件。比如在下图中,使用 MaxScale作为数据库的代理,通过路由转发完成了读写分离。同时我们也可以使用 MHA 工具作为强一致的主从切换工具,从而完成 MySQL的高可用架构。 ![](//img1.jcloudcs.com/developer.jdcloud.com/2a9b78c7-e772-431d-94d1-6641f2714c3320220802142952.png) ------------ ###### 自猿其说Tech-JDL京东物流技术与数据智能部 ###### 作者:刘邓忠
原创文章,需联系作者,授权转载
上一篇:IPSec VPN原理介绍
下一篇:不一样的代码整洁之道
相关文章
【技术干货】企业级扫描平台EOS关于JS扫描落地与实践!
开发也要防沉迷--IDEA插件教程
如何保证MySQL和Redis的数据一致性?10分钟带你搞定!
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号