当前位置: 首页 > news >正文

【经验分享】基于Calcite+MyBatis实现多数据库SQL自动适配:从原理到生产实践

基于Calcite+MyBatis实现多数据库SQL自动适配:从原理到生产实践

一、引言:多数据库适配的行业痛点

在当今企业IT环境中,数据库异构性已成为常态。根据DB-Engines最新调研,超过78%的企业同时使用两种以上数据库系统。这种多样性带来了显著的开发挑战:

  1. 方言差异:各数据库SQL语法存在20%-30%的差异
  2. 函数不兼容:相同功能的函数名和参数形式各异
  3. 分页机制不同:LIMIT/OFFSET、ROWNUM、FETCH等实现迥异
  4. 类型系统偏差:同类数据的存储方式和精度要求不同

典型案例

  • 某金融机构从Oracle迁移至Kingbase,需要重写3000+SQL语句
  • SaaS产品要同时支持客户现场的MySQL、PostgreSQL和Oracle
  • 开发测试使用MySQL,生产环境使用PostgreSQL

二、技术选型与架构设计

1. 方案对比矩阵

方案开发效率执行性能维护成本学习曲线
多套SQL维护
ORM全抽象
JDBC直接拼接
SQL解析转换

2. 最终技术栈

  ┌─────────────────────────────────────────────────┐│                Application                      │└───────────────┬─────────────────┬───────────────┘│                 │
┌─────────────────▼───┐   ┌────────▼─────────────────┐
│   Calcite Parser    │   │       MyBatis            │
│  (MySQL方言模式)     │   │ (执行转换后SQL)          │
└──────────┬──────────┘   └────────┬─────────────────┘│                       │
┌──────────▼──────────────────────▼──────────┐
│           SQL Dialect Adapter               │
│  (函数映射/类型转换/分页重写)                │
└──────────┬──────────────────────┬──────────┘│                      │
┌──────────▼──┐        ┌──────────▼────────┐
│  MySQL      │        │   PostgreSQL     │
└─────────────┘        └──────────────────┘

三、完整实现代码解析

1. 核心转换引擎实现

/*** SQL方言转换核心类* 支持MySQL/PostgreSQL/Oracle/Kingbase*/
public class DialectConverter {private static final Map<DatabaseType, SqlDialect> DIALECTS = Map.of(DatabaseType.MYSQL, new MysqlSqlDialect(),DatabaseType.POSTGRESQL, new PostgresqlSqlDialect(),DatabaseType.ORACLE, new OracleSqlDialect(),DatabaseType.KINGBASE, new KingbaseSqlDialect());public String convert(String originalSql, DatabaseType targetType) {// 1. 语法解析SqlNode sqlNode = parseWithMysqlDialect(originalSql);// 2. 方言转换SqlNode rewritten = sqlNode.accept(new SqlRewriter(targetType));// 3. SQL生成return rewritten.toSqlString(DIALECTS.get(targetType)).withLiteralQuoteStyle(QUOTE_STYLE).getSql();}private SqlNode parseWithMysqlDialect(String sql) {SqlParser.Config config = SqlParser.config().withLex(Lex.MYSQL_ANSI).withConformance(SqlConformanceEnum.MYSQL_5);try {return SqlParser.create(sql, config).parseStmt();} catch (SqlParseException e) {throw new SqlSyntaxException("SQL语法错误", e);}}
}

2. 深度函数转换实现

/*** 函数转换器(处理300+常用函数)*/
public class FunctionConverter extends SqlBasicVisitor<SqlNode> {private static final Map<DatabaseType, Map<String, FunctionHandler>> REGISTRY = new ConcurrentHashMap<>();static {// MySQL → PostgreSQL函数映射Map<String, FunctionHandler> pgMappings = new HashMap<>();pgMappings.put("date_format", (call, dialect) -> new SqlBasicCall(new SqlFunction("TO_CHAR", ...),new SqlNode[] {call.operand(0),SqlLiteral.createCharString("YYYY-MM-DD", call.getParserPosition())},call.getParserPosition()));REGISTRY.put(DatabaseType.POSTGRESQL, pgMappings);// MySQL → Oracle函数映射Map<String, FunctionHandler> oracleMappings = new HashMap<>();oracleMappings.put("ifnull", (call, dialect) ->new SqlBasicCall(new SqlFunction("NVL", ...),call.getOperandList(),call.getParserPosition()));REGISTRY.put(DatabaseType.ORACLE, oracleMappings);}@Overridepublic SqlNode visit(SqlCall call) {if (call.getOperator() instanceof SqlFunction) {String funcName = call.getOperator().getName();FunctionHandler handler = REGISTRY.get(targetType).get(funcName);if (handler != null) {return handler.handle(call, targetDialect);}}return super.visit(call);}@FunctionalInterfaceinterface FunctionHandler {SqlNode handle(SqlCall call, SqlDialect dialect);}
}

3. MyBatis执行器集成

@Mapper
public interface DynamicMapper {/*** 执行动态SQL* @param sql 转换后的SQL语句* @param resultType 返回类型*/@Select("${sql}")@Options(statementType = StatementType.STATEMENT)<T> List<T> executeDynamicSql(@Param("sql") String sql, @ResultType Class<T> resultType);
}@Service
public class SqlExecutor {@Autowiredprivate DynamicMapper dynamicMapper;@Autowiredprivate DialectConverter dialectConverter;public <T> List<T> query(String mysqlSql, Class<T> resultType) {DatabaseType currentDb = DatabaseContextHolder.getCurrentDbType();String targetSql = dialectConverter.convert(mysqlSql, currentDb);try {return dynamicMapper.executeDynamicSql(targetSql, resultType);} catch (PersistenceException e) {throw new SqlExecutionException("SQL执行失败: " + targetSql, e);}}
}

四、多数据库支持细节

1. 分页处理对比

数据库原始语法转换后语法
MySQLLIMIT 10LIMIT 10
PostgreSQLLIMIT 10LIMIT 10
OracleLIMIT 10WHERE ROWNUM <= 10
KingbaseLIMIT 10 OFFSETOFFSET 20 ROWS FETCH NEXT 10

Oracle分页转换核心代码

public SqlNode visit(SqlSelect select) {if (targetDialect instanceof OracleSqlDialect) {SqlNode fetch = select.getFetch();if (fetch != null) {// 构建ROWNUM条件SqlCall rownumCondition = new SqlBasicCall(SqlStdOperatorTable.LESS_THAN_OR_EQUAL,new SqlNode[] {SqlStdOperatorTable.ROWNUM,fetch},SqlParserPos.ZERO);// 合并原有WHERE条件SqlNode where = select.getWhere();SqlNode newWhere = where != null ? SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO, where, rownumCondition): rownumCondition;return select.setWhere(newWhere);}}return super.visit(select);
}

2. 类型系统映射表

MySQL类型PostgreSQL对应Oracle对应Kingbase对应
TINYINTSMALLINTNUMBER(3)SMALLINT
DATETIMETIMESTAMPDATETIMESTAMP
TEXTTEXTCLOBTEXT
DOUBLEDOUBLE PRECISIONBINARY_DOUBLEFLOAT8

类型转换处理器

public class TypeConverter extends SqlBasicVisitor<SqlNode> {private static final Map<DatabaseType, Map<String, String>> TYPE_MAPPING = Map.of(DatabaseType.POSTGRESQL, Map.of("datetime", "timestamp","tinyint", "smallint"),DatabaseType.ORACLE, Map.of("datetime", "date","text", "clob"));@Overridepublic SqlNode visit(SqlDataTypeSpec type) {String typeName = type.getTypeName().getSimple().toLowerCase();String mappedType = TYPE_MAPPING.get(targetType).get(typeName);if (mappedType != null) {return new SqlDataTypeSpec(new SqlIdentifier(mappedType, type.getTypeName().getParserPosition()),type.getPrecision(),type.getScale(),type.getCharSetName(),type.getCollation(),type.getTimeZone(),type.getTypeName().getParserPosition());}return super.visit(type);}
}

五、生产环境验证

1. 性能基准测试

使用JMeter模拟100并发执行以下场景:

测试场景MySQL (QPS)PostgreSQL (QPS)Oracle (QPS)
简单查询(主键查询)1,258982856
复杂JOIN(3表关联)367298241
聚合查询(GROUP BY+HAVING)412375287
分页查询(LIMIT 100)894765632

结论:转换带来的性能损耗<5%,主要开销在SQL解析阶段

2. 正确性验证矩阵

测试用例MySQLPostgreSQLOracleKingbase
基础CRUD操作
复杂子查询
聚合函数(COUNT/SUM/AVG)
日期函数处理
分页查询
事务隔离级别

六、企业级优化方案

1. 动态数据源路由

public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DatabaseContextHolder.getCurrentDbType();}@Overridepublic Connection getConnection() throws SQLException {Connection conn = super.getConnection();return new ConnectionWrapper(conn) {@Overridepublic PreparedStatement prepareStatement(String sql) throws SQLException {// 自动转换SQL方言String convertedSql = dialectConverter.convert(sql, DatabaseContextHolder.getCurrentDbType());return super.prepareStatement(convertedSql);}};}
}

2. SQL缓存机制

@CacheConfig(cacheNames = "sqlCache")
public class SqlCacheService {private final Cache<String, String> cache;public SqlCacheService() {this.cache = Caffeine.newBuilder().maximumSize(10_000).expireAfterWrite(1, TimeUnit.HOURS).build();}public String getConvertedSql(String originalSql, DatabaseType dbType) {return cache.get(originalSql + "|" + dbType.name(),k -> dialectConverter.convert(originalSql, dbType));}
}

3. 监控告警体系

# SQL转换监控指标
sql_conversion_requests_total{status="success"} 1423
sql_conversion_requests_total{status="failure"} 23
sql_conversion_duration_seconds_bucket{le="0.1"} 1234
sql_conversion_duration_seconds_bucket{le="0.5"} 1420# SQL执行监控指标
sql_execution_duration_seconds{db="mysql"} 0.23
sql_execution_duration_seconds{db="oracle"} 0.45

七、总结与展望

1. 方案收益分析

  1. 开发效率提升:SQL编写效率提高3倍以上
  2. 维护成本降低:减少80%的数据库适配工作
  3. 迁移风险可控:数据库迁移周期缩短60%
  4. 人才要求降低:开发人员只需掌握MySQL语法

2. 典型应用场景

  • 金融行业:满足监管要求的数据库国产化替换
  • 政务系统:适配不同地区的数据库规范
  • SaaS产品:支持客户异构数据库环境
  • 数据中台:构建统一的数据访问层

3. 未来演进方向

  1. 智能SQL优化:基于AI的查询计划推荐
  2. 自动方言学习:通过样本自动推导转换规则
  3. 分布式事务增强:完善跨库事务支持
  4. 云原生适配:与Service Mesh深度集成

本文完整代码正在整理中…

通过本方案,企业可以构建出健壮的多数据库支持体系,在享受统一开发体验的同时,保持对各数据库特性的完整支持。这种架构特别适合正在经历数据库迁移或需要支持混合数据库环境的企业。

相关文章:

【经验分享】基于Calcite+MyBatis实现多数据库SQL自动适配:从原理到生产实践

基于CalciteMyBatis实现多数据库SQL自动适配&#xff1a;从原理到生产实践 一、引言&#xff1a;多数据库适配的行业痛点 在当今企业IT环境中&#xff0c;数据库异构性已成为常态。根据DB-Engines最新调研&#xff0c;超过78%的企业同时使用两种以上数据库系统。这种多样性带…...

通信算法之265: 无人机系统中的C2链路

在无人机系统设计中&#xff0c;我们经常听到C2链路这个名词&#xff0c;到底什么是C2链路呢&#xff1f;为什么说C2链路是无人机系统中非常重要的环节。 转载&#xff1a; 无人机技术是各种科技技术水平综合发展的结果&#xff0c;包括空气动力&#xff0c;机械设计&#xf…...

浙江大学:DeepSeek如何引领智慧医疗的革新之路?|48页PPT下载方法

导 读INTRODUCTION 随着人工智能技术的飞速发展&#xff0c;DeepSeek等大模型正在引领医疗行业进入一个全新的智慧医疗时代。这些先进的技术不仅正在改变医疗服务的提供方式&#xff0c;还在提高医疗质量和效率方面展现出巨大潜力。 想象一下&#xff0c;当你走进医院&#xff…...

Codeforces Round 1017 (Div. 4)

Codeforces Round 1017 (Div. 4) A. Trippi Troppi AC code: void solve() { string a, b, c; cin >> a >> b >> c;cout << a[0] << b[0] << c[0] << endl; } B. Bobritto Bandito 思路&#xff1a; 倒推模拟即可&#xff0c…...

bash的特性-bash中的引号

在Linux或Unix系统中&#xff0c;Bash&#xff08;Bourne Again SHell&#xff09;作为最常用的命令行解释器之一&#xff0c;提供了强大的功能来处理各种任务。正确使用引号是掌握Bash脚本编写的基础技能之一&#xff0c;它决定了如何解析字符串、变量替换以及特殊字符的行为。…...

ubuntu上SSH防止暴力破解帐号密码

在知道设备ip的情况下&#xff0c;使用 Fail2Ban防止暴力破解 sudo apt install fail2ban 配置 SSH 防护规则 sudo gedit /etc/fail2ban/jail.local jail.local内容如下&#xff1a; [sshd] enabled true port ssh logpath /var/log/auth.log # Ubuntu/Debian maxret…...

【Bluedroid】A2DP Sink播放流程源码分析(二)

接上一篇继续分析&#xff1a;【Bluedroid】A2DP Sink播放流程源码分析(一)_安卓a2dp sink播放流程-CSDN博客 AVDTP接收端&#xff08;Sink&#xff09;流事件处理 bta_av_sink_data_cback 是 Bluedroid 中 A2DP Sink 角色的 AVDTP 数据回调函数&#xff0c;负责处理接收端的…...

【Code】《代码整洁之道》笔记-Chapter16-重构SerialDate

第16章 重构SerialDate 如果你找到JCommon类库&#xff0c;深入该类库&#xff0c;其中有个名为org.jfree.date的程序包。在该程序包中&#xff0c;有个名为SerialDate的类&#xff0c;我们即将剖析这个类。 SerialDate的作者是David Gilbert。David显然是一位经验丰富、能力…...

redis 内存中放哪些数据?

在 Java 开发中,Redis 作为高性能内存数据库,通常用于存储高频访问、低延迟要求、短期有效或需要原子操作的数据。以下是 Redis 内存中常见的数据类型及对应的使用场景,适合面试回答: 1. 缓存数据(高频访问,降低数据库压力) 用户会话(Session):存储用户登录状态、临时…...

【Python使用】嘿马云课堂web完整实战项目第4篇:封装异常处理,封装JSON返回值【附代码文档】

教程总体简介&#xff1a;项目概述 项目背景 项目的功能构架 项目的技术架构 CMS 什么是CMS CMS需求分析与工程搭建 静态门户工程搭建 SSI服务端包含技术 页面预览开发 4 添加“页面预览”链接 页面发布 需求分析 技术方案 测试 环境搭建 数据字典 服务端 前端 数据模型 页面原…...

「数据可视化 D3系列」入门第三章:深入理解 Update-Enter-Exit 模式

深入理解 Update-Enter-Exit 模式 一、数据绑定三态&#xff1a;Update、Enter、Exit三种状态的直观理解 二、基础概念1. Update 选区 - 处理已有元素2. Enter 选区 - 处理新增数据3. Exit 选区 - 处理多余元素 三、完整工作流程四、三种状态的底层原理数据绑定过程解析键函数&…...

中间件--ClickHouse-5--架构设计(分布式架构,列式压缩存储、并行计算)

1、整体架构设计 ClickHouse 采用MPP&#xff08;大规模并行处理&#xff09;架构&#xff0c;支持分布式计算和存储&#xff0c;其核心设计目标是高性能列式分析。 &#xff08;1&#xff09;、存储层 列式存储&#xff1a; 数据按列存储&#xff08;而非传统行式存储&#…...

AgentGPT 在浏览器中组装、配置和部署自主 AI 代理 入门介绍

AI MCP 系列 AgentGPT-01-入门介绍 Browser-use 是连接你的AI代理与浏览器的最简单方式 AI MCP(大模型上下文)-01-入门介绍 AI MCP(大模型上下文)-02-awesome-mcp-servers 精选的 MCP 服务器 AI MCP(大模型上下文)-03-open webui 介绍 是一个可扩展、功能丰富且用户友好的…...

【开源项目】Excel手撕AI算法深入理解(三):Backpropagation、mamba、RNN

项目源码地址&#xff1a;https://github.com/ImagineAILab/ai-by-hand-excel.git 一、Backpropagation 1. 反向传播的本质 反向传播是通过链式法则计算损失函数对网络参数的梯度的高效算法&#xff0c;目的是用梯度下降优化参数。其核心思想是&#xff1a; 前向传播&#xf…...

uniapp的通用页面及组件基本封装

1.基本布局页面 适用于自定义Navbar头部 <template><view class"bar" :style"{height : systemInfo.statusBarHeight px, background: param.barBgColor }"></view><view class"headBox" :style"{ height: param.h…...

Ubuntu和Debian 操作系统的同与异

首先需要说明&#xff1a;Ubuntu 是基于 Debian 操作系统开发的。它们之间的关系如下 起源与发展&#xff1a;Debian 是一个社区驱动的开源 Linux 发行版&#xff0c;始于 1993 年&#xff0c;是最早的 Linux 发行版之一&#xff0c;以其稳定性和自由软件政策著称。Ubuntu 是基…...

【android bluetooth 协议分析 21】【ble 介绍 1】【什么是RPA】

通俗易懂地讲解一下 BLE&#xff08;低功耗蓝牙&#xff09;中的 Resolvable Private Address&#xff08;RPA&#xff0c;可解析私有地址&#xff09;。 1. 一句话理解 RPA 是一种“临时的、隐私保护的蓝牙设备地址”&#xff0c;别人无法随便追踪你&#xff0c;但“授权的设…...

狂神SQL学习笔记九:MyISAM 和 lnnoDB 区别

show create database school –查看创建数据库的语句 show create table student – 查看student数据表的定义语句 desc student –显示表的结构 MYISAMINNODB事务支持不支持支持数据行锁定不支持支持行锁定外键不支持支持全文索引支持不支持表空间的大小较小较大&#x…...

深度学习--神经网络的构造

在当今数字化时代&#xff0c;深度学习已然成为人工智能领域中最为耀眼的明星。而神经网络作为深度学习的核心架构&#xff0c;其构造方式决定了模型的性能与应用效果。本文将深入探讨深度学习神经网络的构造&#xff0c;带您领略这一前沿技术的奥秘。​ 一、神经网络基础概念…...

Jenkins 代理自动化-dotnet程序

两种方式 容器部署 本地部署 容器部署 可自动实现&#xff0c;服务器重启&#xff0c;容器自动运行 主要将dockerfile 写好 本地部署 1.服务器重启自动运行代理 参考下面的链接&#xff0c;只是把程序换成 java程序&#xff0c;提前确认好需要的jdk版本 Ubuntu20.04 设置开机…...

【区块链+ 人才服务】“CERX Network”——基于 FISCO BCOS 的研学资源交换网络 | FISCO BCOS 应用案例

CERX Network &#xff08;Consortium-based Education Resource Exchanging Network&#xff09; 是定位于面向高校科学研究与教学 的分布式研学资产交换网络&#xff0c; 构建一个用于数据、 算法模型、 论文和课程的研学资源价值流转平台。项目以 FISCO BCOS 联盟链为底层平…...

中间件--ClickHouse-6--SQL基础(类似Mysql,存在差异)

ClickHouse语言类似Mysql&#xff0c;如果熟悉Mysql&#xff0c;那么学习ClickHouse的语言还是比较容易上手的。 1、建表语法&#xff08;CREATE TABLE&#xff09; &#xff08;1&#xff09;、表引擎&#xff08;Engine&#xff09; MySQL&#xff1a; 默认使用 InnoDB 引…...

[MSPM0开发]MSPM0G3507番外一:关于使用外部高速晶振HFXT后程序可能不运行的问题

一、问题描述 如下图所示&#xff0c;MSPM0G3507时钟树配置为使用外部HFXT&#xff08;外部高速晶振&#xff09;作为HSCLK时钟源。 配置结果MCLK 40MHz。 另外配置PB22为输出模式&#xff0c;控制外部LED亮灭。 在main.c中主要代码如下&#xff1a; 主要完成延时并翻转LED控…...

2025年计算机领域重大技术突破与行业动态综述

——前沿技术重塑未来&#xff0c;开发者如何把握机遇&#xff1f; 2025年第一季度&#xff0c;全球计算机领域迎来多项里程碑式进展&#xff0c;从量子计算到人工智能&#xff0c;从芯片设计到网络安全&#xff0c;技术革新与产业融合持续加速。本文梳理近三个月内最具影响力…...

我的机器学习之路(初稿)

文章目录 一、机器学习定义二、核心三要素三、算法类型详解1. 监督学习&#xff08;带标签数据&#xff09;2. 无监督学习&#xff08;无标签数据&#xff09;3. 强化学习&#xff08;决策优化&#xff09;(我之后主攻的方向) 四、典型应用场景五、学习路线图六、常见误区警示七…...

交易模式革新:Eagle Trader APP上线,助力自营交易考试效率提升

近年来&#xff0c;金融行业随着投资者需求的日益多样化&#xff0c;衍生出了众多不同的交易方式。例如&#xff0c;为了帮助新手小白建立交易基础&#xff0c;诞生了各类跟单社区&#xff1b;而与此同时&#xff0c;一种备受瞩目的交易方式 —— 自营交易模式&#xff0c;正吸…...

emotn ui桌面tv版官网-emotn ui桌面使用教程

在智能电视和盒子的使用中&#xff0c;出色的桌面系统能大幅提升体验&#xff0c;Emotn UI桌面TV版便是其中的佼佼者。 访问Emotn UI桌面TV版官网&#xff0c;首页简洁清晰&#xff0c;“产品介绍”“下载中心”等板块一目了然。官网对其功能优势详细阐述&#xff0c;在“下载中…...

Django之modelform使用

Django新增修改数据功能优化 目录 1.新增数据功能优化 2.修改数据功能优化 在我们做数据优化处理之前, 我们先回顾下传统的写法, 是如何实现增加修改的。 我们需要在templates里面新建前端的页面, 需要有新增还要删除, 比如说员工数据的新增, 那需要有很多个输入框, 那html…...

Hadoop:大数据时代的基石

在当今数字化浪潮中&#xff0c;数据量呈爆炸式增长&#xff0c;企业和组织面临着前所未有的数据处理挑战。从社交媒体的海量信息到物联网设备的实时数据&#xff0c;如何高效地存储、管理和分析这些数据成为了一个关键问题。Apache Hadoop 作为大数据处理领域的核心框架&#…...

定制开发还是源码搭建?如何快速上线同城外卖跑腿APP?

在“万物皆可同城配送”的时代&#xff0c;同城外卖跑腿APP成为众多创业者和本地服务商的热门选择。无论是打造本地生活服务平台&#xff0c;还是拓展快送业务&#xff0c;拥有一款功能完善、体验流畅的外卖跑腿APP&#xff0c;已经成为进入市场的标配。 然而&#xff0c;对于…...

How AI could empower any business - Andrew Ng

How AI could empower any business - Andrew Ng References 人工智能如何为任何业务提供支持 empower /ɪmˈpaʊə(r)/ vt. 授权&#xff1b;给 (某人) ...的权力&#xff1b;使控制局势&#xff1b;增加 (某人的) 自主权When I think about the rise of AI, I’m reminded …...

SpringBoot-基础特性

1.SpringApplication 1.1.自定义banner 类路径添加banner.txt或设置spring.banner.location就可以定制 banner 1.2.自定义 SpringApplication import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.bo…...

系统环境变量有什么实际作用,为什么要配置它

系统环境变量有什么实际作用,为什么要配置它 系统环境变量具有以下重要实际作用: 指定程序路径:操作系统通过环境变量来知晓可执行文件、库文件等的存储位置例如,当你在命令提示符或终端中输入一个命令时,系统会根据环境变量PATH中指定的路径去查找对应的可执行文件。如果…...

C++ | STL之list详解:双向链表的灵活操作与高效实践

引言 std::list 是C STL中基于双向链表实现的顺序容器&#xff0c;擅长高效插入和删除操作&#xff0c;尤其适用于频繁修改中间元素的场景。与std::vector不同&#xff0c;std::list的内存非连续&#xff0c;但提供了稳定的迭代器和灵活的元素管理。本文将全面解析std::list的…...

Spring Cloud 服务间调用深度解析

前言 在构建微服务架构时&#xff0c;服务间的高效通信是至关重要的。Spring Cloud 提供了一套完整的解决方案来实现服务间的调用、负载均衡、服务发现等功能。本文将深入探讨 Spring Cloud 中服务之间的调用机制&#xff0c;并通过源码片段和 Mermaid 图表帮助读者更好地理解…...

什么是时间复杂度和空间复杂度?

什么是时间复杂度和空间复杂度? 时间复杂度:衡量代码运行时间随输入规模增大而增长的速度。简单来说,就是“代码跑多快”。 空间复杂度:衡量代码运行时额外占用的内存空间随输入规模增大而增长的速度。简单来说,就是“代码用多少内存”。 我们通常用 大 O 表示法(Big O N…...

算法思想之分治-快排

欢迎拜访&#xff1a;雾里看山-CSDN博客 本篇主题&#xff1a;算法思想之分治-快排 发布时间&#xff1a;2025.4.15 隶属专栏&#xff1a;算法 目录 算法介绍核心步骤优化策略 例题颜色分类题目链接题目描述算法思路代码实现 排序数组题目链接题目描述算法思路代码实现 数组中的…...

25.4.15学习总结

问题&#xff1a; 邮箱验证码通过公钥加密后发到前端&#xff0c;在前端用私钥解密验证可行吗&#xff1f; 结论&#xff1a; 在前端使用私钥解密通过公钥加密的邮箱验证码在技术上是可行的&#xff0c;但存在严重的安全风险&#xff0c;不建议采用。 问题分析 非对称加密的…...

小程序获取用户总结(全)

获取方式 目前小程序获取用户一共有3中(自己接触到的),但由于这个API一直在改,所以不确定后期是否有变动,还是要多关注官方公告。 方式一 使用wx.getUserInfo 实例: wxml 文件<button open-type="getUserInfo" bindgetuserinfo="onGetUserInfo&quo…...

如何成为一名嵌入式软件工程师?

如何成为一名嵌入式软件工程师&#xff1f; 01明确岗位的角色与定位 嵌入式软件工程师主要负责开发运行在特定硬件平台上的软件&#xff0c;这些软件通常与硬件紧密集成&#xff0c;以实现特定的功能。 不仅需要精通编程语言&#xff08;如C/C、Java等&#xff09;和软件开发工…...

机器人发展未来两年会有突破吗?

未来两年,机器人技术将在芯片、编码器、材料、加工工艺和AI等核心领域迎来系统性突破,推动行业从专用化向通用化转型。以下从技术路径、产业动态和商业化前景三个维度展开分析,结合权威数据与技术趋势,构建机器人技术演进的全景框架。 一、芯片技术:3nm制程与存算一体架构…...

【grafana原生告警中心配置飞书机器人告警】

在grafana中的connect point中使用webhook的方式推送到飞书&#xff0c;始终无法触发告警&#xff0c;原因是grafana推送的格式飞书不识别&#xff0c;现有两种方式 1.使用中转服务 使用flask搭建一个服务&#xff0c;grafana告警先通过webhook发送到web服务中&#xff0c;格…...

HTTP HTTPS RSA

推荐阅读 小林coding HTTP篇 文章目录 HTTP 80HTTP 响应码1xx&#xff1a;信息性状态码&#xff08;Informational&#xff09;2xx&#xff1a;成功状态码&#xff08;Success&#xff09;3xx&#xff1a;重定向状态码&#xff08;Redirection&#xff09;4xx&#xff1a;客户端…...

【机器学习】如何正确下载sklearn包

TOC 直接pip install sklearn时&#xff0c;报错 sklearn的包&#xff0c;实际上叫scikit-learn pip install scikit-learn发现成功了&#xff1a; 总结 下载sklearn包的语句&#xff1a;pip install scikit-learn 完成。...

【Python进阶】断言(assert)的十大核心应用场景解析

目录 前言&#xff1a;技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块技术选型对比 二、实战演示环境配置要求核心代码实现&#xff08;10个案例&#xff09;案例1&#xff1a;参数合法性检查案例2&#xff1a;不变…...

关于汽车辅助驾驶不同等级、技术对比、传感器差异及未来发展方向的详细分析

以下是关于汽车辅助驾驶不同等级、技术对比、传感器差异及未来发展方向的详细分析&#xff1a; 一、汽车辅助驾驶等级详解 根据SAE&#xff08;国际自动机工程师学会&#xff09;的标准&#xff0c;自动驾驶分为 L0到L5 六个等级&#xff1a; 1. L0&#xff08;无自动化&…...

STM32 HAL库之WDG示例代码

独立看门狗&#xff08;IWDG&#xff09; 初始化独立看门狗&#xff0c;在main.c中的 MX_IWDG_Init();&#xff0c;也就是iwdg.c中的初始化代码 void MX_IWDG_Init(void) {/* USER CODE BEGIN IWDG_Init 0 *//* USER CODE END IWDG_Init 0 *//* USER CODE BEGIN IWDG_Init 1 …...

【差分隐私相关概念】瑞丽差分隐私(RDP)命题10

命题10证明中的最后一个不等号成立&#xff0c;关键在于将事件 A A A上的积分与Rnyi散度 D α ( P ∥ Q ) D_\alpha(P \parallel Q) Dα​(P∥Q)的定义联系起来&#xff0c;并通过积分放缩得到上界。具体推导如下&#xff1a; Rnyi散度的定义&#xff1a; D α ( P ∥ Q ) 1 …...

Android 开发 如何生成系统签名

在源码中拿到安全文件 文件路径 lagvm/LINUX/android/build/target/product/security如下两个文件 platform.pk8 platform.x509.pem 使用Android studio生成一个jks Android studio 顶部 buildGenerate Signed Bundle or APKapkcrate new记住 记住alias 和password linux下…...

(EtherCAT 转 EtherNet/IP)EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关

型号 协议转换通信网关 EtherCAT 转 EtherNet/IP MS-GW12 概述 MS-GW12 是 EtherCAT 和 EtherNet/IP 协议转换网关&#xff0c;为用户提供两种不同通讯协议的 PLC 进行数据交互的解决方案&#xff0c;可以轻松容易将 EtherNet/IP 网络接入 EtherCAT 网络中&#xff0c;方便…...