当前位置:   article > 正文

ShardingSphere介绍及使用_shardingspheredatasourcefactory

shardingspheredatasourcefactory

前言:

今天我们来聊一聊ShardingSphere,相信做过电商相关项目的同学应该都知道或者用过这个中间件,没错,它是一个用来解决在业务数据超过单表或单库最大接受性能的情景下而出现的一款产品,主要用来对业务数据做水平和横向的扩展,也就是我们常说的分库分表。

ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。 他们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、云原生等各种多样化的应用场景。

Sharding-JDBC

 

定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

  • 适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
  • 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库

Sharding-Proxy 

定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前先提供MySQL/PostgreSQL版本,它可以使用任何兼容MySQL/PostgreSQL协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat等)操作数据,对DBA更加友好。

  • 向应用程序完全透明,可直接当做MySQL/PostgreSQL使用。
  • 适用于任何兼容MySQL/PostgreSQL协议的的客户端。

Sharding-Sidecar(TODO)

定位为Kubernetes的云原生数据库代理,以Sidecar的形式代理所有对数据库的访问。 通过无中心、零侵入的方案提供与数据库交互的的啮合层,即Database Mesh,又可称数据网格。

Database Mesh的关注重点在于如何将分布式的数据访问应用与数据库有机串联起来,它更加关注的是交互,是将杂乱无章的应用与数据库之间的交互有效的梳理。使用Database Mesh,访问数据库的应用和数据库终将形成一个巨大的网格体系,应用和数据库只需在网格体系中对号入座即可,它们都是被啮合层所治理的对象。

功能列表:

数据分片 

  • 分库 & 分表
  • 读写分离
  • 分片策略定制化
  • 无中心化分布式主键

分布式事务 

 

  • 标准化事务接口
  • XA强一致事务
  • 柔性事务

数据库治理 

  • 配置动态化
  • 编排 & 治理
  • 数据脱敏
  • 可视化链路追踪
  • 弹性伸缩(规划中)

 使用:

1.数据分片

   

不使用Spring

引入Maven依赖

  1. <dependency>
  2. <groupId>org.apache.shardingsphere</groupId>
  3. <artifactId>sharding-jdbc-core</artifactId>
  4. <version>${sharding-sphere.version}</version>
  5. </dependency>

基于Java编码的规则配置

Sharding-JDBC的分库分表通过规则配置描述,以下例子是根据user_id取模分库, 且根据order_id取模分表的两库两表的配置。

  1. // 配置真实数据源
  2. Map<String, DataSource> dataSourceMap = new HashMap<>();
  3. // 配置第一个数据源
  4. BasicDataSource dataSource1 = new BasicDataSource();
  5. dataSource1.setDriverClassName("com.mysql.jdbc.Driver");
  6. dataSource1.setUrl("jdbc:mysql://localhost:3306/ds0");
  7. dataSource1.setUsername("root");
  8. dataSource1.setPassword("");
  9. dataSourceMap.put("ds0", dataSource1);
  10. // 配置第二个数据源
  11. BasicDataSource dataSource2 = new BasicDataSource();
  12. dataSource2.setDriverClassName("com.mysql.jdbc.Driver");
  13. dataSource2.setUrl("jdbc:mysql://localhost:3306/ds1");
  14. dataSource2.setUsername("root");
  15. dataSource2.setPassword("");
  16. dataSourceMap.put("ds1", dataSource2);
  17. // 配置Order表规则
  18. TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration("t_order","ds${0..1}.t_order${0..1}");
  19. // 配置分库 + 分表策略
  20. orderTableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "ds${user_id % 2}"));
  21. orderTableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "t_order${order_id % 2}"));
  22. // 配置分片规则
  23. ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
  24. shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig);
  25. // 省略配置order_item表规则...
  26. // ...
  27. // 获取数据源对象
  28. DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new Properties());

 基于Yaml的规则配置

  1. dataSources:
  2. ds0: !!org.apache.commons.dbcp.BasicDataSource
  3. driverClassName: com.mysql.jdbc.Driver
  4. url: jdbc:mysql://localhost:3306/ds0
  5. username: root
  6. password:
  7. ds1: !!org.apache.commons.dbcp.BasicDataSource
  8. driverClassName: com.mysql.jdbc.Driver
  9. url: jdbc:mysql://localhost:3306/ds1
  10. username: root
  11. password:
  12. shardingRule:
  13. tables:
  14. t_order:
  15. actualDataNodes: ds${0..1}.t_order${0..1}
  16. databaseStrategy:
  17. inline:
  18. shardingColumn: user_id
  19. algorithmExpression: ds${user_id % 2}
  20. tableStrategy:
  21. inline:
  22. shardingColumn: order_id
  23. algorithmExpression: t_order${order_id % 2}
  24. t_order_item:
  25. actualDataNodes: ds${0..1}.t_order_item${0..1}
  26. databaseStrategy:
  27. inline:
  28. shardingColumn: user_id
  29. algorithmExpression: ds${user_id % 2}
  30. tableStrategy:
  31. inline:
  32. shardingColumn: order_id
  33. algorithmExpression: t_order_item${order_id % 2}
DataSource dataSource = YamlShardingDataSourceFactory.createDataSource(yamlFile);

使用原生JDBC

通过ShardingDataSourceFactory或者YamlShardingDataSourceFactory工厂和规则配置对象获取ShardingDataSource,ShardingDataSource实现自JDBC的标准接口DataSource。然后可通过DataSource选择使用原生JDBC开发,或者使用JPA, MyBatis等ORM工具。 以JDBC原生实现为例:

  1. DataSource dataSource = YamlShardingDataSourceFactory.createDataSource(yamlFile);
  2. String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?";
  3. try (
  4. Connection conn = dataSource.getConnection();
  5. PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
  6. preparedStatement.setInt(1, 10);
  7. preparedStatement.setInt(2, 1001);
  8. try (ResultSet rs = preparedStatement.executeQuery()) {
  9. while(rs.next()) {
  10. System.out.println(rs.getInt(1));
  11. System.out.println(rs.getInt(2));
  12. }
  13. }
  14. }

使用Spring

引入Maven依赖

  1. <!-- for spring boot -->
  2. <dependency>
  3. <groupId>org.apache.shardingsphere</groupId>
  4. <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
  5. <version>${sharding-sphere.version}</version>
  6. </dependency>
  7. <!-- for spring namespace -->
  8. <dependency>
  9. <groupId>org.apache.shardingsphere</groupId>
  10. <artifactId>sharding-jdbc-spring-namespace</artifactId>
  11. <version>${sharding-sphere.version}</version>
  12. </dependency>

基于Spring boot的规则配置

  1. spring.shardingsphere.datasource.names=ds0,ds1
  2. spring.shardingsphere.datasource.ds0.type=org.apache.commons.dbcp2.BasicDataSource
  3. spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
  4. spring.shardingsphere.datasource.ds0.url=jdbc:mysql://localhost:3306/ds0
  5. spring.shardingsphere.datasource.ds0.username=root
  6. spring.shardingsphere.datasource.ds0.password=
  7. spring.shardingsphere.datasource.ds1.type=org.apache.commons.dbcp2.BasicDataSource
  8. spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
  9. spring.shardingsphere.datasource.ds1.url=jdbc:mysql://localhost:3306/ds1
  10. spring.shardingsphere.datasource.ds1.username=root
  11. spring.shardingsphere.datasource.ds1.password=
  12. spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
  13. spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{user_id % 2}
  14. spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order$->{0..1}
  15. spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
  16. spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order$->{order_id % 2}
  17. spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds$->{0..1}.t_order_item$->{0..1}
  18. spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
  19. spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item$->{order_id % 2}

2.读写分离 

不使用Spring

引入Maven依赖

  1. <dependency>
  2. <groupId>org.apache.shardingsphere</groupId>
  3. <artifactId>sharding-jdbc-core</artifactId>
  4. <version>${sharding-sphere.version}</version>
  5. </dependency>

基于Java编码的规则配置

  1. // 配置真实数据源
  2. Map<String, DataSource> dataSourceMap = new HashMap<>();
  3. // 配置主库
  4. BasicDataSource masterDataSource = new BasicDataSource();
  5. masterDataSource.setDriverClassName("com.mysql.jdbc.Driver");
  6. masterDataSource.setUrl("jdbc:mysql://localhost:3306/ds_master");
  7. masterDataSource.setUsername("root");
  8. masterDataSource.setPassword("");
  9. dataSourceMap.put("ds_master", masterDataSource);
  10. // 配置第一个从库
  11. BasicDataSource slaveDataSource1 = new BasicDataSource();
  12. slaveDataSource1.setDriverClassName("com.mysql.jdbc.Driver");
  13. slaveDataSource1.setUrl("jdbc:mysql://localhost:3306/ds_slave0");
  14. slaveDataSource1.setUsername("root");
  15. slaveDataSource1.setPassword("");
  16. dataSourceMap.put("ds_slave0", slaveDataSource1);
  17. // 配置第二个从库
  18. BasicDataSource slaveDataSource2 = new BasicDataSource();
  19. slaveDataSource2.setDriverClassName("com.mysql.jdbc.Driver");
  20. slaveDataSource2.setUrl("jdbc:mysql://localhost:3306/ds_slave1");
  21. slaveDataSource2.setUsername("root");
  22. slaveDataSource2.setPassword("");
  23. dataSourceMap.put("ds_slave1", slaveDataSource2);
  24. // 配置读写分离规则
  25. MasterSlaveRuleConfiguration masterSlaveRuleConfig = new MasterSlaveRuleConfiguration("ds_master_slave", "ds_master", Arrays.asList("ds_slave0", "ds_slave1"));
  26. // 获取数据源对象
  27. DataSource dataSource = MasterSlaveDataSourceFactory.createDataSource(dataSourceMap, masterSlaveRuleConfig, new Properties());

基于Yaml的规则配置

或通过Yaml方式配置,与以上配置等价:

  1. dataSources:
  2. ds_master: !!org.apache.commons.dbcp.BasicDataSource
  3. driverClassName: com.mysql.jdbc.Driver
  4. url: jdbc:mysql://localhost:3306/ds_master
  5. username: root
  6. password:
  7. ds_slave0: !!org.apache.commons.dbcp.BasicDataSource
  8. driverClassName: com.mysql.jdbc.Driver
  9. url: jdbc:mysql://localhost:3306/ds_slave0
  10. username: root
  11. password:
  12. ds_slave1: !!org.apache.commons.dbcp.BasicDataSource
  13. driverClassName: com.mysql.jdbc.Driver
  14. url: jdbc:mysql://localhost:3306/ds_slave1
  15. username: root
  16. password:
  17. masterSlaveRule:
  18. name: ds_ms
  19. masterDataSourceName: ds_master
  20. slaveDataSourceNames: [ds_slave0, ds_slave1]
  21. props:
  22. sql.show: true
DataSource dataSource = YamlMasterSlaveDataSourceFactory.createDataSource(yamlFile);

使用原生JDBC

通过YamlMasterSlaveDataSourceFactory工厂和规则配置对象获取MasterSlaveDataSource,MasterSlaveDataSource实现自JDBC的标准接口DataSource。然后可通过DataSource选择使用原生JDBC开发,或者使用JPA, MyBatis等ORM工具。 以JDBC原生实现为例:

  1. DataSource dataSource = YamlMasterSlaveDataSourceFactory.createDataSource(yamlFile);
  2. String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?";
  3. try (
  4. Connection conn = dataSource.getConnection();
  5. PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
  6. preparedStatement.setInt(1, 10);
  7. preparedStatement.setInt(2, 1001);
  8. try (ResultSet rs = preparedStatement.executeQuery()) {
  9. while(rs.next()) {
  10. System.out.println(rs.getInt(1));
  11. System.out.println(rs.getInt(2));
  12. }
  13. }
  14. }

使用Spring

引入Maven依赖

  1. <!-- for spring boot -->
  2. <dependency>
  3. <groupId>org.apache.shardingsphere</groupId>
  4. <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
  5. <version>${sharding-sphere.version}</version>
  6. </dependency>

基于Spring boot的规则配置

  1. spring.shardingsphere.datasource.names=master,slave0,slave1
  2. spring.shardingsphere.datasource.master.type=org.apache.commons.dbcp.BasicDataSource
  3. spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
  4. spring.shardingsphere.datasource.master.url=jdbc:mysql://localhost:3306/master
  5. spring.shardingsphere.datasource.master.username=root
  6. spring.shardingsphere.datasource.master.password=
  7. spring.shardingsphere.datasource.slave0.type=org.apache.commons.dbcp.BasicDataSource
  8. spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.jdbc.Driver
  9. spring.shardingsphere.datasource.slave0.url=jdbc:mysql://localhost:3306/slave0
  10. spring.shardingsphere.datasource.slave0.username=root
  11. spring.shardingsphere.datasource.slave0.password=
  12. spring.shardingsphere.datasource.slave1.type=org.apache.commons.dbcp.BasicDataSource
  13. spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.jdbc.Driver
  14. spring.shardingsphere.datasource.slave1.url=jdbc:mysql://localhost:3306/slave1
  15. spring.shardingsphere.datasource.slave1.username=root
  16. spring.shardingsphere.datasource.slave1.password=
  17. spring.shardingsphere.masterslave.name=ms
  18. spring.shardingsphere.masterslave.master-data-source-name=master
  19. spring.shardingsphere.masterslave.slave-data-source-names=slave0,slave1
  20. spring.shardingsphere.props.sql.show=true
基于Spring boot + JNDI的规则配置

如果您计划使用Spring boot + JNDI的方式,在应用容器(如Tomcat)中使用Sharding-JDBC时,可使用spring.shardingsphere.datasource.${datasourceName}.jndiName来代替数据源的一系列配置。 如

  1. spring.shardingsphere.datasource.names=master,slave0,slave1
  2. spring.shardingsphere.datasource.master.jndi-name=java:comp/env/jdbc/master
  3. spring.shardingsphere.datasource.slave0.jndi-name=jdbc/slave0
  4. spring.shardingsphere.datasource.slave1.jndi-name=jdbc/slave1
  5. spring.shardingsphere.masterslave.name=ms
  6. spring.shardingsphere.masterslave.master-data-source-name=master
  7. spring.shardingsphere.masterslave.slave-data-source-names=slave0,slave1
  8. spring.shardingsphere.props.sql.show=true

3.分布式事务

不使用Spring

引入Maven依赖

  1. <dependency>
  2. <groupId>org.apache.shardingsphere</groupId>
  3. <artifactId>sharding-jdbc-core</artifactId>
  4. <version>${sharding-sphere.version}</version>
  5. </dependency>
  6. <!-- 使用XA事务时,需要引入此模块 -->
  7. <dependency>
  8. <groupId>org.apache.shardingsphere</groupId>
  9. <artifactId>sharding-transaction-xa-core</artifactId>
  10. <version>${shardingsphere.version}</version>
  11. </dependency>
  12. <!-- 使用BASE事务时,需要引入此模块 -->
  13. <dependency>
  14. <groupId>org.apache.shardingsphere</groupId>
  15. <artifactId>sharding-transaction-base-seata-at</artifactId>
  16. <version>${sharding-sphere.version}</version>
  17. </dependency>

基于Java编码方式使用分布式事务

  1. TransactionTypeHolder.set(TransactionType.XA); // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE
  2. try (Connection connection = dataSource.getConnection()) { // dataSource的类型为ShardingDataSource
  3. connection.setAutoCommit(false);
  4. PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO t_order (user_id, status) VALUES (?, ?)");
  5. preparedStatement.setObject(1, i);
  6. preparedStatement.setObject(2, "init");
  7. preparedStatement.executeUpdate();
  8. connection.commit();
  9. }

使用Spring-namespace

引入Maven依赖

  1. <dependency>
  2. <groupId>org.apache.shardingsphere</groupId>
  3. <artifactId>sharding-jdbc-spring-namespace</artifactId>
  4. <version>${shardingsphere.version}</version>
  5. </dependency>
  6. <!-- 使用XA事务时,需要引入此模块 -->
  7. <dependency>
  8. <groupId>org.apache.shardingsphere</groupId>
  9. <artifactId>sharding-transaction-xa-core</artifactId>
  10. <version>${shardingsphere.version}</version>
  11. </dependency>
  12. <!-- 使用BASE事务时,需要引入此模块 -->
  13. <dependency>
  14. <groupId>org.apache.shardingsphere</groupId>
  15. <artifactId>sharding-transaction-base-seata-at</artifactId>
  16. <version>${sharding-sphere.version}</version>
  17. </dependency>

配置spring-namespace的事务管理器

  1. <!-- 进行ShardingDataSource的相关配置 -->
  2. ...
  3. <!-- 开启自动扫描@ShardingTransactionType注解,使用Spring原生的AOP在类和方法上进行增强 -->
  4. <sharding:tx-type-annotation-driven />
  5. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  6. <property name="dataSource" ref="shardingDataSource" />
  7. </bean>
  8. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  9. <property name="dataSource" ref="shardingDataSource" />
  10. </bean>
  11. <tx:annotation-driven />

业务代码中使用分布式事务

  1. @ShardingTransactionType(TransactionType.XA) // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE
  2. public void insert() {
  3. jdbcTemplate.execute("INSERT INTO t_order (user_id, status) VALUES (?, ?)", (PreparedStatementCallback<Object>) preparedStatement -> {
  4. preparedStatement.setObject(1, i);
  5. preparedStatement.setObject(2, "init");
  6. preparedStatement.executeUpdate();
  7. });
  8. }

使用Spring-boot

引入Maven依赖

  1. <dependency>
  2. <groupId>org.apache.shardingsphere</groupId>
  3. <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
  4. <version>${shardingsphere.version}</version>
  5. </dependency>
  6. <!-- 使用XA事务时,需要引入此模块 -->
  7. <dependency>
  8. <groupId>org.apache.shardingsphere</groupId>
  9. <artifactId>sharding-transaction-xa-core</artifactId>
  10. <version>${shardingsphere.version}</version>
  11. </dependency>
  12. <!-- 使用BASE事务时,需要引入此模块 -->
  13. <dependency>
  14. <groupId>org.apache.shardingsphere</groupId>
  15. <artifactId>sharding-transaction-base-seata-at</artifactId>
  16. <version>${sharding-sphere.version}</version>
  17. </dependency>

配置spring-boot的事务管理器

  1. @Configuration
  2. @EnableTransactionManagement
  3. public class TransactionConfiguration {
  4. @Bean
  5. public PlatformTransactionManager txManager(final DataSource dataSource) {
  6. return new DataSourceTransactionManager(dataSource);
  7. }
  8. @Bean
  9. public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
  10. return new JdbcTemplate(dataSource);
  11. }
  12. }

业务代码中使用分布式事务

  1. @Transactional
  2. @ShardingTransactionType(TransactionType.XA) // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE
  3. public void insert() {
  4. jdbcTemplate.execute("INSERT INTO t_order (user_id, status) VALUES (?, ?)", (PreparedStatementCallback<Object>) preparedStatement -> {
  5. preparedStatement.setObject(1, i);
  6. preparedStatement.setObject(2, "init");
  7. preparedStatement.executeUpdate();
  8. });
  9. }

结尾:

本篇文章只是对ShardingSphere做了简单的介绍及部分功能的使用,想要详细深入的学习及使用可以参考官网:Index of /document/legacy/4.x

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/757124
推荐阅读
相关标签
  

闽ICP备14008679号