Sharding-JDBC 使用方法
Sharding-JDBC 使用方法
以下是Sharding-JDBC在Spring Boot项目中的完整使用示例,包含详细的配置和代码实现。
1. Maven依赖配置 (pom.xml)
<dependencies><!-- Spring Boot 核心依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- Spring Boot Data JPA --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- Sharding-JDBC --><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.3.2</version> <!-- 使用最新稳定版本 --></dependency><!-- MySQL 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>
</dependencies>
2. 分片规则配置 (application.yml)
spring:application:name: sharding-jdbc-demo# Sharding-JDBC 配置shardingsphere:datasource:# 数据源名称集合,多数据源以逗号分隔names: ds0,ds1# 第一个数据源配置ds0:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/big_market_0?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=falseusername: rootpassword: roothikari:minimum-idle: 5maximum-pool-size: 20idle-timeout: 30000connection-timeout: 30000pool-name: ds0-pool# 第二个数据源配置ds1:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/big_market_1?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=falseusername: rootpassword: roothikari:minimum-idle: 5maximum-pool-size: 20idle-timeout: 30000connection-timeout: 30000pool-name: ds1-pool# 分片规则配置rules:sharding:# 表规则配置tables:# 订单表分片配置t_order:# 数据节点配置,格式为:数据源名称.表名actual-data-nodes: ds$->{0..1}.t_order$->{0..3}# 数据库分片策略database-strategy:standard:# 分片键sharding-column: user_id# 分片算法名称sharding-algorithm-name: database_inline# 表分片策略table-strategy:standard:# 分片键sharding-column: order_id# 分片算法名称sharding-algorithm-name: table_inline# 主键生成策略key-generate-strategy:column: order_idkey-generator-name: snowflake# 订单项表分片配置t_order_item:actual-data-nodes: ds$->{0..1}.t_order_item$->{0..3}database-strategy:standard:sharding-column: user_idsharding-algorithm-name: database_inlinetable-strategy:standard:sharding-column: order_idsharding-algorithm-name: table_inlinekey-generate-strategy:column: order_item_idkey-generator-name: snowflake# 分片算法配置sharding-algorithms:# 数据库分片算法database_inline:type: INLINEprops:algorithm-expression: ds$->{user_id % 2}# 表分片算法table_inline:type: INLINEprops:algorithm-expression: t_order$->{order_id % 4}# 主键生成器配置key-generators:snowflake:type: SNOWFLAKEprops:worker-id: 123# 绑定表配置,用于优化多表关联查询binding-tables:- t_order,t_order_item# 广播表配置,在所有分片库中都存在的表broadcast-tables:- t_config# 模式配置mode:type: Memory# 属性配置props:sql-show: true
3. 自定义分片算法实现
3.1 数据库分片算法
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingValue;import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;/*** 自定义复杂分片算法实现* 支持多个分片键的分片策略*/
public class CustomComplexDatabaseShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {/*** 数据库分片算法实现* * @param availableTargetNames 可用的数据源名称集合* @param shardingValue 分片键值对象* @return 分片后的数据源名称集合*/@Overridepublic Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> shardingValue) {// 定义返回的数据源集合Set<String> result = new LinkedHashSet<>();// 获取分片键及其对应的值Map<String, Collection<Long>> columnNameAndShardingValuesMap = shardingValue.getShardingValuesMap();// 假设我们使用user_id作为分片键if (columnNameAndShardingValuesMap.containsKey("user_id")) {Collection<Long> userIds = columnNameAndShardingValuesMap.get("user_id");// 对每个user_id值进行分片计算for (Long userId : userIds) {// 使用简单的取模算法String targetDataSource = "ds" + (userId % availableTargetNames.size());if (availableTargetNames.contains(targetDataSource)) {result.add(targetDataSource);}}}return result;}
}
3.2 表分片算法
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;import java.util.Collection;/*** 精确分片算法实现* 用于处理 = 和 IN 条件的分片*/
public class CustomPreciseTableShardingAlgorithm implements PreciseShardingAlgorithm<Long> {/*** 表分片算法实现* * @param availableTargetNames 可用的表名称集合* @param shardingValue 分片键值对象* @return 分片后的表名称*/@Overridepublic String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {// 获取分片键名称String columnName = shardingValue.getColumnName();// 获取分片键值Long value = shardingValue.getValue();// 遍历所有可用表名,找到匹配的表for (String tableName : availableTargetNames) {// 例如:根据订单ID取模选择表if (tableName.endsWith(String.valueOf(value % 4))) {return tableName;}}// 如果没有找到匹配的表,抛出异常throw new UnsupportedOperationException("无法找到匹配的表: " + availableTargetNames + " for value: " + value);}
}
4. 实体类定义
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;/*** 订单实体类*/
@Entity
@Table(name = "t_order")
public class Order {@Id@Column(name = "order_id")private Long orderId;@Column(name = "user_id")private Long userId;@Column(name = "total_amount")private BigDecimal totalAmount;@Column(name = "status")private String status;@Column(name = "create_time")private Date createTime;// getter和setter方法省略// ...
}
5. Repository接口
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;import java.util.List;/*** 订单数据访问层*/
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {/*** 根据用户ID查询订单* Sharding-JDBC会自动路由到对应的分片*/List<Order> findByUserId(Long userId);/*** 自定义查询* Sharding-JDBC会自动解析SQL并路由到对应的分片*/@Query("SELECT o FROM Order o WHERE o.userId = ?1 AND o.status = ?2")List<Order> findByUserIdAndStatus(Long userId, String status);
}
6. 服务层实现
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;/*** 订单服务实现*/
@Service
public class OrderService {@Autowiredprivate OrderRepository orderRepository;/*** 创建订单* 使用事务确保数据一致性*/@Transactionalpublic Order createOrder(Order order) {// Sharding-JDBC会根据分片规则自动将订单保存到对应的数据库和表return orderRepository.save(order);}/*** 根据用户ID查询订单* Sharding-JDBC会根据user_id路由到对应的数据库分片*/public List<Order> getOrdersByUserId(Long userId) {return orderRepository.findByUserId(userId);}/*** 根据用户ID和状态查询订单*/public List<Order> getOrdersByUserIdAndStatus(Long userId, String status) {return orderRepository.findByUserIdAndStatus(userId, status);}
}
7. 控制器示例
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** 订单控制器*/
@RestController
@RequestMapping("/api/orders")
public class OrderController {@Autowiredprivate OrderService orderService;/*** 创建订单*/@PostMappingpublic Order createOrder(@RequestBody Order order) {return orderService.createOrder(order);}/*** 根据用户ID查询订单*/@GetMapping("/user/{userId}")public List<Order> getOrdersByUserId(@PathVariable Long userId) {return orderService.getOrdersByUserId(userId);}/*** 根据用户ID和状态查询订单*/@GetMapping("/user/{userId}/status/{status}")public List<Order> getOrdersByUserIdAndStatus(@PathVariable Long userId, @PathVariable String status) {return orderService.getOrdersByUserIdAndStatus(userId, status);}
}
8. 自定义Sharding-JDBC配置类 (可选)
如果需要通过Java代码配置Sharding-JDBC,可以使用以下配置类:
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.StandardShardingStrategyConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;/*** Sharding-JDBC 配置类*/
@Configuration
public class ShardingJdbcConfig {/*** 创建ShardingDataSource*/@Beanpublic DataSource dataSource() throws SQLException {// 配置真实数据源Map<String, DataSource> dataSourceMap = new HashMap<>();dataSourceMap.put("ds0", createDataSource("ds0"));dataSourceMap.put("ds1", createDataSource("ds1"));// 配置分片规则ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();// 添加表规则配置shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfiguration());shardingRuleConfig.getTableRuleConfigs().add(orderItemTableRuleConfiguration());// 配置默认数据库分片策略shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_id", new CustomPreciseDatabaseShardingAlgorithm()));// 配置默认表分片策略shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("order_id", new CustomPreciseTableShardingAlgorithm()));// 创建ShardingDataSourcereturn ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new Properties());}/*** 创建数据源*/private DataSource createDataSource(String dataSourceName) {// 这里实现数据源创建逻辑// ...return null; // 实际使用时返回真实的数据源}/*** 订单表规则配置*/private TableRuleConfiguration orderTableRuleConfiguration() {TableRuleConfiguration tableRuleConfig = new TableRuleConfiguration("t_order", "ds${0..1}.t_order${0..3}");// 设置主键生成策略// tableRuleConfig.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "order_id"));return tableRuleConfig;}/*** 订单项表规则配置*/private TableRuleConfiguration orderItemTableRuleConfiguration() {TableRuleConfiguration tableRuleConfig = new TableRuleConfiguration("t_order_item", "ds${0..1}.t_order_item${0..3}");// 设置主键生成策略// tableRuleConfig.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "order_item_id"));return tableRuleConfig;}
}
9. 注意事项
-
数据库初始化:在使用Sharding-JDBC之前,需要手动创建好所有分片数据库和表。
-
SQL兼容性:部分复杂SQL可能不被Sharding-JDBC支持,需要参考官方文档进行SQL优化。
-
事务支持:Sharding-JDBC支持本地事务,但对于分布式事务,需要使用Seata等额外组件。
-
监控与运维:建议配置
sql-show: true
来查看实际执行的SQL,方便调试和优化。 -
性能优化:
- 使用绑定表减少笛卡尔积查询
- 合理设计分片键,避免热点数据
- 对分片表进行合理的索引设计
这个示例涵盖了Sharding-JDBC的核心使用方法,包括数据源配置、分片规则定义、分片算法实现以及在Spring Boot项目中的集成使用。根据实际业务需求,可以调整分片策略和算法实现。