SpringBoot整合sharding-jdbc 实现分库分表操作的示例代码
目录
- 1、简介
- 核心功能
- 核心概念
- 架构设计
- 使用场景
- 2、实战流程
- 2.1. pom.XML
- 2.2. CustomSnowflakeKeyGenphperator.Java
- 2.3. DataSourceShardingConfig.java
- 2.4. SpringBootDemoShardingJdbcApplicationTests.java
1、简介
Sharding-JDBC 是一款开源的分布式数据库中间件,旨在简化分库分表(Sharding)的实现。它通过透明化的方式将数据分布到多个数据库或表中,同时提供与原生 JDBC 一致的开发体验。Sharding-JDBC 是 Apache ShardingSphere 项目的子模块之一,广泛应用于高并发、大数据量的场景。
核心功能
1、分库分表:
支持水平分库和水平分表,将数据分散到多个数据库或表中,提升系统性能和存储能力。
支持多种分片策略,如按范围、哈希、时间等。
2、读写分离:
支持主从架构的读写分离,将读操作路由到从库,写操作路由到主库,减轻主库压力。
3、分布式事务:
提供基于 XA 和柔性 事务(Saga、TCC)的分布式事务支持,确保数据一致性。
4、数据脱敏:
支持对敏感数据进行加密和脱敏处理,保障数据安全。
5、多数据源管理:
支持动态数据源配置和管理,方便扩展和维护。
6、SQL 兼容性:
支持绝大多数 SQL 语法,兼容主流数据库(如 mysql、PostgreSQL、oracle 等)。
核心概念
1、逻辑表(Logic Table):
开发中使用的虚拟表名,例如 order。
2、真实表(Actual Table):
数据库中实际存在的表,例如 order_0、order_1。
3、数据节点(Data Node):
数据分片的最小单元,由数据源名称和真实表组成,例如 ds0.order_0。
4、分片键(Sharding Key):
用于分片的字段,例如订单表中的 user_id。
5、分片算法(Sharding Algorithm):
定义如何根据分片键将数据路由到不同的数据库或表。
6、绑定表(Binding Table):
具有相同分片规则的表,例如 order 和 order_item,可以避免跨表查询。
架构设计
Sharding-JDBC 采用轻量级的架构设计,直接嵌入应用程序中,无需额外部署中间件。其核心组件包括:
SQL 解析引擎:解析 SQL 语句,提取分片键。
路由引擎:根据分片规则将 SQL 路由到正确的数据节点。
改写引擎:将逻辑 SQL 改写为真实 SQL。
执行引擎:执行 SQL 并合并结果。
使用场景
1、高并发场景:
通过分库分表提升系统的并发处理能力。
2、大数据量场景:
通过数据分片解决单表数据量过大的问题。
3、读写分离场景:
通过读写分离提升数据库的读性能。
4、多租户场景:
通过分库分表实现多租户数据隔离。
2、实战流程
2.1. pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>spring-boot-demo-sharding-jdbc</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-demo-sharding-jdbc</name> <description>Demo project for Spring Boot</description> <parent> <groupId>com.xiaoma</groupId> &http://www.devze.comlt;artifactId>spring-boot-demo</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> <properties> <project.build.sourceEncojsding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>myBATis-plus-boot-starter</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>io.shardingsphere</groupId> <artifactId>sharding-jdbc-core</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <finalName>spring-boot-demo-sharding-jdbc</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.2. CustomSnowflakeKeyGenerator.java
package com.xiaoma.sharding.jdbc.config; import cn.hutool.core.lang.Snowflake; import io.shardingsphere.core.keygen.KeyGenerator; public class CustomSnowflakeKeyGenerator implements KeyGenerator { private Snowflake snowflake; public CustomSnowflakeKeyGenerator(Snowflake snowflake) { this.snowflake = snowflake; } @Override public Number generateKey() { return snowflake.nextId(); } }
2.3. DataSourceShardingConfig.java
@Configuration public class DataSourceShardingConfig { private static final Snowflake snowflake = IdUtil.createSnowflake(1, 1); /** * 需要手动配置事务管理器 */ @Bean public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "dataSource") @Primary public DataSource dataSource() throws SQLException { ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration(); // 设置分库策略 shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "ds${user_id % 2}")); // 设置规则适配的表 shardingRuleConfig.getBindingTableGroups().add("t_order"); // 设置分表策略 shardingRuleConfig.getTableRuleConfigs().add(orderTableRule()); shardingRuleConfig.setDefaultDataSourceName("ds0"); shardingRuleConfig.setDefaultTableShardingStrategyConfig(new NoneShjsardingStrategyConfiguration()); Properties properties = new Properties(); properties.setProperty("sql.show", "true"); return ShardingDataSourceFactory.createDataSource(dataSourceMap(), shardingRuleConfig, new ConcurrentHashMap<>(16), properties); } private TableRuleConfiguration orderTableRule() { TableRuleConfiguration tableRule = new TableRuleConfiguration(); // 设置逻辑表名 tableRule.setLogicTable("t_order"); // ds${0..1}.t_order_${0..2} 也可以写成 ds$->{0..1}.t_order_$->{0..1} tableRule.setActualDataNodes("ds${0..1}.t_order_${0..2}"); tableRule.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "t_order_$->{order_编程客栈id % 3}")); tableRule.setKeyGenerator(customKeyGenerator()); tableRule.setKeyGeneratorColumnName("order_id"); return tableRule; } private Map<String, DataSource> dataSourceMap() { Map<String, DataSource> dataSourceMap = new HashMap<>(16); // 配置第一个数据源 HikariDataSource ds0 = new HikariDataSource(); ds0.setDriverClassName("com.mysql.cj.jdbc.Driver"); ds0.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8"); ds0.setUsername("root"); ds0.setPassword("root"); // 配置第二个数据源 HikariDataSource ds1 = new HikariDataSource(); ds1.setDriverClassName("com.mysql.cj.jdbc.Driver"); ds1.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/test2?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8"); ds1.setUsername("root"); ds1.setPassword("root"); dataSourceMap.put("ds0", ds0); dataSourceMap.put("ds1", ds1); return dataSourceMap; } /** * 自定义主键生成器 */ private KeyGenerator customKeyGenerator() { return new CustomSnowflakeKeyGenerator(snowflake); } }
2.4. SpringBootDemoShardingJdbcApplicationTests.java
@Slf4j @RunWith(SpringRunner.class) @SpringBootTest public class SpringBootDemoShardingJdbcApplicationTests { @Autowired private OrderMapper orderMapper; /** * 测试新增 */ @Test public void testInsert() { for (long i = 1; i < 10; i++) { for (long j = 1; j < 20; j++) { Order order = Order.builder().userId(i).orderId(j).remark(RandomUtil.randomString(20)).build(); orderMapper.insert(order); } } } /** * 测试更新 */ @Test public void testUpdate() { Order update = new Order(); update.setRemark("修改备注信息"); orderMapper.update(update, Wrappers.<Order>update().lambda().eq(Order::getOrderId, 2).eq(Order::getUserId, 2)); } /** * 测试删除 */ @Test public void testDelete() { orderMapper.delete(new QueryWrapper<>()); } /** * 测试查询 */ @Test public void testSelect() { List<Order> orders = orderMapper.selectList(Wrappers.<Order>query().lambda().in(Order::getOrderId, 1, 2)); log.info("【orders】= {}", jsONUtil.toJsonStr(orders)); } }
到此这篇关于SpringBoot整合sharding-jdbc 实现分库分表操作的示例代码的文章就介绍到这了,更多相关SpringBoot sharding-jdbc分库分表内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论