sharding-jdbc一些概念

一、sharding-jdbc与shardingproxy

ShardingSphere-JDBC 定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。

客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架

  • 适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC;

  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, HikariCP 等;

  • 支持任意实现 JDBC 规范的数据库,目前支持 MySQL,PostgreSQL,Oracle,SQLServer 以及任何可使用 JDBC 访问的数据库。

ShardingSphere-Proxy 定位为透明化的数据库代理端,通过实现数据库二进制协议,对异构语言提供支持

  • 向应用程序完全透明,可直接当做 MySQL/PostgreSQL 使用;

  • 兼容 MariaDB 等基于 MySQL 协议的数据库,以及 openGauss 等基于 PostgreSQL 协议的数据库;

  • 适用于任何兼容 MySQL/PostgreSQL 协议的的客户端,如:MySQL Command Client, MySQL Workbench, Navicat 等。

ShardingSphere-JDBC

ShardingSphere-Proxy

数据库

任意

MySQL/PostgreSQL

连接消耗数

异构语言

仅 Java

任意

性能

损耗低

损耗略高

无中心化

静态入口

二、核心概念

逻辑表:水平拆分的数据库的相同逻辑和数据结构表的总称

真实表:在分片的数据库中真实存在的物理表。

数据节点:数据分片的最小单元。由数据源名称和数据表组成

绑定表:分片规则一致的主表和子表。

广播表:也叫公共表,指素有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中都完全一致。例如字典表。

分片键:用于分片的数据库字段,是将数据库(表)进行水平拆分的关键字段。

SQL中若没有分片字段,将会执行全路由,性能会很差。

分片算法:通过分片算法将数据进行分片,支持通过=、BETWEEN和IN分片。分片算法需要由应用开发者自行实现,可实现的灵活度非常高。

分片策略:真正用于进行分片操作的是分片键+分片算法,也就是分片策略。在ShardingJDBC中一般采用基于Groovy表达式的inline分片策略,通过一个包含分片键的算法表达式来制定分片策略,如t_order$->{order_id%2}标识根据u_id模2,分成2张表,表名称为t_order0到t_order2。

db0
  ├── t_order0
  └── t_order1
  ├── t_order_item0
  ├── t_order_item1
db1
  ├── t_order0
  ├── t_order1
  ├── t_order_item0
  ├── t_order_item1

以上图为例,各种概念对应如下:

逻辑表:t_order

真实表: t_order0、t_order1、 t_order_item0、t_order_item1

数据节点:db0.t_order0、db0.t_order1、db0.t_order0、db1.t_order1

绑定表:t_order、t_order_item (都是按照order_id )分片

分片策略 = 分片键 + 分片算法

分片键:t_user_表中的uid (t_order$->{order_id%8})

分片算法:

自动化分片算法:便捷的托管所有数据节点,使用者无需关注真实表的物理分布。 包括取模、哈希、范围、时间等常用分片算法的实现

自定义分片算法:提供接口让应用开发者自行实现与业务实现紧密相关的分片算法,并允许使用者自行管理真实表的物理分布。

标准分片算法:使用单一键作为分片键的 =、IN、BETWEEN AND、>、<、>=、<= 进行分片的场景。

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

Hint 分片算法:用于处理使用 Hint 行分片的场景。

三、springboot整合sharding-jdbc

1、docker配置主从库

2、主服务创建表


CREATE TABLE `t_dict`  (
  `dict_id` bigint(0) PRIMARY KEY NOT NULL,
  `ustatus` varchar(100) NOT NULL,
  `uvalue` varchar(100) NOT NULL
);

CREATE TABLE `t_dict_1`  (
  `dict_id` bigint(0) PRIMARY KEY NOT NULL,
  `ustatus` varchar(100) NOT NULL,
  `uvalue` varchar(100) NOT NULL
);
CREATE TABLE `t_dict_2`  (
  `dict_id` bigint(0) PRIMARY KEY NOT NULL,
  `ustatus` varchar(100) NOT NULL,
  `uvalue` varchar(100) NOT NULL
);



CREATE TABLE `t_user`  (
  `user_id` bigint(0) PRIMARY KEY NOT NULL,
  `username` varchar(100) NOT NULL,
  `ustatus` varchar(50) NOT NULL,
  `uage` int(3)
);

CREATE TABLE `t_user_1`  (
  `user_id` bigint(0) PRIMARY KEY NOT NULL,
  `username` varchar(100) NOT NULL,
  `ustatus` varchar(50) NOT NULL,
  `uage` int(3)
);
CREATE TABLE `t_user_2`  (
  `user_id` bigint(0) PRIMARY KEY NOT NULL,
  `username` varchar(100) NOT NULL,
  `ustatus` varchar(50) NOT NULL,
  `uage` int(3)
);
CREATE TABLE course (
                          cid BIGINT(20) PRIMARY KEY,
                          cname VARCHAR(50) NOT NULL,
                          user_id BIGINT(20) NOT NULL,
                          cstatus varchar(10) NOT NULL
);


CREATE TABLE course_1 (
    cid BIGINT(20) PRIMARY KEY,
    cname VARCHAR(50) NOT NULL,
    user_id BIGINT(20) NOT NULL,
    cstatus varchar(10) NOT NULL
);

CREATE TABLE course_2 (
    cid BIGINT(20) PRIMARY KEY,
    cname VARCHAR(50) NOT NULL,
    user_id BIGINT(20) NOT NULL,
    cstatus varchar(10) NOT NULL
);

3、创建springbot项目中引入依赖

<?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>

    <groupId>com.demo</groupId>
    <artifactId>ShardingSphereDemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.1.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.22</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
    </dependencies>
</project>

4、通过mybatis-plus-generator反编译生成entity、mapper、service

5.1 单库分表

server.port=8080
#配置数据源
spring.shardingsphere.datasource.names=m1

spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://192.168.2.133:3306/db1?useSSL=false
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456
#配置真实表分布 
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m1.course_$->{1..2}
#主键生成策略
spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.course.key-generator.props.worker.id=1
#配置分表策略
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
#
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1}
#其他运行属性
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true

单测类

 @Autowired
CourseMapper courseMapper;
   
@Test
    public void addCourse(){
        for(int i = 0 ; i < 10 ; i ++){
            Course c = new Course();
            c.setCname("test");
            c.setUserId(Long.valueOf(""+(1000+i)));
            c.setCstatus("1");
            courseMapper.insert(c);
        }
    }

主键id为奇数的分片到course_2,偶数course_1

5.2 多库分表,修改配置

#配置多个数据源
spring.shardingsphere.datasource.names=m1,m2

spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://192.168.2.133:3306/db1?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456

spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m2.url=jdbc:mysql://192.168.2.133:3306/db1?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=123456
#真实表分布,分库,分表
spring.shardingsphere.sharding.tables.course.actual-data-nodes=m$->{1..2}.course_$->{1..2}

spring.shardingsphere.sharding.tables.course.key-generator.column=cid
spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.course.key-generator.props.worker.id=1
#inline分片策略
#spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=cid
#spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{cid%2+1}
#inline策略--不支持范围查询
#spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=cid
#spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=m$->{cid%2+1}

#打印sql
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true

主键为偶数进到db1.course_1,主键为奇数进到db2.course_2

5.3.分库、分表算法

实现 PreciseShardingAlgorithm 接口,并重写 doSharding() 方法,自行处理分库、分表逻辑。其他分片策略亦如此

select * from course where cid = ? or cid in (?,?)

分库策略:通过对cid取模加1,计算落路由到那个库 ,使用的分库策略course_$->{cid%2+1)

public class MyPreciseDSShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
    //select * from course where cid = ? or cid in (?,?)
    @Override
    public String doSharding(Collection<String> databaseNames, PreciseShardingValue<Long> cidValue) {
        
        //实现 course_$->{cid%2+1)
        BigInteger shardingValueB = BigInteger.valueOf(cidValue);
        BigInteger resB = (shardingValueB.mod(new BigInteger("2"))).add(new BigInteger("1"));
        String key = "m"+resB;
        if(availableTargetNames.contains(key)){
            return key;
        }
    }
}

public class MyPreciseDSShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
  
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        //实现 course_$->{cid%2+1)
        BigInteger cidValue = BigInteger.valueOf(shardingValue);
        BigInteger resB = (cidValue.mod(new BigInteger("2"))).add(new BigInteger("1"));
        String key = "m"+resB;
        if(availableTargetNames.contains(key)){
            return key;
        } 
    }
}

分库策略配置:databaseNames 参数为所有的数据库,cidValue为分片键

spring.shardingsphere.sharding.tables.course.database-strategy.standard.sharding-column=cid
spring.shardingsphere.sharding.tables.course.database-strategy.standard.precise-algorithm-class-name=com.kbp.shard.algorithem.MyPreciseDSShardingAlgorithm

public class MyPreciseTableShardingAlgorithm implements PreciseShardingAlgorithm<Long> {

    //select * from course where cid = ? or cid in (?,?)
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        //实现 course_$->{cid%2+1)
        BigInteger cidValue = BigInteger.valueOf(cidValue);
        BigInteger resB = (cidValue.mod(new BigInteger("2"))).add(new BigInteger("1"));
        String key = logicTableName+"_"+resB;
        if(availableTargetNames.contains(key)){
            //couse_1, course_2
            return key;
        }    
    }
}

分表策略配置:

spring.shardingsphere.sharding.tables.course.table-strategy.standard.sharding-column=cid
spring.shardingsphere.sharding.tables.course.table-strategy.standard.precise-algorithm-class-name=com.kbp.shard.algorithem.MyPreciseTableShardingAlgorithm

5.3 分布式事务一致性

    @Test
    @Transactional(rollbackFor = Exception.class)
    @ShardingTransactionType(TransactionType.XA)
    public void addCourseTX(){
        for(int i = 0 ; i < 10 ; i ++){
            Course c = new Course();
            c.setCname("test");
            c.setUserId(Long.valueOf(""+(1000+i)));
            c.setCstatus("1");
            courseMapper.insert(c);
            if(i == 4){
                int a = 1/0;
            }
        }
    }

Sharding jdbc 可以通过@ShardingTransactionType(TransactionType.XA),加在方法上就可以;当抛出异常的时候,之前插入的数据全部回滚,避免部分插入

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值