前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >”MySQL官方驱动“主从分离的神秘面纱(扫盲篇)

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

作者头像
xjjdog
发布2019-09-24 16:39:38
4890
发布2019-09-24 16:39:38
举报
文章被收录于专栏:架构专题架构专题

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

JDBC驱动

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

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

我们平常的jdbc连接是这样

代码语言:javascript
复制
jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8

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

代码语言:javascript
复制
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的写法,更加直观

代码语言:javascript
复制
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了,而是这个

代码语言:javascript
复制
com.mysql.jdbc.ReplicationDriver

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

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

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

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

代码语言:javascript
复制
public interface UserManager {
   public UserDO get(int id);
   public void insert(UserDO user);
   public void update(int id);
}
代码语言:javascript
复制
@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管理的方式,可以基于其做一些配置变更之类的功能。市面上并没有这种配置管理工具,可能还是因为它太小众了。

代码语言:javascript
复制
 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,不过就是为了管理个连接集合。

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-12-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小姐姐味道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JDBC驱动
  • 代码层
  • 参数
  • 管理
  • 结尾
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档