”MySQL官方驱动“主从分离的神秘面纱(扫盲篇)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 我们经常使用的MySQL驱动jar包,其实默认有非常棒的功能,那就是主从分离和HA。如果你只是需要一个主从分离、failover的功能,不要sharding。一个驱动就够了,不需要引入什么中间层。

假如你日后的工作,需要快速实现MySQL的读写分离功能,你一定会想起这篇文章。如果你再次回到这里,证明你已经迫切需要一个简单快捷的解决方案了--那就是MySQL官方驱动层实现的读写分离,偏小众,但很有效。

JDBC驱动

我们经常使用的MySQL驱动jar包,其实默认有非常棒的功能,那就是主从分离和HA。如果你只是需要一个主从分离、failover的功能,不要sharding。一个驱动就够了,不需要引入什么中间层。

这个东西就是Replication协议。Mysql JDBC Connector在5.1.X版本之后增加了这些功能,以支持“multi-host”集群拓扑的访问范式。这个功能是在驱动层实现的,而既然是驱动层,那就不可避免有一些驱动层的问题(详见《“分库分表" ?选型和流程要慎重,否则会失控》

我们平常的jdbc连接是这样

jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8

而经过协议改造后的jdbc连接,长得要长一些、大一些!

jdbc:mysql:replication://127.0.0.1:3306,127.0.0.1:3307,127.0.0.1:3308/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=false&loadBalanceStrategy=random

当然,也可以有ipv6的写法,更加直观

jdbc:mysql://address=(type=master)(host=master1host),address=(type=master)(host=master2host),address=(type=slave)(host=slave1host)/db

8.0的文档看这里:
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-multi-host-connections.html
说明:

协议的第一个连接,表示主库Master
后面的一堆连接,表示从库Slave,当然可以有多个
当你把Master连接也放在后面的一堆里,那么它也拥有了“读库“的属性了
后面有一堆参数,来控制这所有连接,到底要如何相处

这样,所谓的主从分离功能,只要配置好这个连接串,就枯木逢春了。

代码层

首先你要改驱动类,再也不是Driver了,而是这个

com.mysql.jdbc.ReplicationDriver

这种情况下
DataSource.getConnection()
获取的连接,实际上是ReplicationConnection,这个连接是虚拟的,和真实的数据库连接是个1对多的关系,所以记得给每一个MySQL都做上相应的机器授权。

那么如何来区别本次请求是读是写呢?靠的其实是Connection中的readonly属性,这个属性是通过请求header中的“readonly”传递的。所以如果请求中有写入操作,这整个的事务就一定是readonly=false的。

对于Spring来说,就可以使用@Transactional注解来控制这个属性了。一个事务不可能跨两个连接,所以是读是写,有最高层决定。

以下代码片段展示了你应该配置的一些元素,没错,就是注解。

public interface UserManager {
    public UserDO get(int id);
    public void insert(UserDO user);
    public void update(int id);
}
@Component
public class UserManagerImpl implements UserManager{
    @Autowired
    private UserDao userDao;
    ...
    @Override
    @Transactional(readOnly = false,propagation = Propagation.REQUIRED)
    public void insert(UserDO user) {
        this.userDao.insert(user);
    }
}

是不是很简单?等等,别高兴太早。

参数

不要觉得是官方驱动,就可以任性的用。这套jdbc驱动的参数还是非常丰富的,学习的代价也就高了些。在一些小流量下运行的很好,但在高并发环境下会频繁发生问题。这里只挑最重要的说下。

一个虚拟连接,对应着一个真正的主库连接和多个从库连接。对于主机的存活和重新上线,我们要考虑三种情况:

  • Master都死掉了
  • Slave都死掉了
  • Master、Slave全都死掉了

无论哪种情况,MySQL驱动都表现出一些奇怪的行为,默认参数是不好使的。

你可能以为驱动也就是管理一下几个连接而已,但情况比这复杂的多。首先给张图看下这个复杂的关系。


1、readFromMasterWhenNoSlaves 当所有的salve死掉后,此参数用来控制主库是否参与读。如果从库的流量很大,配置此参数对主库有很大风险;但如果你关掉,请求则会快速失败。
2、loadBalanceStrategy 策略用来指定从库的轮询规则。有轮询,也有权重,也可以指定具体的策略实现。当你维护或者迁移某个实例时,先置空流量,这会非常有用。或许,你会给某DB一个预热的可能。
3、allowMasterDownConnections 如果主机当机,当连接池获取新的连接时,会失败。但如果打开此参数,则虚拟连接只会创建Slave连接组,整个连接会降级为只读,不论你设置了什么注解。
4、allowSlavesDownConnections 如果没有只读库了,是否允许创建新的连接。在这种情况下,此参数开启,读操作有很大可能会失败。
5、retriesAllDown 当所有的hosts都无法连接时重试的最大次数(依次循环重试),默认为120。重试次数达到阈值仍然无法获取有效链接,将会抛出SQLException。
6、autoReconnect 实例既然有下线、就有上线。上线以后要能够继续服务,此参数用来控制断线情况下自动重连而不抛出异常。这会破坏事务的完整性,但还是默认开启。

然而MySQL驱动提供了更加丰富的参数来控制这个过程,如果你的业务要求比较苛刻,这些参数可能要测个遍才会放心。
但大多数情况下,它运行的很好。

管理

仅有配置参数,此协议就算一个半成品而已。所幸,此驱动提供了JMX管理的方式,可以基于其做一些配置变更之类的功能。市面上并没有这种配置管理工具,可能还是因为它太小众了。

 public abstract void addSlaveHost(String groupFilter, String host) throws SQLException;
 public abstract void removeSlaveHost(String groupFilter, String host) throws SQLException;
 public abstract void promoteSlaveToMaster(String groupFilter, String host) throws SQLException;
 public abstract void removeMasterHost(String groupFilter, String host) throws SQLException;
 public abstract String getMasterHostsList(String group);
 public abstract String getSlaveHostsList(String group);
 public abstract String getRegisteredConnectionGroups();
 public abstract int getActiveMasterHostCount(String group);
 public abstract int getActiveSlaveHostCount(String group);
 public abstract int getSlavePromotionCount(String group);
 public abstract long getTotalLogicalConnectionCount(String group);
 public abstract long getActiveLogicalConnectionCount(String group);

我们顺便提一下阿里的德鲁伊数据库连接池。如图,某些功能,只支持默认的单连接,对multi-host支持还是有限。

结尾

MySQL 5.1.x官方驱动出了这么个东西以后,其实宣告了很多小公司自研的某些小中间件的死亡。翻来服务,改写JDBC,不过就是为了管理个连接集合。

本文对象为专注基础设施研发的同学。有人看到的,不过是一堆参数而已;而真正去深入使用的人,会感到背脊通彻的寒冷。

当它小众时,你对它不屑一顾。然而当你一旦采用了某种方案,你却希望全世界都是关于它的描写。人生从来就没那么幸运,很多坑,还需要自己来踩。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
关系型数据库 MySQL Java
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
64 0
|
9天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
24 4
|
29天前
|
Java 关系型数据库 MySQL
mysql5.7 jdbc驱动
遵循上述步骤,即可在Java项目中高效地集成MySQL 5.7 JDBC驱动,实现数据库的访问与管理。
116 1
|
1月前
|
Java 关系型数据库 MySQL
【编程基础知识】Eclipse连接MySQL 8.0时的JDK版本和驱动问题全解析
本文详细解析了在使用Eclipse连接MySQL 8.0时常见的JDK版本不兼容、驱动类错误和时区设置问题,并提供了清晰的解决方案。通过正确配置JDK版本、选择合适的驱动类和设置时区,确保Java应用能够顺利连接MySQL 8.0。
137 1
|
5月前
|
Prometheus 监控 关系型数据库
数据库同步革命:MySQL GTID模式下主从配置的全面解析
数据库同步革命:MySQL GTID模式下主从配置的全面解析
616 0
|
4月前
|
存储 SQL 关系型数据库
(六)MySQL索引原理篇:深入数据库底层揭开索引机制的神秘面纱!
《索引原理篇》它现在终于来了!但对于索引原理及底层实现,相信大家多多少少都有了解过,毕竟这也是面试过程中出现次数较为频繁的一个技术点。在本文中就来一窥`MySQL`索引底层的神秘面纱!
340 5
|
5月前
|
运维 容灾 关系型数据库
介绍几种 MySQL 官方高可用方案
MySQL 官方提供了多种高可用部署方案,从最基础的主从复制到组复制再到 InnoDB Cluster 等等。本篇文章以 MySQL 8.0 版本为准,介绍下不同高可用方案架构原理及使用场景。
1172 3
介绍几种 MySQL 官方高可用方案
|
4月前
|
存储 关系型数据库 MySQL
利用 MySQL 克隆插件搭建主从
MySQL 的 Clone 插件是一个强大的功能,首次引入于 MySQL 8.0.17 版本。简单来说,Clone Plugin 是一款物理克隆数据工具,它能够帮助我们快速、高效地克隆或复制数据库,极大地简化了数据库迁移、备份和恢复的过程,让我们在处理大量数据时更加得心应手。本篇文章我们一起来学习下如何使用克隆插件。
82 2
|
4月前
|
运维 关系型数据库 MySQL
【实操记录】MySQL主从配置
本文使用MySQL原生支持的主从同步机制,详细记录了配置步骤及运维操作方法,可供大家直接参考、使用。 本文假设已经部署了两台主机的MySQL软件,且数据库服务正常,详细部署步骤可本站搜索:"mysql二进制安装包部署"
142 0
|
4月前
|
SQL 关系型数据库 MySQL
【MySQL】主从异步复制配置
【MySQL】主从异步复制配置
93 1