sharding-jdbc metadata load优化(4.1.1版本)

背景

系统启动时,会注意sharding-jdbc提示加载metadata

于是想看看里面做了什么事情

问题追踪

debug后可以观察走到了该类

org.apache.shardingsphere.shardingjdbc.jdbc.core.context.ShardingRuntimeContext#loadSchemaMetaData

先看这个shardingRuntimeContext相关的类关系,对于多数据源的场景,会定义一个加载元数据的方法供子类实现,主要关注loadSchemaMetaData方法

重点关注ShardingRuntimeContext里的逻辑

对于分库的数据库加载,可以看到有两个问题

1.对于分库的表元数据加载,是单线程执行的,即使把max.connections.size.per.query调大,也不会有效率提升

2.某些规则的元数据与分片表的元数据是一致的,存在重复加载情况

问题解决

分表配置中,某些规则的acutal_data_nodes是一样的,根据该字段分组,对于分表规则相同的配置,可以加载一份即可

在本项目中复写对应的类增强下对应的load方法,新增了groupBy加载的配置支持

//根据配置选择原生加载还是groupBy加载
public SchemaMetaData load(final DatabaseType databaseType) throws SQLException {SchemaMetaData result = useGroupMetaLoad?loadShardingSchemaMetaDataGroupByActualDataNodes(databaseType):loadShardingSchemaMetaData(databaseType);result.merge(loadDefaultSchemaMetaData(databaseType));return result;}//原有逻辑private SchemaMetaData loadShardingSchemaMetaData(final DatabaseType databaseType) throws SQLException {LOGGER.info("Loading {} logic tables' meta data.", shardingRule.getTableRules().size());Map<String, TableMetaData> tableMetaDataMap = new HashMap<>(shardingRule.getTableRules().size(), 1);for (TableRule each : shardingRule.getTableRules()) {tableMetaDataMap.put(each.getLogicTable(), load(each.getLogicTable(), databaseType));}return new SchemaMetaData(tableMetaDataMap);}
//新逻辑private SchemaMetaData loadShardingSchemaMetaDataGroupByActualDataNodes(final DatabaseType databaseType) throws SQLException {LOGGER.info("Loading {} logic tables' meta data.", shardingRule.getTableRules().size());
//根据actualDataNodes分组,key为要查询的逻辑表名,value为同个acutalDataNodes的表名Map<String, Set<String>> sameNodeMap = groupByActualDataNodes(shardingRule.getShardingDataSourceNames().getShardingRuleConfig().getTableRuleConfigs());int maxQuery=Math.min(CORES*2,maxConnectionsSizePerQuery);List<List<String>> tableGroups = Lists.partition(new ArrayList<>(sameNodeMap.keySet()), Math.max(sameNodeMap.size() / maxQuery, 1));Map<String, TableMetaData> tableMetaDataMap = new HashMap<>(shardingRule.getTableRules().size(), 1);if (tableGroups.size() == 1 || isCheckingMetaData) {for (String sameLogicTable : tableGroups.get(0)) {TableMetaData load = load(sameLogicTable, databaseType);Set<String> value = sameNodeMap.get(sameLogicTable);for (String s : value) {tableMetaDataMap.put(s, load);}}} else {//async,模仿已有写法ExecutorService executorService = Executors.newFixedThreadPool(Math.min(tableGroups.size(), maxQuery));try {Collection<Future<Map<String, TableMetaData>>> futures = new LinkedList<>();for (List<String> each : tableGroups) {futures.add(executorService.submit(() -> {Map<String, TableMetaData> tableMetaData = new HashMap<>();for (String s : each) {tableMetaData.put(s, load(s, databaseType));}return tableMetaData;}));}for (Future<Map<String, TableMetaData>> each : futures) {try {Map<String, TableMetaData> m = each.get();for (String s : m.keySet()) {Set<String> sameTable = sameNodeMap.get(s);for (String string : sameTable) {tableMetaDataMap.put(string, m.get(s));}}} catch (final InterruptedException | ExecutionException ex) {if (ex.getCause() instanceof SQLException) {throw (SQLException) ex.getCause();}Thread.currentThread().interrupt();}}} finally {executorService.shutdown();}}LOGGER.info("Actual {} logic tables' meta data loaded.", sameNodeMap.size());return new SchemaMetaData(tableMetaDataMap);}private Map<String, Set<String>> groupByActualDataNodes(Collection<TableRuleConfiguration> configurations) {Map<String, List<TableRuleConfiguration>> collect = configurations.stream().collect(Collectors.groupingBy(TableRuleConfiguration::getActualDataNodes));Map<String, Set<String>> containSet = new HashMap<>();for (Entry<String, List<TableRuleConfiguration>> entry : collect.entrySet()) {//同一个datasource分为一组Map<String,Set<String>> sameDatabaseMap=new HashMap<>();entry.getValue().stream().map(TableRuleConfiguration::getLogicTable).forEach(e->{String currentDatabase = getFirstDataSourceNameByLogicTableName(e);Set<String> tableNames = sameDatabaseMap.getOrDefault(currentDatabase, new HashSet<>());tableNames.add(e);sameDatabaseMap.put(currentDatabase,tableNames);});for (Entry<String, Set<String>> sameDatabaseSet : sameDatabaseMap.entrySet()) {Set<String> value = sameDatabaseSet.getValue();containSet.put(value.iterator().next(),value);}}return containSet;}private String getFirstDataSourceNameByLogicTableName(String logicTableName){TableRule tableRule = shardingRule.getTableRule(logicTableName);DataNode dataNode = tableRule.getActualDataNodes().iterator().next();return dataNode.getDataSourceName();}

这样就达到了优化的效果

并添加配置

spring.shardingsphere.props.max.connections.size.per.query=10
spring.shardingsphere.props.group.metadata.load.enabled=true

运行结果如下,减少重复的表元数据加载,并采用异步加载,启动速度快了一些

配置修改后的关注问题

可以关注到对于max.connections.size.per.query,我们从1→10,有什么需要注意的呢?

1.createConnections

我们可以先看一下一次查询的执行过程

1.org.apache.shardingsphere.underlying.pluggble.prepare.BasePrepareEngine#prepare

这里主要解析sql,做路由&生成需要执行的单元信息,生成执行上下文

2.接下来是重点关注的逻辑

根据执行上下文初始化执行器

我们需要关注的是生成执行单元中获取链接的逻辑

具体在 org.apache.shardingsphere.shardingjdbc.executor.PreparedStatementExecutor#obtainExecuteGroups

一路debug会走到

我们需要关注的是生成执行单元中获取链接的逻辑

具体在 org.apache.shardingsphere.shardingjdbc.executor.PreparedStatementExecutor#obtainExecuteGroups

一路debug会走到

在这里可以看到该配置的影响,他会根据实际要执行的sql单元,确认链接模式,关于链接模式的进一步说明,可以参考官网说明

链接模式说明
MEMORY_STRICTLY
内存限制模式,当对单个物理库查询时,链接数足够时会采用此模式,单个库有多个链接
CONNECTION_STRICTLY
链接限制模式,对单个物理库查询时,只有0或1个链接可用

这两种限制模式在创建链接时有差异

链接限制模式直接创建,对于内存限制模式,需要一次性获取执行链接

主要影响是单个逻辑sql有多个分片sql执行场景时所需要的连接数,由于我们使用的druid链接池,获取链接的方法为com.alibaba.druid.pool.DruidDataSource#getConnectionDirect

对于配了超时(druid.maxWait),如果maxActive<max.connections.size.per.query,会报无法获取足够链接的错误

对于没配超时,会出现一直等待的场景com.alibaba.druid.pool.DruidDataSource#takeLast,造成假死

重点保证链接池的maxActive>=max.connections.size.per.query即可

2.executeQuery

org.apache.shardingsphere.shardingjdbc.executor.PreparedStatementExecutor#getQueryResult

内存限制模式,会把链接hold住,相当于游标方式获取结果,对于链接限制模式,会把数据加载到内存,链接可以释放

其他

1.本地启动时也可以配置druid链接池进行异步初始化,加快启动速度

spring.datasource.druid.async-init=true

2.在sharding-jdbc执行过程中,会发现如下逻辑

会抽取第一个任务给主线程执行,其他交由线程池异步处理

减少主线程的空等待时间,我们一些异步多任务的执行也可以参考一下该做法 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/423409.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式-QT学习-小练习

1. 实现多窗口 2. 给按键增加图标 3. 动图展示 结果演示&#xff1a; Mul_Con main.cpp #include "widget.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }一、第一个窗口展示 …

Android 测试机

要测手机应用&#xff0c;直接挂电脑上跑虚拟机的话&#xff0c;怀疑电脑都要起火了。 eBay 上买了个新的机器&#xff0c;也才 100 美元多点&#xff0c;机器都没有拆过&#xff0c;电池是完全无电的状态。 操作系统是 Android 12 的版本&#xff0c;升级到 Android 14 后&am…

苹果CMS vs. 海洋CMS:哪个系统更易于百度收录?

在选择网站内容管理系统&#xff08;影视网站选择那个CMS&#xff1f;&#xff09;时&#xff0c;收录效率和优化能力是关键考量因素。苹果CMS和海洋CMS都是受欢迎的选项&#xff0c;但在百度收录效果上&#xff0c;苹果CMS表现得更为出色。以下将详细探讨苹果CMS为何在百度收录…

uni-app生命周期(三)

文章目录 一、uni-app的生命周期二、应用生命周期三、页面的生命周期函数1.简介2.页面加载时序介绍3.页面加载常见问题4.页面加载顺序4.部分生命周期介绍 四、组件的生命周期函数 一、uni-app的生命周期 应用生命周期&#xff08;整个App的生命周期&#xff09; 在app.vue里面…

是德keysight N7552A 9G电子校准件2端口

是德keysight N7552A 9G电子校准件2端口 频率范围为直流到 9 GHz 支持 N 型和 3.5 mm 连接器 更小、更轻巧的 2 端口电子校准件 零等待时间&#xff0c;实现更快校准 兼具电子校准件的便利性与经济型机械套件的性能 N7552A 支持是德科技的 PNA-X、PNA、ENA、PXI 矢量网络分…

四、滑动窗口-算法总结

文章目录 四、滑动窗口4.1 模板4.2 示例4.2.1 最小覆盖子串4.2.2 字符串的排列4.2.3 找到字符串中所有字母异位词4.2.4 无重复字符的最长子串 四、滑动窗口 4.1 模板 /* 滑动窗口算法框架 */ void slidingWindow(string s, string t) {unordered_map<char, int> need, …

QT::QComboBox自定义左击事件信号

因为QComboBox没有自定义的clink信号&#xff0c;所以自己新建一个MyComBox类继承QComboBox&#xff0c;并且添加自定义的左击信号&#xff0c;以及使用该信号连接一个槽函数 mycombobox.h #ifndef MYCOMBOBOX_H #define MYCOMBOBOX_H#include <QComboBox> #include &l…

在 Mac 上安装虚拟机怎么样,安装虚拟机与直接安装 Windows 系统有区别吗?

随着跨系统操作的不断发展&#xff0c;虚拟机技术在生产力领域扮演着越来越重要的角色。Mac作为一款主流的操作系统&#xff0c;也有着运行虚拟机的能力。接下来给大家介绍Mac装虚拟机好不好&#xff0c;Mac装虚拟机和装Windows系统一样吗的具体内容。 Mac装虚拟机好不好 Mac…

通信工程学习:什么是FDMA频分多址

FDMA&#xff1a;频分多址 FDMA&#xff08;Frequency Division Multiple Access&#xff0c;频分多址&#xff09;是一种在无线通信领域广泛应用的多址技术。该技术通过将可用的频谱资源按频率划分&#xff0c;把传输频带划分为若干较窄且互不重叠的子频带&#xff08;或称信道…

SprinBoot+Vue爱老助老服务平台的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

c/c++面试100道

1.一道笔试题解析_哔哩哔哩_bilibili P20&#xff1a;#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER) 1、 offsetof 宏是 C 语言中用于计算结构体成员相对于结构体起始地址的偏移量的宏定义。这个宏的定义如下&#xff1a; #define offsetof(TYPE, …

JavaScript模块化——ES6模块化规范

作者&#xff1a;CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 使用环境&#xff1a;vscode Chrome浏览器 1.ES6 1.1ES6介绍 ES6的全称是ECMAScript 6&#xff0c;也称为ES2015&#xff0c;是JavaScript的一个重要版本&#xff0c;它引入了许多新特性和改进&#xf…

Linux搭建邮箱服务器(简易版)

本章是上一文档的简易版本搭建方式更为快速简洁&#xff08;只需要两条命令即可搭建&#xff09;&#xff0c;如果想了解更详细一些可以看我上一文档 Linux接发邮件mailx_linux mailx o365-CSDN博客文章浏览阅读857次&#xff0c;点赞25次&#xff0c;收藏19次。本文详细描述了…

独立站内容营销SOP 1.0 丨出海笔记

提到内容营销&#xff0c;可能很多朋友都听过但没深入做&#xff0c;国内跨境独立站通过内容营销做的大流量的目前不多&#xff0c;哪怕大如 Shein, Anker&#xff0c;大部分时候还是在买量获客的阶段。 但大家只要明白一点即可&#xff1a;内容做得好不好&#xff0c;直接影响…

文档智能:OCR+Rocketqa+layoutxlm

此次先记录LayoutLMv2&#xff0c;梳理相关论文&#xff0c;记录如下&#xff1a; 首先认识一下 visually-rich document understanding tasks → \to → VrDU 其次&#xff0c;the text fields of interest&#xff0c;与图像识别的感兴趣区域 region of Interest 类似&…

【脑机接口】脑机接口性能的电压波形的尖峰分类和阈值比较

Comparison of spike sorting and thresholding of voltage waveforms for intracortical brain–machine interface performance 脑机接口性能的电压波形的尖峰分类和阈值比较论文下载&#xff1a;摘要1 介绍2 方法2.1数据获取2.2spike sorting 技术2.3神经数据分析 3结果3.1神…

社交媒体的未来:Facebook如何通过AI技术引领潮流

在数字化时代的浪潮中&#xff0c;社交媒体平台不断演变&#xff0c;以适应用户需求和技术发展的变化。作为全球领先的社交媒体平台&#xff0c;Facebook在这一进程中扮演了重要角色。尤其是人工智能&#xff08;AI&#xff09;技术的应用&#xff0c;正在深刻地改变Facebook的…

搜索树和Map

一.搜索树 1.概念 二叉搜索树又叫二叉排序树&#xff0c;它可以是一颗空树也可以是具有以下性质的二叉树 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值它的左子树也分别为二…

NR intra-freq和inter-freq测量

intra-freq 测量和inter-freq测量可以分为以下几类&#xff1a; 1 SSB based intra-freq 测量&#xff1a;serving cell SSB的center freq与邻区 SSB的center freq 相同并且两个SSB 的SCS也相同。 2 SSB based inter-freq 测量&#xff1a;serving cell SSB的center freq与邻…

用Qt 对接‌百度语音识别接口

一 、前期准备工作 1&#xff0c;搭建好开发环境&#xff1b; 2&#xff0c;注册百度云平台&#xff0c;获取语音相关东西&#xff0c; 短语音识别标准版_短语音识别-百度AI开放平台 (baidu.com) 3&#xff0c;涉及到的Qt 类有 QAudioFormat&#xff0c;QAudioDeviceInfo&a…