ShardingJdbc-分表;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务
2021/6/7 18:21:02
本文主要是介绍ShardingJdbc-分表;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录- 创建项目
- 分表
- 导包
- 表结构
- Yml
- 分库分表
- 数据库
- Yml
- 读写分离
- 数据库
- Yml
- 其他
- 只请求主库
- 读写分离判断逻辑代码
- 一主多从+分表
- Yml
- 一主多从+分库分表
- Yml
- 公共表&数据脱敏
- 公共表
- 数据库
- Java代码
- Yml
- 数据脱敏
- 公共表
- 分布式事务
- Yml
- pom
- Java
- 代码下载
创建项目
一顿下一步,勾选web、lombok等插件
分表
导包
ShardingJdbc
官方最新稳定版4.1.1
<!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/sharding-jdbc-spring-boot-starter --> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version> </dependency>
Mysql
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency>
Druid
<!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.6</version> </dependency>
MyBatisPlus
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3</version> </dependency>
表结构
注意:之前我这表名叫table_0,结果一直报找不到表,后来发现,不能用关键字
CREATE TABLE `master_db`.`my_table_0` ( `id` BIGINT (20) NOT NULL, `source` VARCHAR (20), `remark` VARCHAR (100), PRIMARY KEY (`id`) ); CREATE TABLE `master_db`.`my_table_1` ( `id` BIGINT (20) NOT NULL, `source` VARCHAR (20), `remark` VARCHAR (100), PRIMARY KEY (`id`) );
Yml
application-sharding_table.yml
server: port: 80 spring: application: name: shardingJdbcDemo #shardingsphere相关配置 shardingsphere: datasource: names: db #库名,只是名字 db: #数据源 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 sharding: #指定表的分片规则 tables: # 看到table "s" ,就知道可配置多个 my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致 actualDataNodes: db.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的 tableStrategy: inline: # 指定表的分片策略 shardingColumn: id #参与分片运算的列名 algorithmExpression: my_table_$->{id % 2} #分片规则 keyGenerator: # 指定表的主键生成策略 type: SNOWFLAKE #SNOWFLAKE column: id #指定主键 props: sql: show: true #输出日志
至此配置完毕,运行效果见下方代码
分库分表
java代码都不改,只改数据库及yml
数据库
master_db、 slave_db1、 slave_db2
库中分别创建my_table_0、my_table_1,结构同 上
Yml
application-sharding_master_slave.yml
spring: application: name: shardingJdbcDemo #shardingsphere相关配置 shardingsphere: datasource: names: db0,db1,db2 #库名,只是名字 db0: #主库 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 db1: #从库1 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 db2: #从库2 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 #分库分表start sharding: #指定表的分片规则 tables: # 看到table "s" ,就知道可配置多个 my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致 actualDataNodes: db$->{0..2}.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的 databaseStrategy: inline: # 指定表的分片策略 shardingColumn: id #参与分片运算的列名 algorithmExpression: db$->{id % 3} #分片算法,分了三个库,所以要%3 tableStrategy: inline: # 指定表的分片策略 shardingColumn: id #参与分片运算的列名 algorithmExpression: my_table_$->{id % 2} #分片算法 keyGenerator: # 指定表的主键生成策略 type: SNOWFLAKE #SNOWFLAKE column: id #指定主键 #分库分表end props: sql: show: true #输出日志
然后继续访问第一步的save&select方法就可看到效果了,配置文件中写的主从库没有实际意义,起错名字了,实际都会往里面写
读写分离
数据库
模拟主从,不做MySql真正的主从同步
上面做表分片时已经创建好了主库master_db 再创建两个库 slave_db1 slave_db2
三个库表结构一致
master_db表中无数据
slave_db1 表数据如下
"id" "source" "remark"
"1" "source1" "remark1"
slave_db2 表数据如下
"id" "source" "remark"
"1" "source2" "remark2"
Yml
application-master_slave.yml
spring: application: name: shardingJdbcDemo #shardingsphere相关配置 shardingsphere: datasource: names: masterdb,slavedb1,slavedb2 #库名,只是名字 masterdb: #主库 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 slavedb1: #从库1 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 slavedb2: #从库2 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 masterslave: name: dbs master-data-source-name: masterdb #主库 slave-data-source-names: slavedb1,slavedb2 #多个从库 load-balance-algorithm-type: ROUND_ROBIN #RANDOM随机 ROUND_ROBIN 轮训 props: sql: show: true #输出日志
这时,访问上面搭好的项目,即可进行读写分离,代码见上方链接
其他
只请求主库
在请求上方添加如下代码即可
// HintManager hintManager = HintManager.getInstance(); // hintManager.setMasterRouteOnly(); @GetMapping("select") public PageInfo select(int pageNum,int pageSize,Long id){ // HintManager hintManager = HintManager.getInstance(); // hintManager.setMasterRouteOnly(); PageHelper.startPage(pageNum,pageSize); QueryWrapper<Table0> queryWrapper=new QueryWrapper(); if(!StringUtils.isEmpty(id)) { queryWrapper.eq("id", id); } List<Table0> list = table0Service.list(queryWrapper); PageInfo pageInfo = new PageInfo<>(list); return pageInfo; }
读写分离判断逻辑代码
大致的流程是shardingJdbc根据sql获得对应的sqlStatement,然后只有SelectStatement的才走从库
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.shardingsphere.masterslave.route.engine.impl; import lombok.RequiredArgsConstructor; import org.apache.shardingsphere.api.hint.HintManager; import org.apache.shardingsphere.core.rule.MasterSlaveRule; import org.apache.shardingsphere.sql.parser.sql.statement.SQLStatement; import org.apache.shardingsphere.sql.parser.sql.statement.dml.SelectStatement; import java.util.ArrayList; /** * Data source router for master-slave. */ @RequiredArgsConstructor public final class MasterSlaveDataSourceRouter { private final MasterSlaveRule masterSlaveRule; /** * Route. * * @param sqlStatement SQL statement * @return data source name */ public String route(final SQLStatement sqlStatement) { if (isMasterRoute(sqlStatement)) { MasterVisitedManager.setMasterVisited(); return masterSlaveRule.getMasterDataSourceName(); } return masterSlaveRule.getLoadBalanceAlgorithm().getDataSource( masterSlaveRule.getName(), masterSlaveRule.getMasterDataSourceName(), new ArrayList<>(masterSlaveRule.getSlaveDataSourceNames())); } private boolean isMasterRoute(final SQLStatement sqlStatement) { return containsLockSegment(sqlStatement) || !(sqlStatement instanceof SelectStatement) || MasterVisitedManager.isMasterVisited() || HintManager.isMasterRouteOnly(); } private boolean containsLockSegment(final SQLStatement sqlStatement) { return sqlStatement instanceof SelectStatement && ((SelecStatement) sqlStatement).getLock().isPresent(); } }
一主多从+分表
上面实现了一主多从和表分片,现在把它整合到一起
java代码还是没改,主要改的还是Yml
Yml
application-sharding_db_table_oneMaster_slaves.yml
关键配置见 masterSlaveRule,分片配置未改
#一主多从+表分片 spring: application: name: shardingJdbcDemo #shardingsphere相关配置 shardingsphere: datasource: names: db0,db1,db2 #库名,只是名字 db0: #主库 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 db1: #从库1 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 db2: #从库2 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 masterSlaveRule: # 这里配置这个规则的话,相当于是全局读写分离配置 name: ds_rw # 名称,合法的字符串即可,但如果涉及到在读写分离的基础上设置分库分表,则名称需要有意义才可以,另外,虽然目前没有强制要求,但主从库配置需要配置在实际关联的主从库上,如果配置的数据源之间主从是断开的状态,那么可能会发生写入的数据对于只读会话无法读取到的问题 # 如果一个会话发生了写入并且没有提交(显式打开事务),sharidng sphere在后续的路由中,select都会在主库执行,直到会话提交 masterDataSourceName: db0 # 主库的DataSource名称 slaveDataSourceNames: # 从库的DataSource列表,至少需要有一个 - db1 - db2 loadBalanceAlgorithmType: ROUND_ROBIN #从库负载均衡算法类型,可选值:ROUND_ROBIN,RANDOM。若loadBalanceAlgorithmClassName存在则忽略该配置,默认为ROUND_ROBIN sharding: #指定表的分片规则 tables: # 看到table "s" ,就知道可配置多个 my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致 actualDataNodes: db$->{0..2}.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的 databaseStrategy: inline: # 指定表的分片策略 shardingColumn: id #参与分片运算的列名 algorithmExpression: db$->{id % 3} #分片算法,分了三个库,所以要%3 tableStrategy: inline: # 指定表的分片策略 shardingColumn: id #参与分片运算的列名 algorithmExpression: my_table_$->{id % 2} #分片算法 keyGenerator: # 指定表的主键生成策略 type: SNOWFLAKE #SNOWFLAKE column: id #指定主键 props: sql: show: true #输出日志
一主多从+分库分表
上面实现了一主多从和表分片,现在把它整合到一起
java代码还是没改,主要改的还是Yml
创建了两个主库两个从库master_db1、master_db2、slave_db1、slave_db2
下方配置为 master_db1与slave_db1为主从关系、master_db2与slave_db2为主从关系
修改点有点多,查看标*****的位置
参考
Yml
application-sharding_db_table_masters_slaves.yml
#一主多从+表分片 spring: application: name: shardingJdbcDemo #shardingsphere相关配置 shardingsphere: datasource: names: db0,db1,db2,db3 #库名,只是名字 ******************新增名称db3 db0: #主库 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/master_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 db1: #主库1 ****************** 添加主库 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/master_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 db2: #从库1 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 db3: #从库2 ******************添加从库 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 sharding: master-slave-rules: # 新增配置 ****************** db0: # 此处名字一定要配置和下面 master-data-source-name 名字一致的 master-data-source-name: db0 slave-data-source-names: db2 db1: # 此处名字一定要配置和下面 master-data-source-name 名字一致的 master-data-source-name: db1 slave-data-source-names: db3 tables: # 看到table "s" ,就知道可配置多个 my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致 actualDataNodes: db$->{0..1}.my_table_$->{0..1} #******************每组有一主一从,所以是0..1 databaseStrategy: inline: # 指定表的分片策略 shardingColumn: id #参与分片运算的列名 algorithmExpression: db$->{(id / 10).toBigInteger() % 2} # *******不能再用id%2方式了,会导致数据分配不均,所以需要自定义方法 tableStrategy: inline: # 指定表的分片策略 shardingColumn: id #参与分片运算的列名 algorithmExpression: my_table_$->{id % 2} #分片算法 keyGenerator: # 指定表的主键生成策略 type: SNOWFLAKE #SNOWFLAKE column: id #指定主键 props: sql: show: true #输出日志
公共表&数据脱敏
公共表
项目中会有很多字典表、配置表等等,此类表数据固定、量级不大,所以可以无需采用分库分表,每个库存一份;
当配置公共表后,每次对公共表进行操作,都会同步操作所有库中的公共表
数据库
分别在三个库中新增表pub_table
Java代码
生成pub_table相关的MybatisPlus代码
Yml
application-publicTable_encryptor.yml
spring: application: name: shardingJdbcDemo #shardingsphere相关配置 shardingsphere: datasource: names: db0,db1,db2 #库名,只是名字 db0: #主库 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 db1: #从库1 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 db2: #从库2 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 sharding: default-data-source-name: db #如果有多个库,公共表只有一个库有,那么,就要指定有公共表的库,否则会报找不到表 default-database-strategy: inline: sharding-column: id algorithm-expression: db$->{id % 3} broadcast-tables: pub_table #公共表配置,可以多个 props: sql: show: true #输出日志
数据脱敏
参考
spring: application: name: shardingJdbcDemo #shardingsphere相关配置 shardingsphere: datasource: names: db #库名,只是名字 db: #数据源 type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT username: root password: 123 sharding: #指定表的分片规则 # 数据脱敏规则配置---start encrypt-rule: encryptors: encryptor_MD5: type: MD5 props: md5.key.value: 123456 encryptor_aes: # 加密、解密器的名字,内置的为MD5,aes. # 可以自定义,实现 # org.apache.shardingsphere.encrypt.strategy.spi.Encryptor # 或者 # org.apache.shardingsphere.encrypt.strategy.spi.QueryAssistedEncryptor # 这两个接口即可 type: aes props: aes.key.value: 123456 tables: # tables my_table: columns: # 逻辑列,就是写SQL里面的列,因为实体类的名字和数据库的加密列一致,所以这里都是name source: # 原文列 # plainColumn: password # 密文列,用来存储密文数据 cipherColumn: source # 加密器名字 encryptor: encryptor_MD5 # password1: # 原文列 # plainColumn: password1 # 密文列,用来存储密文数据 # cipherColumn: aes_password # 加密器名字 # encryptor: encryptor_aes # 数据脱敏规则配置---end broadcast-tables: pub_table #公共表 tables: # 看到table "s" ,就知道可配置多个 my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致 actualDataNodes: db.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的 tableStrategy: inline: # 指定表的分片策略 shardingColumn: id #参与分片运算的列名 algorithmExpression: my_table_$->{id % 2} #分片算法 keyGenerator: # 指定表的主键生成策略 type: SNOWFLAKE #SNOWFLAKE column: id #指定主键 props: sql: show: true #输出日志 query.with.cipher.column: true #是否使用密文列查询
分布式事务
分库分表后,因为不是一个库了,所以一旦报错,数据无法回滚
Yml
使用上方 application-sharding_db_table_masters_slaves.yml
pom
<!-- 使用 XA 事务时,需要引入此模块 --> <dependency> <groupId>io.shardingsphere</groupId> <artifactId>sharding-transaction-spring-boot-starter</artifactId> <version>3.1.0</version> <type>pom</type> </dependency>
Java
新增
package com.rollback.shardingjdbcdemo.demo.conf; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; @Configuration @EnableTransactionManagement public class TransactionConfiguration { @Bean public PlatformTransactionManager txManager(final DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean public JdbcTemplate jdbcTemplate(final DataSource dataSource) { return new JdbcTemplate(dataSource); } }
修改save方法
saveByTransaction
package com.rollback.shardingjdbcdemo.demo.sharding.controller; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.rollback.shardingjdbcdemo.demo.sharding.model.Table0; import com.rollback.shardingjdbcdemo.demo.sharding.service.Table0Service; import org.apache.shardingsphere.api.hint.HintManager; import org.apache.shardingsphere.transaction.annotation.ShardingTransactionType; import org.apache.shardingsphere.transaction.core.TransactionType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Random; /** * <p> * 前端控制器 * </p> * * @author koala * @since 2021-05-31 */ @RestController @RequestMapping("/table0") public class Table0Controller { @Autowired Table0Service table0Service; @GetMapping("save") public void save(int tag){ table0Service.save(new Table0(){{setSource("source"+tag);setRemark("remark"+tag);}}); } @Transactional @ShardingTransactionType(TransactionType.XA) // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE @GetMapping("saveByTransaction") public void saveByTransaction(int tag){ for (int i = 0; i < 10; i++) { if(i==5){ List list=null; list.add("error"); } table0Service.save(new Table0(){{setSource("source"+tag);setRemark("remark"+tag);}}); } } @GetMapping("select") public PageInfo select(int pageNum,int pageSize,Long id){ // HintManager hintManager = HintManager.getInstance(); // hintManager.setMasterRouteOnly(); PageHelper.startPage(pageNum,pageSize); QueryWrapper<Table0> queryWrapper=new QueryWrapper(); if(!StringUtils.isEmpty(id)) { queryWrapper.eq("id", id); } queryWrapper.eq("source","source1"); List<Table0> list = table0Service.list(queryWrapper); PageInfo pageInfo = new PageInfo<>(list); return pageInfo; } @GetMapping("select1") public List<Table0> select1(int pageNum,int pageSize,Long id){ QueryWrapper<Table0> queryWrapper=new QueryWrapper(); if(!StringUtils.isEmpty(id)) { queryWrapper.eq("id", id); } //queryWrapper.eq("source","source1"); List<Table0> list = table0Service.list(queryWrapper); return list; } }
验证步骤:
-
清空数据库
-
执行saveByTransaction
-
报错后观察数据库,一条都没有
-
去掉
@Transactional
@ShardingTransactionType(TransactionType.XA) // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE后,会出现保存部分数据的情况
参考官网
代码下载
代码见sharding包下,请求入口见 Table0Controller
这篇关于ShardingJdbc-分表;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享