当前位置: 首页 > news >正文

Sharding-jdbc基本使用步骤以及执行原理剖析

一、基本使用步骤

1、需求说明

使用sharding-jdbc完成对订单表的水平分表,通过快速入门的开发,了解sharding-jdbc使用方法

人工创建两张表,t_order_1和t_order_2,这两张表是订单表拆分后的表,通过sharding-jdbc向订单表插入数据,按照一定的分片规则,主键为偶数的进入t_order_1,另一部分数据进入t_order_2,通过sharding-jdbc查询数据,根据SQL语句的内容从t_order_1或t_order_2查询数据。

2、环境搭建

创建订单数据库order_db

CREATE DATABASE order_db CHARACTER SET 'utf8' COLLATE 'utf8_general_ci'; 1

在order_db中创建t_order_1、t_order_2表

DROP TABLE IF EXISTS t_order_1;CREATE TABLE t_order_1 (`order_id` BIGINT ( 20 ) NOT NULL COMMENT '订单id',`price` DECIMAL ( 10, 2 ) NOT NULL COMMENT '订单价格',`user_id` BIGINT ( 20 ) NOT NULL COMMENT '下单用户id',`status` VARCHAR ( 50 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '订单状态',PRIMARY KEY ( `order_id` ) USING BTREE 
) ENGINE = INNODB CHARACTER 
SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;DROP TABLE IF EXISTS t_order_2;
CREATE TABLE t_order_2 (`order_id` BIGINT ( 20 ) NOT NULL COMMENT '订单id',`price` DECIMAL ( 10, 2 ) NOT NULL COMMENT '订单价格',`user_id` BIGINT ( 20 ) NOT NULL COMMENT '下单用户id',`status` VARCHAR ( 50 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '订单状态',PRIMARY KEY ( `order_id` ) USING BTREE 
) ENGINE = INNODB CHARACTER 
SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

创建工程,引入坐标

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.0.RELEASE</version><relativePath/><!-- lookup parent from repository --></parent><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.0</version><scope>provided</scope></dependency><!-- MySQL Connector/J for database connectivity --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.16</version></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.0.0-RC1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>2.1.0.RELEASE</version><scope>test</scope></dependency></dependencies>

3、配置文件

在application.properties中进行如下配置:(尤其关注sharding-jdbc的配置,我已经将每条配置都解释的很详细了)

# 端口号
server.port=56000
# 应用名称
spring.application.name=sharding_quick
# 表示spring中发现的bean会覆盖之前相同名称的bean
spring.main.allow-bean-definition-overriding=true
# 该配置项,将数据库中带有下划线的字段名称映射成驼峰命名
mybatis.configuration.map-underscore-to-camel-case=true# 以下配置为sharding-jdbc分片规则配置# 1.定义数据源
#定义数据源名称
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://localhost:3306/order_db?useUnicode=true
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456# 2.指定订单表的数据分布情况,配置数据节点 下面的't_order'是逻辑表,这个名字可以自己起一个   m1.t_order_$->{1..2}表示利用行表达式来实现动态表
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=m1.t_order_$->{1..2}# 3.指定t_order表中的主键生成策略#表示告诉sharding-jdbc数据库表中的那一个字段进行主键生成
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
#指定具体的主键生成策略  -> 雪花算法
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE# 4.指定t_order表的分片策略(分片策略=分片键+分片算法):主键为偶数路由到t_order_1中,否则插入到t_order_2中#告诉分片键是哪一个字段
spring.shardingsphere.sharding.tables.t_order.tableStrategy.inline.shardingColumn=order_id
#确定采取什么样的分片算法
spring.shardingsphere.sharding.tables.t_order.tableStrategy.inline.algorithmExpression=t_order_$->{order_id % 2 + 1}# 5.指定,打开sharding-jdbc提供的sql输出日志配置
spring.shardingsphere.props.sql.show=true# 日志配置
logging.level.root=info
logging.level.org.springframework=info
logging.level.com.lcc=debug
logging.level.druid.sql=debug

4、完成新增订单功能

创建订单实体

import lombok.Data;import java.math.BigDecimal;@Data
public class Order {private Long orderId;private BigDecimal price;private Long userId;private String status;}

创建mapper接口

import com.lcc.domain.Order;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;import java.util.List;
import java.util.Map;@Mapper
public interface OrderMapper {/*** 这里t_order就是sharding-jdbc中的逻辑表*/@Insert("insert into t_order(price,user_id,status) values(#{price},#{userId},#{status})")public int insertOrder(Order order);
}

在测试类中进行测试 

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;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;@RunWith(SpringRunner.class)
@SpringBootTest
public class ShardingQuickApplicationTests {@Autowiredprivate OrderMapper orderMapper;@Testpublic void insertTest(){for (int i = 0; i < 10; i++) {Order order = new Order();order.setStatus("success_"+i);order.setUserId(1L);order.setPrice(new BigDecimal((i+1)*5));int result = orderMapper.insertOrder(order);System.out.println(result);}}
}

我们查看数据库发现,已经根据我们的分片策略进行不同orderId的落盘

5、完成查询订单功能

在mapper中新增selectListByOrderIds方法

@Mapper
public interface OrderMapper {/*** 这里t_order就是sharding-jdbc中的逻辑表*/@Insert("insert into t_order(price,user_id,status) values(#{price},#{userId},#{status})")public int insertOrder(Order order);@Select("<script>" +"select " +"* " +"from t_order t " +"where t.order_id in " +"<foreach collection='orderIds' item='id' open='(' separator=',' close=')'>" +"#{id}" +"</foreach>" +"</script>")public List<Map> selectListByOrderIds(@Param("orderIds") List<Long> orderIds);
}

在测试类中新增selectTest方法

@RunWith(SpringRunner.class)
@SpringBootTest
public class ShardingQuickApplicationTests {@Autowiredprivate OrderMapper orderMapper;@Testpublic void insertTest(){for (int i = 0; i < 10; i++) {Order order = new Order();order.setStatus("success_"+i);order.setUserId(1L);order.setPrice(new BigDecimal((i+1)*5));int result = orderMapper.insertOrder(order);System.out.println(result);}}@Testpublic void selectTest(){List<Long> orderIds = new ArrayList<>();orderIds.add(1074443883426873344L);orderIds.add(1074443883489787905L);List<Map> maps = orderMapper.selectListByOrderIds(orderIds);for (Map map : maps) {System.out.println(map);}}
}

二、sharding-jdbc执行原理剖析

我们先来看一张官网上给出的大致执行流程图

我们再调整一下,SQL路由应该在SQL改写的前面,如下图

1、SQL解析

首先,使用内置的 SQL 解析器对原始 SQL 进行解析,识别出查询中的表名、条件、分组、排序等信息。这一步骤确保了后续操作能够正确地针对分片后的数据库和表进行。

2、SQL路由

根据分片策略和解析后的 SQL 信息,确定需要访问的具体分片。对于涉及多表关联查询的情况,还会检查是否为绑定表(Binding Table),以优化查询路径。

3、SQL改写

基于路由结果,对原始 SQL 进行必要的改写,例如替换表名为实际的分片表名,调整 LIMIT 子句等,以适应分片后的环境。

4、SQL执行

在完成 SQL 改写后,Sharding-JDBC 会为每个目标分片生成独立的执行计划。这意味着每个分片上的查询都会被视为单独的 SQL 操作,并行执行。

5、结果归并

由于同一个查询可能涉及到多个分片的数据,因此 Sharding-JDBC 需要负责将从各个分片获取的结果集合并成最终的结果返回给应用程序。这个过程包括:

  • 数据去重:对于某些聚合查询或 DISTINCT 关键字的使用,需要去除重复记录。

  • 排序和分页:如果原始查询包含 ORDER BY 或 LIMIT 等子句,则需要对合并后的结果重新排序或截取指定数量的记录。

http://www.lryc.cn/news/502892.html

相关文章:

  • mysql重置root密码(适用于5.7和8.0)
  • Linux下SVN客户端保存账号密码
  • centos7.9 gcc升级到11.2.1
  • HQChart使用教程30-K线图如何对接第3方数据42-DRAWTEXTREL,DRAWTEXTABS数据结构
  • 数仓高频面试 | 数仓为什么要分层
  • 网络安全—部署CA证书服务器
  • MATLAB中circshift函数的原理分析——psf2otf函数的核心
  • js 惰性函数
  • 智能技术引领未来:自动图像标注的创新应用与发展
  • 深入探索数据库世界:SQLite、Redis、MySQL 与数据库设计范式
  • 内网是如何访问到互联网的(华为源NAT)
  • 华为无线AC、AP模式与上线解析(Huawei Wireless AC, AP Mode and Online Analysis)
  • 奖励模池化
  • 基于django协同过滤的音乐推荐系统的设计与实现
  • Tiptap,: 富文本编辑器入门与案例分析
  • 使用Linux的logrotate工具切割日志:Tomcat、NGINX(journal文件清理)
  • CSS系列(11)-- 滤镜与混合模式详解
  • linux - 存储管理
  • 在 Kibana 中为 Vega Sankey 可视化添加过滤功能
  • styled-components 库的用法介绍和实践总结
  • SSE(Server-Sent Events)主动推送消息
  • pandas.core.frame.DataFrame怎么进行对象内容的读写
  • 短作业优先调度算法
  • SpringBoot 应用并发处理请求数的深入解析
  • MetaGPT中的教程助手:TutorialAssistant
  • 介绍一款docker ui 管理工具
  • 0022 基于SpringBoot的婚纱摄影线上预约系统的设计与实现
  • uni-app在image上绘制点位并回显
  • Comparator.comparing 排序注意
  • PPO系列3 - PPO原理