Sharding-JDBC快速入门
-
需求说明
- 本章节使用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查询数据。
- 本章节使用Sharding-JDBC演示单库分表初体验,完成对订单表的水平分表,通过快速入门程序的开发,快速体验Sharding-JDBC的使用方法
-
环境搭建
-
环境说明
- 开发工具:IntelliJ IDEA
- 数据库:MySQL-8.0.16-winx64
- JDK:64位 jdk1.8.0
- 应用框架:spring-boot-2.2.0.RELEASE,MyBatis-3.5.3
- Sharding-JDBC:sharding-jdbc-spring-boot-starter-4.0.0-RC2
-
创建数据库
- 创建订单库order_db
CREATE DATABASE `order_db` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
- 创建订单库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;
-
引入maven依赖
- 引入 sharding-jdbc和SpringBoot整合的Jar包
<dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.0.0-RC2</version> </dependency>
- 引入 sharding-jdbc和SpringBoot整合的Jar包
-
-
编写sharding-jdbc配置
- 分片规则配置
- 分片规则配置是sharding-jdbc进行对分库分表操作的重要依据,配置内容包括:
- 数据源
- 主键生成策略
- 分片策略等
- 分片规则配置是sharding-jdbc进行对分库分表操作的重要依据,配置内容包括:
- 配置信息,见application.properties中配置
- 分片规则配置
# Mybatis 配置
mybatis.mapper-locations = classpath:mapping/*Dao.xml
mybatis.type-aliases-package = com.shair.domain
#sharding-jdbc分片规则配置
#数据源
spring.shardingsphere.datasource.names = m1
spring.shardingsphere.datasource.m1.type = com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.m1.driver-class-name = com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.jdbcUrl = jdbc:mysql://127.0.0.1:3306/order_db?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = root
# 指定t_order表的数据分布情况,配置数据节点 m1.t_order_1,m1.t_order_2
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
- 编写程序
# OrderDao
@Mapper
public interface OrderDao {
int insert(Order record);
}
# OrderDao.xml
<insert id="insert" parameterType="com.shair.domain.Order">
INSERT INTO t_order (price, user_id, status)
VALUES (#{price,jdbcType=DECIMAL}, #{userId,jdbcType=BIGINT}, #{status,jdbcType=VARCHAR})
</insert>
- 测试代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
@Autowired
private OrderDao orderDao;
@Test
public void testInsertOrder() {
for (int i = 0; i < 10; i++) {
Order order = new Order();
order.setPrice(new BigDecimal((i + 1) * 5));
order.setUserId(1L);
order.setStatus("SUCCESS");
orderDao.insert(order);
}
}
- 测试数据
- 执行 testInsertOrder
- 通过日志可以发现:
- order_id为奇数的被插入到 t_order_2表
- order_id为偶数的被插入到 t_order_1表
2019-10-27 16:06:34.035 [main] INFO ShardingSphere-SQL - Actual SQL: m1 ::: INSERT INTO t_order_1 (price, user_id, status, order_id)
VALUES (?, ?, ?, ?) ::: [20, 1, SUCCESS, 395246018112782336]
2019-10-27 16:06:34.046 [main] INFO ShardingSphere-SQL - Actual SQL: m1 ::: INSERT INTO t_order_2 (price, user_id, status, order_id)
VALUES (?, ?, ?, ?) ::: [25, 1, SUCCESS, 395246018154725377]
- 流程分析
- Sharding-JDBC在拿到用户要执行的sql后,执行以下步骤
- 解析sql,获取片键值,在本例中是order_id
- Sharding-JDBC通过规则配置 t_order_$->{order_id % 2 + 1},知道了当order_id为偶数时,应该往t_order_1表插数据,为奇数时,往t_order_2插数据
- 于是Sharding-JDBC根据order_id的值改写sql语句,改写后的SQL语句是真实所要执行的SQL语句
- 执行改写后的真实sql语句
- 将所有真正执行sql的结果进行汇总合并,返回
- Sharding-JDBC在拿到用户要执行的sql后,执行以下步骤