Sharding-JDBC

本文深入探讨了Sharding-JDBC如何增强JDBC功能,实现数据库分库分表。讲解了逻辑表、分片键、数据节点等核心概念,并通过代码实例展示了配置数据源、定义分表规则的过程。此外,还介绍了行内、标准、复合等多种分片策略及其应用场景。最后,对比了Sharding-JDBC与Mycat的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01、主要概念

增强了JDBC的功能,使JDBC具有分库分表的作用。比如:SQL的解析、路由、执行和结果的处理等等。

02、框架:

逻辑表会在SQL解析和路由时被替换成真实的表名。

分片键不一定是主键,也不一定有业务含义。

03、核心概念

数据节点、逻辑表、真实表、动态表、广播表、绑定表、分片键

【1】、动态表

对于逻辑表的分表

【2】、广播表

全局表,每个分片的数据库都包含有该表。

【3】、绑定表

主表和字表的绑定关系应该在同一个数据库,负责无法关联出数据的完整性。

04、编写流程

  • 【1】、配置数据源-->>配置多个数据源
  • 【2】、定义表的分表规则
  • 【3】、配置分库+分表规则
  • 【4】、加载分片规则
  • 【5】、获取数据源

原生代码案例

package com.gupaoedu.jdbc;

import io.shardingsphere.api.config.rule.ShardingRuleConfiguration;
import io.shardingsphere.api.config.rule.TableRuleConfiguration;
import io.shardingsphere.api.config.strategy.InlineShardingStrategyConfiguration;
import io.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.apache.commons.dbcp.BasicDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @Author: wangyognxun
 * @Date: 2019/10/21 11:16
 * @Description:sharding-jdbc
 */
public class ShardJDBCTest {
    public static void main(String[] args) throws SQLException {
        // 配置真实数据源
        Map<String, DataSource> dataSourceMap = new HashMap<>();

        // 配置第一个数据源
        BasicDataSource dataSource1 = new BasicDataSource();
        dataSource1.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource1.setUrl("jdbc:mysql://localhost:3306/shard0");
        dataSource1.setUsername("root");
        dataSource1.setPassword("123456");
        dataSourceMap.put("ds0", dataSource1);

        // 配置第二个数据源
        BasicDataSource dataSource2 = new BasicDataSource();
        dataSource2.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource2.setUrl("jdbc:mysql://localhost:3306/shard1");
        dataSource2.setUsername("root");
        dataSource2.setPassword("123456");
        dataSourceMap.put("ds1", dataSource2);

        // 配置Order表规则
        TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration();
        orderTableRuleConfig.setLogicTable("order");
        orderTableRuleConfig.setActualDataNodes("ds${0..1}.order${0..1}");


        // 配置分库 + 分表策略
        orderTableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "ds${order_id % 2}"));
        orderTableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("order_id", "order${order_id % 2}"));

        // 配置分片规则
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig);

        Map<String,Object> map = new HashMap<>();

        // 获取数据源对象
        DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig,map, new Properties());

        String sql = "SELECT * from order WHERE user_id=?";
        try (
                Connection conn = dataSource.getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
                preparedStatement.setInt(1, 2673);
            System.out.println();
                try (ResultSet rs = preparedStatement.executeQuery()) {
                    while(rs.next()) {
                        // %2结果,路由到 shard1.order1
                        System.out.println("order_id---------"+rs.getInt(1));
                        System.out.println("user_id---------"+rs.getInt(2));
                        System.out.println("create_time---------"+rs.getTime(3));
                        System.out.println("total_price---------"+rs.getInt(4));
                }
            }
        }
    }
}

05、总结:

分片策略5种:

行内、标准、复合、Hint、无。

06、雪花算法(snowFlake)

07、spring的配置

# MyBatis配置
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.config-location=classpath:mybatis-config.xml

# 数据源配置
sharding.jdbc.datasource.names=ds0,ds1
sharding.jdbc.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds0.url=jdbc:mysql://localhost:3306/ds0
sharding.jdbc.datasource.ds0.username=root
sharding.jdbc.datasource.ds0.password=123456

sharding.jdbc.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds1.url=jdbc:mysql://localhost:3306/ds1
sharding.jdbc.datasource.ds1.username=root
sharding.jdbc.datasource.ds1.password=123456

sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=user_id
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=ds${user_id % 2}

# 分库算法 user_info,多库分表
# 单库内没有分表,注释了分表策略
sharding.jdbc.config.sharding.tables.user_info.actual-data-nodes=ds$->{0..1}.user_info
sharding.jdbc.config.sharding.tables.user_info.databaseStrategy.inline.shardingColumn=user_id
sharding.jdbc.config.sharding.tables.user_info.databaseStrategy.inline.algorithm-expression=ds${user_id % 2}

# 分库算法 t_order 多库分表
sharding.jdbc.config.sharding.tables.t_order.databaseStrategy.inline.shardingColumn=order_id
sharding.jdbc.config.sharding.tables.t_order.databaseStrategy.inline.algorithm-expression=ds${order_id % 2}
sharding.jdbc.config.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order

# 分库算法 t_order_item 多库分表
sharding.jdbc.config.sharding.tables.t_order_item.databaseStrategy.inline.shardingColumn=order_id
sharding.jdbc.config.sharding.tables.t_order_item.databaseStrategy.inline.algorithm-expression=ds${order_id % 2}
sharding.jdbc.config.sharding.tables.t_order_item.actual-data-nodes=ds$->{0..1}.t_order_item


# 绑定表规则列表,防止关联查询出现笛卡尔积
sharding.jdbc.config.sharding.binding-tables[0]=t_order,t_order_item

# 广播表
sharding.jdbc.config.sharding.broadcast-tables=t_config

08、分片策略【重点】

【1】、行表达式分片策略

InlineShardingStrategy类。只支持单分片键,提供对=和IN操作的支持。行内表达式的配置比较简单。

${begin..end}表示范围区间

${[unit1,unit2,unit_x]}表示枚举值

t_user_$->{u_id%8}表示t_user表根据u_id模8,而分成8张表,表名称为t_user_0到t_user_7。

【2】、标准分片策略

对应StandardShardingStrategy类

标准分片策略只支持单分片键,提供了提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法,分别对应于SQL语句中的=,IN和BETWEEN、AND。

如果要使用标准分片策略,必须要实现PreciseShardingAlgorithm,用来处理=和IN的分片。

RangeShardingAlgorithm是可选的。如果没有实现,SQL语句会发到所有的数据节点上执行。

sharding.jdbc.config.sharding.tables.user_info.databaseStrategy.standard.shardingColumn=user_id
sharding.jdbc.config.sharding.tables.user_info.databaseStrategy.standard.preciseAlgorithmClassName=com.gupaoedu.config.DBShardAlgo
sharding.jdbc.config.sharding.tables.user_info.tableStrategy.standard.shardingColumn=user_id
sharding.jdbc.config.sharding.tables.user_info.tableStrategy.standard.preciseAlgorithmClassName=com.gupaoedu.config.TblPreShardAlgo
sharding.jdbc.config.sharding.tables.user_info.tableStrategy.standard.rangeAlgorithmClassName=com.gupaoedu.config.TblRangeShardAlgo

 

import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;

import java.util.Collection;

/**
 * 数据库分库的策略,根据分片键,返回数据库名称
 */
public class DBShardAlgo implements PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
        String db_name="ds";
        Long num= preciseShardingValue.getValue()%2;
        db_name=db_name + num;
        System.out.println("----------------db_name:" + db_name);

        for (String each : collection) {
            System.out.println("ds:" + each);
            if (each.equals(db_name)) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }

}
import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;

import java.util.Collection;

/**
 * 等值查询使用的分片算法,包括in
 */
public class TblPreShardAlgo implements PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingColumn) {
        // 不分表
        System.out.println("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-availableTargetNames:" + availableTargetNames);
        for (String tbname : availableTargetNames) {
            return tbname;
        }
        throw new IllegalArgumentException();
    }
}
import com.google.common.collect.Range;
import io.shardingsphere.api.algorithm.sharding.RangeShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.RangeShardingAlgorithm;

import java.util.Collection;
import java.util.LinkedHashSet;

/**
 * 范围查询所使用的分片算法
 */
public class TblRangeShardAlgo implements RangeShardingAlgorithm<Long> {
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> rangeShardingValue) {
        System.out.println("范围-*-*-*-*-*-*-*-*-*-*-*---------------"+availableTargetNames);
        System.out.println("范围-*-*-*-*-*-*-*-*-*-*-*---------------"+rangeShardingValue);
        Collection<String> collect = new LinkedHashSet<>();
        Range<Long> valueRange = rangeShardingValue.getValueRange();
        for (Long i = valueRange.lowerEndpoint(); i <= valueRange.upperEndpoint(); i++) {
            // 不分表
            for (String each : availableTargetNames) {
                collect.add(each);
                /* if (each.endsWith(i % availableTargetNames.size() + "")) {
                    collect.add(each);
                }*/
            }
        }
        return collect;
    }

}

 

【3】、复合分片策略

对应ComplexShardingStrategy类

支持等值查询和范围查询

【4】、Hint分片策略

通过Hint而非SQL解析的方式分片的策略。

【5】、不分片策略

对应NoneShardingStrategy。不分片的策略。

08、分片算法

【1】、精确分片算法

用于处理使用单一键作为分片键的=与IN进行分片的场景。需要配合StandardShardingStrategy使用。

【2】、范围分片算法

用于处理使用单一键作为分片键的BETWEENAND进行分片的场景。需要配合StandardShardingStrategy使用。

如果不配置范围分片算法,范围查询默认会路由到所有节点。

【3】、复合分片算法

用于处理使用多键作为分片键进行分片的场景,包含多个分片键的逻辑较复杂,需要应用开发者自行处理其中的复杂度。需要配合ComplexShardingStrategy使用。

【4】、Hint分片算法

用于处理使用Hint行分片的场景。需要配合HintShardingStrategy使用。

 

 

09、Shareing-JDBC的工作流程

 SQL解析=>执行器优化=>SQL路由=>SQL改写=>SQL执行=>结果归并。

10、Sharding-JDBC实现原理

替换数据的4大对象:DataSource、Connection、Statement(PS)、ResulstSet。

11、与Mycat对比

 Sharding-JDBCMycat
工作层面JDBC协议MySQL协议/JDBC协议
运行方式Jar包,客户端独立服务,服务端
开发方式代码/配置改动连接地址(数据源)
运维方式管理独立服务,运维成本高
性能多线程并发按操作,性能高独立服务+网络开销,存在性能损失风险
功能范围协议层面包括分布式事务、数据迁移等
适用操作OLTPOLTP+OLAP
支持数据库基于JDBC协议的数据库MySQL和其他支持JDBC协议的数据库
支持语言Java项目中使用支持JDBC协议的语言

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值