生成式AI领域的最新成果都在这里!抢 QCon 展区门票 了解详情
写点什么

MySQL-JDBC Loadbalance 深入解析

  • 2019-10-21
  • 本文字数:3074 字

    阅读完需:约 10 分钟

MySQL-JDBC Loadbalance深入解析

公司的整个电商系统搭建在华为云上,根据老总的估计,上线 3 个月之后日订单量会达到百万级别,保守估计 3 个月之后总订单个数预计会有 5 千万。MySQL 单表达到千万级别,就会出现明显的性能问题。


根据如此规模的数据,当时考虑了 2 套解决方案:


方案一


在业务上根据用户 ID 做拆分,将数据打散放在 5 台 32U128G 的华为云 RDS 上边


方案二


直接使用华为云的分布式数据库中间件 DDM


方案一的好处是,分片算法全部在业务上实现,整个方案都在自己的控制下。后续问题定位,方案修改都会好很多;坏处是,整个方案需要业务代码支撑,访问到做了拆分的数据都需要做特殊处理,代价还是比较大的,而且对开发人员的能力要求很高。后续运维的工作也比较大。


方案二的好处是,直接使用云服务后续不需要担心运维的事情,另外 DDM 从中间件层屏蔽了分库分表的具体实现,业务可以当做单库来操作,易用性以及对代码的要求、对开发人员的要求都会低了很多。缺点就是,使用了 DDM 之后,对华为云的粘性会大很多。


综合考虑了两个方案的优缺点,最终选择了方案二,主要是基于对华为云技术能力和后续蓬勃发展的信心。


对 DDM 做了一定的调研,的确是一个非常不错的分库分表服务。支持超大规模数据,10 备于单机数据库的超强性能,百万并发,读写分离,支持平滑扩容等等。。。优点数不胜数~


搭建到华为云之后,一直平稳运行,但是前阵子出了个奇怪的问题,在 DDM 技术专家的协助下,很快定位了出来,结果是 MySQL-JDBC 的一个 bug 导致。作为一个具有打破砂锅问到底、不破楼兰誓不还的程序员,决定对 MySQL 的相关参数做个详细的分析,免得从一个坑里边爬出来又进了另外一个。

Loadbalance 模式说明

为了提供高性能,百万并发,DDM 自身是以无状态的集群形式对外提供的。内部怎么做的我们不清楚,能看到的是,每个 DDM 提供了多个访问地址,每个库的访问 url 类似于:jdbc:mysql:loadbalance://192.168.0.35:5066,192.168.0.192:5066,192.168.0.175:5066,192.168.0.139:5066/orderdb?loadBalanceAutoCommitStatementThreshold=5


从访问的 url 看,内部应该是多台 DDM 节点的,实际上从我们测试的情况看,访问任何一台的效果都是一样的。猜测,内部的交互应该是类似如下图的:



跟 DDM 的技术专家求证,的确是如此的,心里有点小得意~~


我们的代码全部是 java 的代码,连接池用的是 druid,根据 DDM 的指导,将 url 配置好就能正常访问了。感觉关健的就在 loadbalance 这个,应该是告诉了驱动,通过负载均衡方式访问 DDM。在网上查了下,这种方式是直接在驱动层面做的负载均衡,相比通过负载均衡器的方式,少了一次网络转发,怪不得效率会这么高。不过,APP 到底是访问哪个 DDM,内部机制是什么样子的?这些在网上查了下,都是语焉不详,没办法只好从 MySQL JDBC 的源码入手了。


驱动的源码是托管在 github 上,我们当前用的是 DDM 推荐的 5.1.44 版本的:https://github.com/mysql/mysql-connector-j/tree/5.1.44


核心的就是几个 Loadbalance 开头的类:



代码比较多,其他的就不多说了,最关键的就是下边这块代码:


LoadBalancedConnectionProxy.java 类的 pickNewConnection()函数:


这个函数在创建连接对象、一个事务提交或者回滚都会调用,作用就是轮换下一个 DDM 节点。这块代码的逻辑就是,根据一定的负载均衡策略挑选一个节点的连接,做个基本的连接有效性探测,然后将当前连接的状态同步到新连接(见 Table 2 MultiHostConnectionProxy.syncSessionState())。同步完毕,就把当前使用的连接设置为新挑选的连接。如果所有的连接都不可用,就把当前状态设置为了 Closed 状态。看着快代码,感觉 MySQL 的有些代码也不严谨,比如如果在获取新连接的时候,如果抛了 SQLException 出来,这个异常就直接被吃掉了,不会抛出去,也不会有任何信息记录下来,这个对后续的问题定位还是很不方便的,不知道是出于什么考虑的。


Table 1 LoadBalancedConnectionProxy.pickNewConnection()   synchronized void pickNewConnection() throws SQLException {       if (this.isClosed && this.closedExplicitly) {           return;       }       if (this.currentConnection == null) { // startup           this.currentConnection = this.balancer.pickConnection(this, Collections.unmodifiableList(this.hostList),                   Collections.unmodifiableMap(this.liveConnections), this.responseTimes.clone(), this.retriesAllDown);           return;       }       if (this.currentConnection.isClosed()) {           invalidateCurrentConnection();       }       int pingTimeout = this.currentConnection.getLoadBalancePingTimeout();       boolean pingBeforeReturn = this.currentConnection.getLoadBalanceValidateConnectionOnSwapServer();       for (int hostsTried = 0, hostsToTry = this.hostList.size(); hostsTried < hostsToTry; hostsTried++) {           ConnectionImpl newConn = null;           try {               newConn = this.balancer.pickConnection(this, Collections.unmodifiableList(this.hostList), Collections.unmodifiableMap(this.liveConnections), this.responseTimes.clone(), this.retriesAllDown);               if (this.currentConnection != null) {                   if (pingBeforeReturn) {                       if (pingTimeout == 0) {                           newConn.ping();                       } else {                           newConn.pingInternal(true, pingTimeout);                       }                   }                   syncSessionState(this.currentConnection, newConn);
} this.currentConnection = newConn; return; } catch (SQLException e) { if (shouldExceptionTriggerConnectionSwitch(e) && newConn != null) { // connection error, close up shop on current connection invalidateConnection(newConn); } } } // no hosts available to swap connection to, close up. this.isClosed = true; this.closedReason = "Connection closed after inability to pick valid new connection during load-balance."; }


Table 2 MultiHostConnectionProxy.syncSessionState() static void syncSessionState(Connection source, Connection target, boolean readOnly) throws SQLException { if (target != null) { target.setReadOnly(readOnly); } if (source == null || target == null) { return; }target.setAutoCommit(source.getAutoCommit()); target.setCatalog(source.getCatalog()); target.setTransactionIsolation(source.getTransactionIsolation()); target.setSessionMaxRows(source.getSessionMaxRows()); }
复制代码


MySQL-JDBC Loadbalance 参数说明


明白了 MySQL-JDBC 的 Loadbalance 的相关机制,最重要的还是要对相关的参数有个详细的了解,并且设置有效的值,Loadbalance 相关一共有十几个参数,几个比较关键的如下表所示:




其他还有几个参数,一般用不到,也就不罗列出来了。


本文转载自公众号中间件小哥(ID:huawei_kevin)。


原文链接:


https://mp.weixin.qq.com/s/baxyONDEHTlPrSwszjo3Jw


2019-10-21 14:051286

评论

发布
暂无评论
发现更多内容

软件测试 | 跨平台API对接

测吧(北京)科技有限公司

测试

一键接入 ChatGPT,让你的QQ群变得热闹起来

极客飞兔

人工智能 聊天机器人 openai ChatGPT

1.基于Label studio的训练数据标注指南:信息抽取(实体关系抽取)、文本分类等

汀丶人工智能

数据标注 关系抽取 labelstudio 实体抽取

政企专属的IM即时通讯平台,促进团队安全沟通与协作

WorkPlus

软件开发,如何同时保证效率和质量?

SoFlu软件机器人

博睿数据入选中国信通院《高质量数字化转型产品及服务全景图》

博睿数据

可观测性 智能运维 博睿数据 信通院 高质量发展

软件测试/测试开发 | 测试平台开发-前端开发之数据展示与分析

测试人

软件测试 自动化测试 测试开发 测试平台

如何通过C#和VB.NET压缩PDF文档

Geek_249eec

C# .net PDF VB.NET

百度点石隐私计算平台与FATE开源框架实现互联互通

百度安全

人工智能 开源 联邦学习 开发

吹爆Alibaba自研的Spring全能笔记,建议人手一份!

小小怪下士

Java spring springmvc springboot

MAXON indoor or outdoor tracking and positioning tech with Wi-Fi Bluetooth Lora UWB AoA

wifi6module

LoRa wifi solution blueteeth UWB AOA

Java Agent场景性能测试分析优化经验分享

华为云开发者联盟

开发 华为云 java 华为云开发者联盟 企业号 3 月 PK 榜

Spring Boot是如何内嵌Tomcat的?原理剖析

做梦都在改BUG

Java tomcat Spring Boot

从ChatGPT的技术发展角度解析未来智能化的发展方向

加入高科技仿生人

人工智能 AI 低代码 智能化 ChatGPT

软件测试/测试开发 | 学做测试平台开发-Vuetify 框架

测试人

软件测试 测试开发 测试平台

还在头疼你的API,送你一个保姆级的API设计管理平台

华为云开发者联盟

云计算 开发 华为云 华为云开发者联盟 企业号 3 月 PK 榜

瓴羊Quick BI提供移动端自助分析解决方案, 易于性高于 Fine BI、 Smart BI

流量猫猫头

大数据 数据分析

软件测试 | Vuetify框架

测吧(北京)科技有限公司

测试

Centos 环境搭建

流火

Linux centos Centos 7

坚如磐石:TiDB 基于时间点的恢复(PiTR)特性优化之路丨6.5 新特性解析

PingCAP

TiDB

极狐GitLab DevSecOps 为企业许可证安全合规保驾护航

极狐GitLab

许可证 DevSecOps 极狐GitLab 安全左移 安全合规

PHP中出现Cannot modify header information - headers already sent

ModStart

国内“谁”能实现chatgpt,对MOSS、ChatYuan给出关键技术简评,一文带你深入了解宏观技术路线| 社区征文

汀丶人工智能

ChatGPT

主题别名(Topic Alias)-MQTT 5.0新特性

EMQ映云科技

物联网 IoT mqtt 企业号 3 月 PK 榜 主题别名

软件测试 | ECharts简介与安装

测吧(北京)科技有限公司

测试

卷麻了,业务同事都能开发软件,我简直无地自容……

这我可不懂

低代码 低代码开发平台 JNPF

直播预告 | 时序数据库的流计算支持

KaiwuDB

流计算 时序数据库 KaiwuDB

如何在服务端渲染fabric.js

ModStart

4道数学题,求解极狐GitLab CI 流水线|第4题:合并列车

极狐GitLab

ci DevOps pipeline runner 合并列车

软件测试 | Android与iOS在app测试时有什么区别?

测吧(北京)科技有限公司

测试

国内“谁”能实现chatgpt,一文带你深入了解宏观技术路线| 社区征文

汀丶人工智能

ChatGPT

MySQL-JDBC Loadbalance深入解析_文化 & 方法_苗永辉_InfoQ精选文章