栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Mysql读写分离

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mysql读写分离

目前市面上有很多 MySQL 性能优化的文章,它们大多是基于索引优化、SQL 优化、操作系统调优等维度的,这些优化维度比较容易上手,毕竟调优一个 SQL 语句或者索引的成本很低,只需要使用 explain 命令去观察、实验就好了。另一方面,常见的操作系统的优化参数就那么多,基于一个配置手册,很快就可以配置好了。再进一步,有时它们会对 MySQL 进行表分区,这几乎可以让单机表性能达到极致。而当我们真正面对海量数据集,仅依赖上面的这些维度去调优是远远不够的。这时我们就需要依赖架构的力量去弥补上述不足,其中一个著名的架构方案就是读写分离。


什么是读写分离?

从名字上看,读写分离是为了将对数据库的读、写分散到不同的数据库实例上。这样的设计并不一定是完美的。读写分离主要针对的是读多写少的场景,对于写多读少的场景就不合适了。

比如,持久化落库就是一个写多读少的场景,多数情况是在不断的将数据记录到数据库,偶尔才需要去查询一下,相当于归档,大多数数据可能都不会被访问到。当然,大多数应用都有读多写少的特性,这也使得读写分离具有广泛的应用场景。

多数情况下,我们的读写分离都是采用一主多从的架构,也就是一台主数据库负责写入操作,其他数据库负责读取操作。主数据库和其他数据库之间会进行数据同步,这种同步是准实时的。既然是准实时,说明还是有一个时间差,这个时间差导致了主库和从库的数据不一致。

那么如何处理这种不一致情况呢?通常有 3 个思路:

  • 将读请求交给主库

显然,从库没有我想要的数据,我们就可以从主库读取,不同的框架都提供强制走主库的 API 支持。这是比较主流的一种做法,但是这种方法增加了主库的压力,相当于读写分离一定程度上失效了。

  • 延迟读取

有一个不用动脑子的方法,就是让程序 sleep 一段时间之后再去读数据,通常主从之间的时间差不会差太大,都是毫秒级别的。

  • 业务规避

上面的两个技术方案并不是很完美,最合适的方案是在业务层面绕开这种可能依赖主从数据同步的场景,比如,我们可以在完成写入请求之后,避免立即进行请求操作。幸运的是,这种场景并不多见,多数情况下,我们可以天然的规避这些操作。

 如何实现读写分离?

那么说了这么多,如何实现读写分离呢?其实很多现成的框架组件都帮我们做好了,无论使用哪个框架,它们的原理都是一样的,基本都是以下 3 步:

  • 首先部署多个 MySQL 实例,选择其中一台作为主库;
  • 保证主从数据库是准实时同步;
  • 将写请求分给主库,读请求分给从库。

其中比较著名的是官方的 MySQL Router 以及阿里的 MyCat。它们都是独立部署的比较重要的中间件。实际上是在程序和 MySQL 中间加了一个代理层。应用程序将所有的请求都交给代理层处理,由代理层负责分发读写请求,将它们路由到对应的数据库中。

更常见的做法是直接引入一个 Jar 包,这个包允许你配置多个表,主从数据库地址等等,这样就不需要部署独立的中间件了,简化了开发和运维的成本,其中比较著名的是 Sharding-JDBC,这个比较推荐,很多大厂都在使用。

主从同步

下面我们聊聊读写分离的核心——主从同步。

主从同步主要是通过 MySQL binlog 日志来进行的,binlog 主要记录了 MySQL 数据库中数据的所有 DDL 和 DML 操作。因此,我们根据主库的 binlog 日志就可以把数据同步到其他数据库实例中。咱们贴一个来自国外 toptal 平台的文章《MySQL Master-Slave Replication on the Same Machine》的图:

1.从库创建一个 I/O 线程向主库请求更新的 binlog;

2.主库创建一个 binlog dump 线程来发送 binlog;

3.从库的 I/O 线程将接收的 binlog 写入到 relay log 中(这里的 relay log 和 binlog 格式类似,下面我们会讲到,在这里大家当成是另一个 binlog 就好);

4.从库读取 relay log 同步到本地,通过 SQL 线程在本地执行里面的内容。

通过上面的分析,咱们可以很明显地看出来,由于 binlog 包含了所有 DDL 和 DML 操作,因此 binlog 除了可以用于主从复制,还可以恢复数据,是一个多功能的文件。

上面提到的 I/O 线程和 SQL 线程可以看作是在从库上工作的 2 个流水线工人,I/O 线程负责原材料的运输,写入本地的 relay log 中,SQL 线程负责从 relay log 获取原材料并加工。

上面我们提到了 relay log 的格式和 binlog 非常相似,那么为什么需要 relay log 呢?relay log 中文翻译为“中继日志”,中继的意思是桥梁纽带,除了数据本身以外 relay log 内部还包含了一些子文件,这些文件记录了上一次读取到主库同步过来的 binlog 的位置,复制的进度以及连接主库的配置信息等等。

很多三方工具可以帮助我们实现 MySQL 和其他数据库或者另外一台 MySQL 数据库之间的数据同步。大多数情况下,这些三方工具的底层原理都是基于 binlog。它们的原理就是在模拟 MySQL 主从复制的过程,解析 binlog 将数据同步到其他的数据源。

除了 MySQL,比如咱们常用的分布式 NoSQL、缓存 Redis 等,也通过主从复制实现了读写分离

总结

今天我们聊了 MySQL 的读写分离,读写分离几乎在所有大并发的场景得到了运用。主写从读已经成为一个很普遍的技术场景。读写分离给我们带来方便的同时,我们也要注意主从同步的延时。通常可以通过 API 强制走主库来避免这个问题,但是这就相当于没有做读写分离,更好的方案是在业务上避免这种操作,比如不要在插入之后立刻读取。

我们讨论了读写分离的原理和市面上常用的工具,虽然有很多中间件很有名,但是大厂还是用 Sharding-JDBC 最多,因为 Sharding-JDBC 轻量、几乎无侵入。

最后我们基于《MySQL Master-Slave Replication on the Same Machine》聊了一下主从复制的流程,这个流程只有 4 步,非常简单。

 

今天 MySQL 的读写分离咱们就讲完了,最后希望我的分享可以帮到你,欢迎你在评论区给我留言,也欢迎把这篇文章分享给你的朋友!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/606546.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号