ShardingSphere JDBC 分库实现多数据库源

Sharding-JDBC多数据源动态切换 Sharding-JDBC多数据源动态切换背景介绍方案介绍版本说明实现方式1. spring-boot依赖2. 启动类配置3. yml配置4. 自定义强制路由5. AOP切换数据源6. 编写事务代码7. 源码下载 背景介绍 我们公司项目使用多个mysql实例,业务分库,无需分表。需要实现如下功能: 多数据源动态切换 读写分离 分布式事务(XA) 方案介绍 通过阅读Sharding-Sphere官方文档,结合业务进行了设计,给出如下解决方案: 使用Sharding-JDBC管理数据源,自带读写分离和分布 阅读详情

简介

基于Shardingsphere JDBC 5.0.0版本,利用Sharding分库实现日常开始中的数据库多数据源使用需求,结合Spring Boot 和 Mybatis Plus

数据源需求说明

数据库初始语句如下:

create database demo1;
create database demo2;

create table `demo1`.table1 (
    id int
);

create table `demo2`.table2 (
    id int
);

create table `demo1`.sharding_table (
    id int
);

create table `demo2`.sharding_table (
    id int
);

insert into `demo1`.sharding_table (id) values(1);
insert into `demo2`.sharding_table (id) values(1);

两个数据库,数据库1有表:table1、sharding_table

数据库2有表:table2、sharding_table

要求如下:

  • 当访问表 table1 时,访问数据库 demo1
  • 当访问表 table2 时,访问数据库 demo2
  • 当访问表 sharding_table 时,根据自定义的传入参数,访问对应的数据,本篇文章,将要访问的数据源存入ThreadLocal中,获取后访问对应的数据源

关键代码示例

完整代码GitHub地址:https://github.com/lw1243925457/JAVA-000/tree/main/code/shardingsphere/shardingdb

定义数据源

配置ShardingSphere JDBC数据源,关键代码如下:

配置如下,定义了连个数据源,最后的rules是标识表table1到数据源db0访问,表table2到数据源db1访问

# shardingSphere 分库设置
shardingsphere:
  # 配置真实数据源
  datasources:
    # 数据库1
    db0:
      jdbcurl: ${DB1_URL:jdbc:mysql://127.0.0.1:3306/demo1?useUnicode=true&serverTimezone=UTC}
      username: ${DB1_USER:root}
      password: ${DB1_PASS:root}
    # 数据库2
    db1:
      jdbcurl: ${DB2_URL:jdbc:mysql://127.0.0.1:3306/demo2?useUnicode=true&serverTimezone=UTC}
      username: ${DB2_USER:root}
      password: ${DB2_PASS:root}
  rules:
    table1: db0
    table2: db1

如果使用ShardingSphere的yaml文件配置,暂时还没有找到如何使用环境变量的方式,不方便修改,所有使用Java代码直接进行配置

@Slf4j
@Configuration
public class ShardingDataSourceMybatisPlusConfig extends MybatisPlusAutoConfiguration {

    private final MultipleDbConfig multipleDbConfig;

    @Primary
    @Bean("dataSource")
    public DataSource getDataSource() throws SQLException {
        // 配置真实数据源
        Map<String, MultipleDbConfig.DbSource> dbs = multipleDbConfig.getDatasources();
        Map<String, DataSource> dataSourceMap = new HashMap<>(dbs.size());
        for (String dbName: dbs.keySet()) {
            MultipleDbConfig.DbSource dbConfig = dbs.get(dbName);
            HikariDataSource dataSource = new HikariDataSource();
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setJdbcUrl(dbConfig.getJdbcUrl());
            dataSource.setUsername(dbConfig.getUsername());
            dataSource.setPassword(dbConfig.getPassword());
            dataSourceMap.put(dbName, dataSource);
        }

        // 配置分片规则
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();

        // 遍历表的固定映射:表table1到数据源db0访问,表table2到数据源db1访问
        Map<String, String> rules = multipleDbConfig.getRules();
        for (final String table: rules.keySet()) {
            // 配置添加 t_order 表规则
            final String actualDataNodes = String.join(".", rules.get(table), table);
            shardingRuleConfig.getTables().add(new ShardingTableRuleConfiguration(table, actualDataNodes));
        }

        // 配置 sharding_table 表的访问,需要自定义实现分库和分表算法
        ShardingTableRuleConfiguration ShardingTableRuleConfiguration = new ShardingTableRuleConfiguration("sharding_table", "db${0..1}.sharding_table");
        shardingRuleConfig.setDefaultDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("id", "customDbSharding"));
        shardingRuleConfig.setDefaultTableShardingStrategy(new StandardShardingStrategyConfiguration("id", "customTableSharding"));
        shardingRuleConfig.getTables().add(ShardingTableRuleConfiguration);

        // 配置分库算法
        Properties dbShardingAlgorithmProps = new Properties();
        dbShardingAlgorithmProps.setProperty("strategy", "standard");
        dbShardingAlgorithmProps.setProperty("algorithmClassName", "com.shardingsphere.shardingdb.config.CustomDbSharding");
        shardingRuleConfig.getShardingAlgorithms().put("customDbSharding", new ShardingSphereAlgorithmConfiguration("CLASS_BASED", dbShardingAlgorithmProps));

        // 配置分表算法
        Properties tableShardingAlgorithmProps = new Properties();
        tableShardingAlgorithmProps.setProperty("strategy", "standard");
        tableShardingAlgorithmProps.setProperty("algorithmClassName", "com.shardingsphere.shardingdb.config.CustomTableSharding");
        shardingRuleConfig.getShardingAlgorithms().put("customTableSharding", new ShardingSphereAlgorithmConfiguration("CLASS_BASED", tableShardingAlgorithmProps));

        // 开启Sql日志
        final Properties properties = new Properties();
        properties.setProperty("sql-show", "true");

        // 创建 ShardingSphereDataSource
        return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfig), properties);
    }

    @Override
    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource")DataSource dataSource) throws Exception {
        return super.sqlSessionFactory(getDataSource());
    }

    @Override
    @Bean("sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory")SqlSessionFactory sqlSessionFactory) {
        return super.sqlSessionTemplate(sqlSessionFactory);
    }
}

从代码上可以看出,大部分还是便于后面直接修复配置文件进行扩展的

自定义分库代码如下:主要是获取ThreadLocal中的数据源名称信息,然后返回给Shardingsphere,这样就能访问对应的数据源

示例中只是为了简单而使用这种直接的方式,也可以放入其他信息,自行根据需求转成对应的数据源

public final class CustomDbSharding implements StandardShardingAlgorithm<Integer> {

    @Override
    public void init() {
    }

    @Override
    public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Integer> shardingValue) {
        String dbName = ThreadLocalCache.threadLocal.get();
        for (String each : availableTargetNames) {
            if (each.equals(dbName)) {
                return each;
            }
        }
        return null;
    }

    @Override
    public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Integer> shardingValue) {
        return availableTargetNames;
    }

    @Override
    public String getType() {
        return null;
    }
}

自定义分表,之类其实应该没有,但为了展示一个完整的,所以也弄了一个自定义分表,这里是直接返回即可

public final class CustomTableSharding implements StandardShardingAlgorithm<Integer> {

    @Override
    public void init() {
    }

    @Override
    public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Integer> shardingValue) {
        for (String each : availableTargetNames) {
            return each;
        }
        return null;
    }

    @Override
    public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Integer> shardingValue) {
        return availableTargetNames;
    }

    @Override
    public String getType() {
        return null;
    }
}

Entity、Mapper定义

简单的写写即可:

@Data
@TableName("sharding_table")
public class ShardingTable {
    private Long id;
}

@Data
@TableName("table1")
public class Table1 {
    private Long id;
}

@Data
@TableName("table2")
public class Table2 {

    private Long id;
}

@Repository
public interface ShardingTableMapper extends BaseMapper<ShardingTable> {
}

@Repository
public interface Table1Mapper extends BaseMapper<Table1> {
}

@Repository
public interface Table2Mapper extends BaseMapper<Table2> {
}

测试验证

我们写了测试类,进行测试即可

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ShardingDbTest {

    @Autowired
    private Table1Mapper table1Mapper;
    @Autowired
    private Table2Mapper table2Mapper;
    @Autowired
    private ShardingTableMapper shardingTableMapper;

    @Test
    public void test() {
        final List<Table1> l1 = table1Mapper.selectList(null);
        l1.forEach(System.out::println);

        final List<Table2> l2 = table2Mapper.selectList(null);
        l2.forEach(System.out::println);

        ThreadLocalCache.threadLocal.set("db1");
        System.out.println(shardingTableMapper.selectById(1L));

        ThreadLocalCache.threadLocal.set("db0");
        System.out.println(shardingTableMapper.selectById(1L));
    }
}

结果如下:

Logic SQL: SELECT  id  FROM table1
SQLStatement: MySQLSelectStatement(limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
Actual SQL: db0 ::: SELECT  id  FROM table1

Logic SQL: SELECT  id  FROM table2
SQLStatement: MySQLSelectStatement(limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
Actual SQL: db1 ::: SELECT  id  FROM table2

Logic SQL: SELECT id FROM sharding_table WHERE id=? 
SQLStatement: MySQLSelectStatement(limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
Actual SQL: db1 ::: SELECT id FROM sharding_table WHERE id=?  ::: [1]
ShardingTable(id=1)

Logic SQL: SELECT id FROM sharding_table WHERE id=? 
SQLStatement: MySQLSelectStatement(limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
Actual SQL: db0 ::: SELECT id FROM sharding_table WHERE id=?  ::: [1]

可以看到访问四次,Actual SQL符合我们的预期

总结

展示了如何使用Shardingsphere JDBC实现多数据源访问,Shardingsphere JDBC如何实现自定义的分库和分表算法

参考链接

多数据源下配置shardingjdbc,导致主数据源失效的场景 踩坑sharding jdbc,集成多数据源 使用Shardingsphere和dynamic-datasource实现多数据源切换并分表 sharding-jdbc配置的数据源连接失败 shardingsphere分库分表集成多数据源 shardingsphere配置和双数据源dynamic该如何配置 阅读详情

相关推荐

【ShardingSphere专题】SpringBoot整合ShardingSphere(一、数据分片入门及实验)

最近线上的项目部分数据表增量速度比较快,可以预见的是,个把月后数据量会急剧增长至千万级,所以只是简单的使用索引等已经无法满足业务需求了,分库分表势在必行!于是着手研究如何整合ShardingSphere到现有项目中,顺带记录一下实验过程吧。特别声明:这边是实验配置阶段,还没有完成整合到项目、以及测试联调阶段,所以不敢保证实验过程是否正确。而且,在我的业务中,还涉及到【普通单表】与【分片表】之间的联表查询,所以需要后期比较严谨的测试才能知道最终效果。不过我自己对比了站内其他大佬的教程,大体是没问题的。

qq_32681589的博客 5333

shardingsphere分库分表集成多数据源

如果有分库分表,又有切换数据源的需求可以使用多数据源dynamic-datasource与shardingsphere集成的场景方案。3、添加一个多数据测试库yz-order和表sys_order。新增yz-log数据库和oper_log_xxx四张表。入到yz-log库oper_log_delete表。入到yz-log库oper_log_post表。入到yz-log库oper_log_get表。入到yz-log库oper_log_put表。入到yz-order库sys_order表。

扭曲的影子 6705

shardingsphere分库分表项目实践2-多库动态路由原理

shardingshpere 抽象出了一套逻辑对象,实际上用的是代理模式设计思想: 逻辑数据源: 包含了真是的多个物理数据源,和sharding策略规则 逻辑connection : 没有具体连接,包含了逻辑数据源的引用 逻辑statement : 根具sql参数和sharding 规则计算 真实的数据库表,然后通过sql解析改写,最后交给真是的statement执行。 逻辑sql : 就是代码里面的sql, 表名不含sharding部分,真正执行的时候根据参数和sharding规则拼接上去

zfj321的博客 1118

shardingsphere5.x整合springboot+dynamic-datasource多数据源实战

shardingsphere,分库分表,多数据源

任人人人呢的博客 1万+

Spring Boot项目实战:用ShardingSphere-JDBC 5.3.2搞定PostgreSQL分库分表,附完整配置流程

本文详细介绍了如何在Spring Boot项目中整合ShardingSphere-JDBC 5.3.2实现PostgreSQL的分库分表,包括环境准备、核心配置、业务层适配和性能优化等实战内容。通过完整的配置流程和最佳实践,帮助开发者高效解决大数据量下的查询和写入性能问题。

weixin_29196613的博客 186

ShardingSphere X openGauss

后端模块实现了对这些数据库协议、SQL 语法的支持,考虑到 Proxy 本身不会对 SQL 进行计算(只会处理少量需要聚合计算的结果),因此 Proxy 不需要完全解析并理解 SQL 语法,而是对其采取了半理解的解析方式,依赖 antrl 实现语法解析,然后遍历 TOKEN 取出分片算法关心的 TOKEN(如 where 条件等),根据分片算法改写 SQL 并路由到对应的数据库,在所有结果返回后进行合并并处理,最后将结果返回给请求的客户端。社区官网对于 ShardingSphere 的定义。

2401_83143557的博客 949

ShardingSphere-JDBC 和 ShardingSphere-Proxy区别

适合需要将分库分表逻辑嵌入到应用中的场景,轻量级、直接与应用程序集成、配置简单,适合单体应用和中小规模的系统。:适合需要集中管理数据库连接、跨多个应用共享数据库服务的场景,适合微服务架构和大规模分布式数据库集群的运维管理,能够简化多个应用的数据库管理。选择使用还是取决于你的架构设计、应用规模以及对性能和管理的需求。

专注于技术分享 1255

Apache ShardingSphere-JDBC 多数据源动态配置实战指南

本文详细介绍了Apache ShardingSphere-JDBC在多数据源动态配置中的实战应用,包括基础配置、读写分离、分库分表等核心功能。通过具体示例和最佳实践,帮助开发者高效管理多个数据源,实现负载均衡和动态扩展,提升数据库性能和系统稳定性。

weixin_29311017的博客 375

分库分表神器MyCat和ShardingSphere

数据库分库分表中间件,常用的就是mycat和shardingsphere了,两者都是国人开源产品中的佼佼者。两者的定位也是不一样的,一个本地拦截处理(sharding-jdbc),一个是服务器端拦截处理(mycat)mycat的生态还并不是很完善,很多内容都在开发中,而ShardingSphere相对就更加完善了,有人看好mycat的前景,但是也不得不为眼前考虑,不得已选择了ShardingSphere。ShardingSphere的社区活跃还是蛮高的,有问题可以询问。

码农桃子的博客 6694

Spring Boot集成ShardingSphere配合dynamic-datasource进行数据源切换 | Spring Cloud 49

可能存在以下场景:原项目中使用的是dynamic-datasource进行数据源管理,由于项目经历一段时间的线上运行,数据库压力越来越大,计划使用shardingsphere-jdbc进行数据分片或读写分离。

gmHappy 2万+

数据库中间件ShardingSphere v5.2.1

数据库中间件ShardingSphere

北执南念的博客 389

Sharding-JDBC分库分表的基本使用

本篇介绍了分库分表以及分库分表存在的问题,进而介绍了能够解决分库分表问题的Sharding-JDBC框架,并以一个示例,分享了Sharding-JDBC的基本使用。

JingAi_jia917的博客 1817

5GCPE与4G物联网卡兼容实战:通过AT指令修改IMEI实现设备迁移

本文详细介绍了如何通过AT指令修改5GCPE设备的IMEI,实现4G物联网卡的设备迁移。从硬件准备、驱动安装到串口工具配置,再到具体的AT指令操作步骤,提供了全面的实战指南。文章还包含信号优化、APN设置等实用技巧,帮助用户顺利完成设备迁移并提升网络性能。

weixin_28684757的博客 626

【ShardingJDBC】【笔记】---- ShardingSphere 入门到精通

一套开源的分布式数据库中间件解决方案有三个产品:Sharding-JDBC 和 Sharding-Proxy定位为关系型数据库中间件,合理在分布式环境下使用关系型数据库操作Apache ShardingSphere(Incubator) 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar(规划中)这 3 款相互独立,却又能够混合部署配合使用的产品组成。

朱朱博客,分享技术 1205

第四章 自定义组件、动画

第三章 自定义组件、动画 (一)自定义View 1.1) onMeasure:对当前View的尺寸进行测量 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec和heightMeasureSpec包含测量模式和尺寸大小 int widthMode = MeasureSpec....

Stay Hungry Stay Foolish 求知若饥 虚心若愚 8130

Kill5.37版本下,使用ARMcomplier6编译__asm 函数报错的问题

Kill5-5.37版本下,使用ARMcomplier6编译__asm 函数报错的问题 问题简要描述: 昨日更新了keil5软件的版本,从5.17更新到了5.37版本,然后编译STM32项目文件时,软件提示编译报错。报错问题如下: Build started: Project: QKsoftware *** Using Compiler 'V6.18', folder: 'E:\MDK-ARM\ARM\ARM\ARMCLANG\Bin' Build target 'QKsoftware' compiling

weixin_43644424的博客 1万+

从零到一:Apache ShardingSphere-JDBC 数据源配置的实战避坑指南

本文详细介绍了Apache ShardingSphere-JDBC数据源配置的实战指南,涵盖从基础参数设置到生产环境最佳实践。通过多类型数据库支持、连接池优化及密码安全加密等核心功能,帮助开发者高效配置分布式数据库环境,避免常见陷阱。

weixin_29313423的博客 386

手把手教你用6轴IMU跑通LIO-SAM:参数配置与代码修改保姆级教程

本文提供了一套完整的6轴IMU适配LIO-SAM的解决方案,包括参数配置与代码修改的详细步骤。从理解6轴与9轴IMU的关键差异入手,逐步指导如何调整核心配置文件params.yaml、重构utility.h关键函数、优化mapOptimization.cpp的位姿融合逻辑,并给出编译验证与性能调优建议,帮助开发者快速实现6轴IMU在LIO-SAM中的稳定运行。

weixin_28717807的博客 356

springboot+mybatisplus+sharding-jdbc分库分表

springboot,mybatisplus,sharding-jdbc实现分库分表

zbmzbm00的博客 1511

二十一、SAP-库存管理

业务逻辑、功能讲解、图文解析、章节总结

m0_72403327的博客 1808

SAPIEN ManiSkill3 入门教程(一)

请注意,table.set_pose(pose) 设置的是演员在世界帧中的坐标系姿势。移除的实体可以再次添加到场景中,但已在场景中的实体则不能再次添加。显示器可以是物理的(如显示器),也可以是虚拟的(如 VNC)。我们可以通过 get_pose()、get_linear_velocity() 和 get_angular_velocity()获取演员的运动量(姿势、线速度、角速度)。现在,让我们创建一个斜坡。例如,您可能需要一个简单的碰撞形状来进行快速模拟,但却需要一个复杂的视觉形状来进行逼真的渲染。

机器人控制与仿真应用 3070

Apache ShardingSphere-JDBC 数据源配置(Data Source)

Apache ShardingSphere-JDBC数据源配置深度解析:支持多数据库类型(MySQL/Oracle等)和连接池(HikariCP/Druid),提供主从架构、读写分离等场景配置方案。核心配置包括必填参数(连接池类名、驱动、URL等)和专属优化参数(超时时间、连接数等)。重点强调生产环境实践:密码加密(内置AES或集成KMS)、读写分离数据源分组、分库分表映射。高级技巧涵盖连接池调优公式(CPU核数×2+1)、多数据库混配注意事项及故障转移配置。最后展示主从分库完整配置示例,实现分布式数据库高

csdn_tom_168的博客 1437

YoloV8优化:感受野注意力卷积运算(RFAConv),效果秒杀CBAM和CA等 | 即插即用系列

感受野注意力卷积运算(RFAConv),解决卷积块注意力模块(CBAM)和协调注意力模块(CA)只关注空间特征,不能完全解决卷积核参数共享的问题

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 4263

shardingsphere分析

1、前言 鉴于最近shardingSphere非常火爆,分析分析下其中的实现 2、常见的sharding的策略 实现层面 应用框架 优劣分析 数据访问层(DAO层) 适合在该层进行自主研发 不受ORM框架的制约、实现起来较为简单、易于根据系统特点进行灵活的定制、无需SQL解析和路由规则匹配,性能上表现会稍好一些;劣势在于:有一定的技术门槛,工作量比依靠...

weixin_30594001的博客 249

YOLO车辆测距、车辆识别与单目测距

YOLO(You Only Look Once)是一种实时物体检测系统,能够识别视频或图像中的多个对象,并确定其位置。结合车辆识别与单目测距技术,YOLO可以用于交通监控、自动驾驶等应用场景,通过单个摄像头实现车辆的识别与距离测量。YOLO结合单目测距技术,在多个应用领域展现出巨大的潜力与灵活性。其实时性和准确性为智能交通、自动驾驶等领域提供了强有力的技术支持。

走向CTO的路上... 1667

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

上一篇: JDK动态代理
下一篇: ShardingSphere JDBC 分库实现多数据库源
_萧_
博客等级 码龄10年 55粉丝 157原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值