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

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 我们经常使用的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,不过就是为了管理个连接集合。

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

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

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
关系型数据库 MySQL 开发工具
MySQL5.7主从配置(Docker)
MySQL5.7主从配置(Docker)
726 0
|
1月前
|
SQL 关系型数据库 MySQL
解决MySQL主从慢同步问题的常见的解决方案:
解决MySQL主从慢同步问题的方法有很多,以下是一些常见的解决方案: 1. 检查网络连接:确保主从服务器之间的网络连接稳定,避免网络延迟或丢包导致数据同步缓慢。 2. 优化数据库配置:调整MySQL的配置参数,如增大binlog文件大小、调整innodb_flush_log_at_trx_commit等参数,以提高主从同步性能。 3. 检查IO线程和SQL线程状态:通过SHOW SLAVE STATUS命令检查IO线程和SQL线程的状态,确保它们正常运行并没有出现错误。 4. 检查主从日志位置:确认主从服务器的binlog文件和位置是否正确,避免由于错误的日志位置导致同步延迟。 5.
116 1
|
3月前
|
关系型数据库 MySQL
若依框架----如何降低mysql驱动版本?
若依框架----如何降低mysql驱动版本?
58 3
|
4月前
|
负载均衡 关系型数据库 MySQL
MySQL主从架构的搭建
MySQL主从架构的搭建
58 3
|
3月前
|
SQL 关系型数据库 MySQL
MySQL-主从架构的搭建
MySQL-主从架构的搭建
52 0
|
1月前
|
分布式计算 关系型数据库 MySQL
Sqoop【部署 01】CentOS Linux release 7.5 安装配置 sqoop-1.4.7 解决警告并验证(附Sqoop1+Sqoop2最新版安装包+MySQL驱动包资源)
【2月更文挑战第8天】Sqoop CentOS Linux release 7.5 安装配置 sqoop-1.4.7 解决警告并验证(附Sqoop1+Sqoop2最新版安装包+MySQL驱动包资源)
93 1
|
6天前
|
关系型数据库 MySQL API
常见MySQL驱动介绍
常见MySQL驱动介绍。
9 2
|
9天前
|
SQL 关系型数据库 MySQL
mysql主从同步出错解决办法
mysql主从同步出错解决办法
7 0
|
4月前
|
消息中间件 关系型数据库 MySQL
在kafka connect 同步 mysql 主从数据库
在kafka connect 同步 mysql 主从数据库
43 0
|
4月前
|
关系型数据库 MySQL 数据库
分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离(一)
分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离(一)