【Sharding-JDBC简单学习】

Sharding-jdbc

基本概念

一、垂直分表:

垂直分表是一种数据库设计策略,其中一张表被拆分成多张表,每张表存储的是原始表的不同字段。这种拆分是基于列进行的,而不是行。
举个例子:典型的就是列表和详情,拿电商平台举例,用户查看商品列表的几率远远高于查看商品详情,这时可以将商品详情从商品表中拆分出去。

二、垂直分库

就是根据业务不同,将不同的表拆分到不同的数据库中(通常在设计环节进行,根据我的经验来看,在项目上线后不会轻易进行重新垂直分库的动作)
举个例子:以ERP系统为例,接受员工和供应商发票到付款环节耦合在一起,虽然发票会对应付款计划行,但是不应该将其放在一个数据库中,应该通过垂直分库,将发票的接收,验证,计税,匹配PO等步骤放在发票服务的数据库中,付款的数据库在付款的微服务中,既能让数据库压力变小,还能更符合微服务的划分。

三、水平分表

是指将一个大表按照数据量进行拆分,将同一张表中的不同行数据分离到不同的表中。这种方式主要用于应对数据量过大的情况,以便将数据分散到不同的数据库中,提高数据库的处理能力和查询效率
举个例子:仍然以ERP系统为例,对于大公司来说,财经的发票报销环节,会接收特别多的发票,发票明细行表数据动辄就是十几亿的数据,此时如果不进行分表的动作,就会导致单表查询的效率非常低

四、水平分库

以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中,每个数据库的表结构是一致的,可以同时进行分库分表,即先根据一定的规则进行分库,再根据水平分表规则,将数据存储到数据库的分片表
举个例子:一般在磁盘IO,数据库CPU达到性能瓶颈时,考虑进行分库

五、Sharding-JDBC

在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。
简单理解就是帮助程序员完成分库分表的任务,大大降低了程序员进行分库分表的开发难度,否则程序员需要自己实现在什么策略下进行分库,分到哪个库,应用什么样的策略生成SQL插入分片表。Sharding-JDBC只需简单的配置,即可轻易上手分库分表。

名词解释

逻辑表:
数据分片的逻辑表,对于水平拆分的数据库(表),同一类表的总称。例:订单数据根据主键尾数拆分为10张表,分别是t_order_0到t_order_9,他们的逻辑表名为t_order,实际在数据库中此表不存在。

绑定表:
指在任何场景下分片规则均一致的主表和子表。例:订单表和订单项表,均按照订单ID分片,则此两张表互为BindingTable关系。BindingTable关系的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。否则在主表中的数据会逐个查询子表,造成笛卡尔积关联。

分片键:
就是用于分片的数据库字段,是将数据库(表)水平拆分的关键字段。例:订单表订单ID分片尾数取模分片,则订单ID为分片字段。
SQL中如果无分片字段,将执行全路由,性能较差,支持多分片字段

执行过程

SQL解析
在这里插入图片描述

SQL路由:
根据上下文匹配的数据和表的分片策略,生成路由路径。对于携带分片键的sql可以分为单片路由和多片路由,还有范围路由,若是能根据分片键确定是哪张表,即单片路由,若是IN之类的,就是范围多片路由,如果不携带分片键,那么就是广播路由,即每个节点都要执行。

SQL改写:
就是将原本的SQL进行改写,方便后续操作
比如在进行排序查询时,sharding-jdbc会将排序字段一并查出,便于在合并结果时重新进行排序
在这里插入图片描述

水平分表实现

1、搭建Srping-Boot项目,添加如下配置

spring.application.name=shardingjdbc
server.port=8080
mybatis.type-aliases-package=com.zqlwudi.po
mybatis.configuration.map-underscore-to-camel-case=true
spring.main.allow-bean-definition-overriding=true

# 以下是分片规则配置
# 定义数据源
spring.shardingsphere.datasource.names=m1
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver‐class‐name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://127.0.0.1:3306/order_db?useUnicode=true
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=Aa123456

# 指定t_order表的数据分布情况,配置数据节点
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=m1.t_order_$->{1..2}

# 指定t_order表的主键生成策略为SNOWFLAKE,此时不需要在代码中生成主键
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE

# 指定t_order表的分片策略,分片策略包括分片键和分片算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
#分片算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2 + 1}

#打开sql输出日志
spring.shardingsphere.props.sql.show=true

logging.level.root=info
logging.level.org.springframework.web=info
logging.level.com.itheima.dbsharding=debug
logging.level.druid.sql=debug


2、引入Maven依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.5.5</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <!-- 不能使用druid-spring-boot-starter,会导致:Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required 和Mapper接口找不到异常 -->
        <!--        <dependency>-->
        <!--            <groupId>com.alibaba</groupId>-->
        <!--            <artifactId>druid-spring-boot-starter</artifactId>-->
        <!--            <version>1.2.8</version>-->
        <!--        </dependency>-->

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

3、测试代码

package com.example.shardingjdbc.dao;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

@Mapper
@Component
public interface OrderDao {

    @Insert("insert into t_order (price,user_id,status) values (#{price},#{userId},#{status})")
    void insertOrder(@Param("price")BigDecimal price,@Param("userId") Long userId,@Param("status") String status);
}
import com.example.shardingjdbc.ShardingjdbcApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.math.BigDecimal;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ShardingjdbcApplication.class})
public class OrderDaoTest {

    @Autowired
    OrderDao orderDao;

    @Test
    public void testInsert() {
        orderDao.insertOrder(new BigDecimal(12),1L,"yes");
    }
}

验证结果
在这里插入图片描述

水平分库

相比较水平分表配置文件做如下改动,
1、添加分库策略配置

# 分库策略
spring.shardingsphere.sharding.tables.t_order.databaseStrategy.inline.shardingColumn=user_id
spring.shardingsphere.sharding.tables.t_order.databaseStrategy.inline.algorithmExpression=m$->{user_id % 2+1 }

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.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://127.0.0.1:3306/order_db1?useUnicode=true
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=Aa123456

spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name =com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url=jdbc:mysql://127.0.0.1:3306/order_db2?useUnicode=true
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=Aa123456

3、配置数据节点时,添加分库

spring.shardingsphere.sharding.tables.t_order.actualDataNodes=m$->{1..2}.t_order_$->{1..2}

4、测试,即可在不同的数据库中看到插入的数据
在这里插入图片描述
在这里插入图片描述

  • 10
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值