1. ShardingJDBC实际使用01
1. Mysql数据库架构演变历史
单机
1. 请求量⼤查询慢
2. 单机故障导致业务不可⽤
主从
1. 数据库主从同步,从库可以⽔平扩展,满⾜更⼤读需求
2. 但单服务器TPS,内存,IO都是有限的
双主
1. ⽤户量级上来后,写请求越来越多
2. ⼀个Master是不能解决问题的,添加多了个主节点进⾏写
3. 多个主节点数据要保存⼀致性,写操作需要2个master之间同步更加复杂
分库和分表
数据库优化方案
1. 在数据量及访问压⼒不是特别⼤的情况,⾸先考虑缓存、读写分离、索引技术等⽅案。
2. 如果数据量极⼤,且业务持续增⻓快,再考虑分库分表⽅案
2. 进Mysql数据库分库分表后带来的优点
分库分表解决的问题
1. 解决数据库本身瓶颈
连接数: 连接数过多时,就会出现‘too many connections’的错误,访问量太⼤或者数据库设置的最⼤连接数太⼩的原因。
Mysql默认的最⼤连接数为100.可以修改,⽽mysql服务允许的最⼤连接数为16384。
数据库分表可以解决单表海量数据的查询性能问题。
数据库分库可以解决单台数据库的并发访问压⼒问题。
2. 解决系统本身IO、CPU瓶颈
磁盘读写IO瓶颈,热点数据太多,尽管使⽤了数据库本身缓存,但是依旧有⼤量IO,导致sql执⾏速度慢。
⽹络IO瓶颈,请求的数据太多,数据传输⼤,⽹络带宽不够,链路响应时间变⻓。
CPU瓶颈,尤其在基础数据量⼤单机复杂SQL计算,SQL语句执⾏占⽤CPU使⽤率⾼,也有扫描⾏数⼤、锁冲突、锁等待等原因。
3. Mysql数据库分库分表后的六⼤问题
问题⼀:跨节点数据库Join关联查询
1. 数据库切分前,多表关联查询,可以通过sql join进⾏实现。
2. 分库分表后,数据可能分布在不同的节点上,sql join带来的问题就⽐较麻烦。
问题⼆:分库操作带来的分布式事务问题
1. 操作内容同时分布在不同库中,不可避免会带来跨库事务问题,即分布式事务。
问题三:执⾏的SQL排序、翻⻚、函数计算问题
1. 分库后,数据分布再不同的节点上, 跨节点多库进⾏查询时,会出现limit分⻚、order by排序等问题。
2. ⽽且当排序字段⾮分⽚字段时,更加复杂了,要在不同的分⽚节点中将数据进⾏排序并返回,然后将不同分⽚返回的结果集进⾏汇总和再次排序(也会带来更多的CPU/IO资源损耗)
问题四:数据库全局主键重复问题
1. 常规表的id是使⽤⾃增id进⾏实现,分库分表后,由于表中数据同时存在不同数据库中,如果⽤⾃增id,则会出现冲突问题
问题五:容量规划,分库分表后⼆次扩容问题
1. 业务发展快,初次分库分表后,满⾜不了数据存储,导致需要多次扩容
问题六:分库分表技术选型问题
1. 市场分库分表中间件相对较多,框架各有各的优势与短板,应该如何选择?
4. 海量数据处理之Mysql数据库垂直分表案例
垂直分表
1. 就是“⼤表拆⼩表”,基于列字段进⾏.
2. 拆分原则⼀般是表中的字段较多,将不常⽤的或者数据较⼤⻓度较⻓的拆分到“扩展表 如text类型字段.
3. 访问频次低、字段⼤的商品描述信息单独存放在⼀张表中,访问频次较⾼的商品基本信息单独放在⼀张表中.
4. 业务经常组合查询的列放在⼀张表中.
需求:
商品表字段太多,每个字段访问频次不⼀样,浪费了IO资源,需要进⾏优化。在商品检索页面,是只需要查询该商品的部分字段,商品的详细信息应该是点击详情时查看.
例如
1. 商品详情⼀般是拆分主表和附表
拆分前:
CREATE TABLE `product` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(524) DEFAULT NULL COMMENT '视频标题',
`cover_img` varchar(524) DEFAULT NULL COMMENT'封⾯图',
`price` int(11) DEFAULT NULL COMMENT '价格,分',
`total` int(10) DEFAULT '0' COMMENT '总库存',
`left_num` int(10) DEFAULT '0' COMMENT '剩余',
`learn_base` text COMMENT '课前须知,学习基础',
`learn_result` text COMMENT '达到⽔平',
`summary` varchar(1026) DEFAULT NULL COMMENT '概 述',
`detail` text COMMENT '视频商品详情',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT
CHARSET=utf8;
拆分后:
CREATE TABLE `product` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(524) DEFAULT NULL COMMENT '视频标题',
`cover_img` varchar(524) DEFAULT NULL COMMENT'封⾯图',
`price` int(11) DEFAULT NULL COMMENT '价格,分',
`total` int(10) DEFAULT '0' COMMENT '总库存',
`left_num` int(10) DEFAULT '0' COMMENT '剩余',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT
CHARSET=utf8;
CREATE TABLE `product_detail` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`product_id` int(11) DEFAULT NULL COMMENT '产品主键',
`learn_base` text COMMENT '课前须知,学习基础',
`learn_result` text COMMENT '达到⽔平',
`summary` varchar(1026) DEFAULT NULL COMMENT '概 述',
`detail` text COMMENT '视频商品详情',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT
CHARSET=utf8;
垂直分库
需求
C端项⽬⾥⾯,单个数据库的CPU、内存⻓期处于90%+的利⽤率,数据库连接经常不够,需要进⾏优化
分库
1. 垂直分库针对的是⼀个系统中的不同业务进⾏拆分, 数据库的连接资源⽐较宝贵且单机处理能⼒也有限。
2. 没拆分之前全部都是落到单⼀的库上的,单库处理能⼒成为瓶颈,还有磁盘空间,内存,tps等限制。
3. 拆分之后,避免不同库竞争同⼀个物理机的CPU、内存、⽹络IO、磁盘,所以在⾼并发场景下,垂直分库⼀定程度上能够突破IO、连接数及单机硬件资源的瓶颈。
4. 垂直分库可以更好解决业务层⾯的耦合,业务清晰,且⽅便管理和维护。
5. ⼀般从单体项⽬升级改造为微服务项⽬,就是垂直分库
问题
垂直分库分表可以提⾼并发,但是依然没有解决单表数据量过⼤的问题
4.1 Mysql数据库⽔平分表
需求
当⼀张表的数据达到⼏千万时,查询⼀次所花的时间⻓。
拆表
1. 垂直分表:表结构拆分
2. ⽔平分表:数据拆分
水平拆分
1. 把⼀个表的数据分到⼀个数据库的多张表中,每个表只有这个表的部分数据。
2. 核⼼是把⼀个⼤表,分割N个⼩表,每个表的结构是⼀样的,数据不⼀样,全部表的数据合起来就是全部数据。
3. 针对数据量巨⼤的单张表(⽐如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表⾥⾯去。
4. 但是这些表还是在同⼀个库中,所以单数据库操作还是有IO瓶颈,主要是解决单表数据量过⼤的问题。
5. 减少锁表时间,没分表前,如果是DDL(create/alter/add等)语句,当需要添加⼀列的时候mysql会锁表,期间所有的读写操作只能等待
4.2 Mysql数据库⽔平分库
需求
⾼并发的项⽬中,⽔平分表后依旧在单个库上⾯,1个数据库资源瓶颈 CPU/内存/带宽等限制导致响应慢。
⽔平分库
1. 把同个表的数据按照⼀定规则分到不同的数据库中,数据库在不同的服务器上。
2. ⽔平分库是把不同表拆到不同数据库中,它是对数据⾏的拆分,不影响表结构。
3. 每个库的结构都⼀样,但每个库的数据都不⼀样,没有交集,所有库的并集就是全量数据。
4. ⽔平分库的粒度,⽐⽔平分表更⼤
4.3 Mysql数据库分库分表总结
技术负责⼈前瞻性思维
1. 需要提前考虑系统⼀年到两年左右的业务增⻓情况
2. 对数据库服务器的QPS、连接数、容量等做合理评估和规划
3. “分库分表”是宜早不宜迟
4. 常规开发⾥⾯单表建议1千万内,推荐是百万级别单表存储,常规sql和索引优化先⾏,然后结合缓存+异步+nosql+mq
5. ⽔平分库分表常⻅策略
5.1 range
⽅案⼀:⾃增id,根据ID范围进⾏分表(左闭右开)
1. 规则案例
1~1,000,000 是 table_1
1,000,000 ~2,000,000 是 table_2
2,000,000~3,000,000 是 table_3
......
2. 优点
id是⾃增⻓,可以⽆限增⻓
扩容不⽤迁移数据,容易理解和维护
3. 缺点
⼤部分读和写都访会问新的数据,有IO瓶颈,整体资源利⽤率低
数据倾斜严重,热点数据过于集中,部分节点有瓶颈
注意:Range范围分库分表,有热点数据问题
Range更多是⽔平分表
1. 数字
⾃增id范围
2. 时间
年、⽉、⽇范围
⽐如按照⽉份⽣成 库或表 itfnew_log_2022_01,itfnew_log_2022_02,itfnew_log_2022_03
3. 空间
地理位置:省份、区域(华东、华北、华南)
⽐如按照 省份 ⽣成 库或表,例如阿里云,七牛云等云服务
基于Range范围分库分表业务场景
1. 微博发送记录、微信消息记录、⽇志记录,id增⻓/时间分区
2. ⽹站签到等活动流⽔数据时间分区最好。
3. ⼤区划分(⼀⼆线城市和五六线城市活跃度不⼀样,如果能避免热点问题,即可选择)
saas业务⽔平分库(华东、华南、华北等)
5.2 Hash取模
hash取模(Hash分库分表是最普遍的⽅案)
为啥不直接取模,如果取模的字段不是整数型要先hash,统⼀规则就⾏
案例
1. ⽤户ID是整数型的,要分2库,每个库表数量4表,⼀共8张表
2. ⽤户ID取模后,值是0到7的要平均分配到每张表
A库ID = userId % 库数量 2
表ID = userId / 库数量 2 % 表数量4
优点
1. 保证数据较均匀的分散落在不同的库、表中,可以有效的避免热点数据集中问题
缺点
2. 扩容不是很⽅便,需要数据迁移
6. 中间件介绍-ShardingSphere
常⻅分库分表中间件
1. Cobar(已经被淘汰没使⽤了)
2. TDDL
淘宝根据⾃⼰的业务特点开发了 TDDL,基于JDBC规范,没有server,以client-jar的形式存在,引⼊项⽬即可使⽤。开源功能⽐较少,阿⾥内部使⽤为主
3. Mycat
Java语⾔编写的MySQL数据库⽹络协议的开源中间件,前身 Cobar。
遵守Mysql原⽣协议,跨语⾔,跨平台,跨数据库的通⽤中间件代理。
是基于 Proxy,它复写了 MySQL 协议,将 Mycat Server伪装成⼀个 MySQL 数据库。
和ShardingShere下的Sharding-Proxy作⽤类似,需要单独部署
4. ShardingSphere 下的Sharding-JDBC
地址:https://shardingsphere.apache.org/
Apache ShardingSphere 是⼀套开源的分布式数据库中间件解决⽅案组成的⽣态圈,由 Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar 3个独⽴产品组合。
Sharding-JDBC:
基于jdbc驱动,不⽤额外的proxy,⽀持任意实现 JDBC规范的数据库。
使⽤客户端直连数据库,以 jar 包形式提供服务,⽆需额外部署和依赖。
可理解为加强版的 JDBC 驱动,兼容 JDBC 和各类 ORM框架。
Mycat和ShardingJdbc区别
1. 两者设计理念相同,主流程都是SQL解析-->SQL路由-->SQL改写-->结果归并
2. sharding-jdbc
基于jdbc驱动,不⽤额外的proxy,在本地应⽤层重写Jdbc原⽣的⽅法,实现数据库分⽚形式
是基于 JDBC 接⼝的扩展,是以 jar 包的形式提供轻量级服务的,性能⾼
代码有侵⼊性.
3. Mycat
基于 Proxy,它复写了 MySQL 协议,将 Mycat Server伪装成⼀个 MySQL 数据库
客户端所有的jdbc请求都必须要先交给MyCat,再有MyCat转发到具体的真实服务器.
缺点是效率偏低,中间包装了⼀层.
代码⽆侵⼊性.
6.1 常⻅概念术语
数据节点Node
1. 数据分⽚的最⼩单元,由数据源名称和数据表组成.
⽐如:ds_0.product_order_0
真实表
1. 在分⽚的数据库中真实存在的物理表
⽐如订单表 product_order_0、product_order_1、product_order_2
逻辑表
1. ⽔平拆分的数据库(表)的相同逻辑和数据结构表的总称
⽐如订单表 product_order_0、product_order_1、product_order_2,逻辑表就是product_order
绑定表
1. 指分⽚规则⼀致的主表和⼦表
⽐如product_order表和product_order_item表,均按照order_id分⽚,则此两张表互为绑定表关系.
绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将⼤⼤提升.
⼴播表
1. 指所有的分⽚数据源中都存在的表,表结构和表中的数据在每个数据库中均完全⼀致.
2. 适⽤于数据量不⼤且需要与海量数据的表进⾏关联查询的场景
例如:字典表、配置表
6.2 分库分表和Sharding-Jdbc常⻅分⽚算法
数据库表分⽚(⽔平库、表)
1. 包含分⽚键和分⽚策略
分⽚键 (PartitionKey)
1. ⽤于分⽚的数据库字段,是将数据库(表)⽔平拆分的关键字段。
2. ⽐如prouduct_order订单表,根据订单号 out_trade_no做哈希取模,则out_trade_no是分⽚键。
3. 除了对单分⽚字段的⽀持,ShardingSphere也⽀持根据多个字段进⾏分⽚。
分⽚策略
1. ⾏表达式分⽚策略 InlineShardingStrategy
只⽀持【单分⽚键】使⽤Groovy的表达式,提供对SQL语句中的 =和IN 的分⽚操作⽀持
可以通过简单的配置使⽤,⽆需⾃定义分⽚算法,从⽽避免繁琐的Java代码开发。
prouduct_order_$->{user_id % 8}` 表示订单表根据user_id模8,⽽分成8张表,表名称为`prouduct_order_0`到`prouduct_order_7
2. 标准分⽚策略StandardShardingStrategy
只⽀持【单分⽚键】,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分⽚算法。
PreciseShardingAlgorithm 精准分⽚ 是必选的,⽤于处理=和IN的分⽚。
RangeShardingAlgorithm 范围分配 是可选的,⽤于处理BETWEEN AND分⽚。
如果不配置RangeShardingAlgorithm,如果SQL中⽤了BETWEEN AND语法,则将按照全库路由处理,性能下降
3. 复合分⽚策略ComplexShardingStrategy
⽀持【多分⽚键】,多分⽚键之间的关系复杂,由开发者⾃⼰实现,提供最⼤的灵活度。
提供对SQL语句中的=, IN和BETWEEN AND的分⽚操作支持。
4. Hint分⽚策略HintShardingStrategy
这种分⽚策略⽆需配置分⽚健,分⽚健值也不再从 SQL中解析,外部⼿动指定分⽚健或分⽚库,让 SQL在指定的分库、分表中执⾏。
⽤于处理使⽤Hint⾏分⽚的场景,通过Hint⽽⾮SQL解析的⽅式分⽚的策略。
Hint策略会绕过SQL解析的,对于这些⽐较复杂的需要分⽚的查询,Hint分⽚策略性能可能会更好。
7. 代码实战
技术栈: SpringBoot2.5+MybatisPlus+Sharding-Jdbc
新建maven项⽬
<?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.dss.sharding</groupId>
<artifactId>nwgame</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.boot.version>2.5.5</spring.boot.version>
<mybatisplus.boot.starter.version>3.4.0</mybatisplus.boot.starter.version>
<lombok.version>1.18.16</lombok.version>
<sharding-jdbc.version>4.1.1</sharding-jdbc.version>
<junit.version>4.12</junit.version>
<druid.version>1.1.16</druid.version>
<skipTests>true</skipTests>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.boot.starter.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>${sharding-jdbc.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
数据库新建,两个库,并且每个库各两张表
库1:
DB: dss_shop_order_0
Table: product_order_0, product_order_1
库2:
DB: dss_shop_order_1
Table: product_order_0,product_order_1
CREATE TABLE `product_order_0` (
`id` bigint NOT NULL AUTO_INCREMENT,
`out_trade_no` varchar(64) DEFAULT NULL COMMENT '订单唯⼀标识',
`state` varchar(11) DEFAULT NULL COMMENT 'NEW 未⽀付订单,PAY已经⽀付订单,CANCEL超时取消订单',
`create_time` datetime DEFAULT NULL COMMENT '订单⽣成时间',
`pay_amount` decimal(16,2) DEFAULT NULL COMMENT '订单实际⽀付价格',
`nickname` varchar(64) DEFAULT NULL COMMENT '昵称',
`user_id` bigint DEFAULT NULL COMMENT '⽤户id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_bin;
CREATE TABLE `product_order_1` (
`id` bigint NOT NULL AUTO_INCREMENT,
`out_trade_no` varchar(64) DEFAULT NULL COMMENT '订单唯⼀标识',
`state` varchar(11) DEFAULT NULL COMMENT 'NEW 未⽀付订单,PAY已经⽀付订单,CANCEL超时取消订单',
`create_time` datetime DEFAULT NULL COMMENT '订单⽣成时间',
`pay_amount` decimal(16,2) DEFAULT NULL COMMENT '订单实际⽀付价格',
`nickname` varchar(64) DEFAULT NULL COMMENT '昵称',
`user_id` bigint DEFAULT NULL COMMENT '⽤户id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_bin;
package com.dss.sharding.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
@Data
@TableName("product_order")
@EqualsAndHashCode(callSuper = false)
public class ProductOrderDO {
/**
* 方式一: 使用work.id的方式 + mybatis-plus自己实现的雪花算法
*/
//@TableId(value = "id",type = IdType.AUTO) //使用默认的自增
//@TableId(value = "id",type = IdType.ASSIGN_ID) //使用默认的雪花算法生成id
private Long id;
private String outTradeNo;
private String state;
private Date createTime;
private Double payAmount;
private String nickname;
private Long userId;
}
package com.dss.sharding.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dss.sharding.model.ProductOrderDO;
public interface ProductOrderMapper extends BaseMapper<ProductOrderDO> {
}
spring.application.name=dss-sharding-jdbc
server.port=8080
# 打印执行的数据库以及语句
spring.shardingsphere.props.sql.show=true
# 数据源 db0
spring.shardingsphere.datasource.names=ds0,ds1
# 第一个数据库
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://127.0.0.1:3306/dss_shop_order_0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=root
# 第二个数据库
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://127.0.0.1:3306/dss_shop_order_1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=root
#配置workId
spring.shardingsphere.sharding.tables.product_order.key-generator.props.worker.id=1
#id生成策略
spring.shardingsphere.sharding.tables.product_order.key-generator.column=id
spring.shardingsphere.sharding.tables.product_order.key-generator.type=SNOWFLAKE
# 指定product_order表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},
# 但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...}
# product_order: 逻辑表名
# 水平分库会解析成:ds0.product_order_0,ds0.product_order_1
spring.shardingsphere.sharding.tables.product_order.actual-data-nodes=ds0.product_order_$->{0..1}
# 指定product_order表的分片策略,分片策略包括【分片键和分片算法】
spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.algorithm-expression=product_order_$->{user_id % 2}
package dss.nq.db;
import java.util.Date;
import java.util.UUID;
import com.dss.sharding.Application;
import com.dss.sharding.mapper.ProductOrderMapper;
import com.dss.sharding.model.ProductOrderDO;
import lombok.extern.slf4j.Slf4j;
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;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@Slf4j
public class ShardingTest {
@Autowired
private ProductOrderMapper productOrderMapper;
@Test
public void testSaveProductOrder(){
for(int i=0; i<10;i++){
ProductOrderDO productOrderDO = new ProductOrderDO();
productOrderDO.setCreateTime(new Date());
productOrderDO.setNickname("sharding_test_i="+1);
productOrderDO.setOutTradeNo(UUID.randomUUID().toString().substring(0,32));
productOrderDO.setPayAmount(100.00);
productOrderDO.setState("PAY");
//user_id是分片键
productOrderDO.setUserId(Long.valueOf(i+""));
productOrderMapper.insert(productOrderDO);
}
}
}
雪花算法:
方式一: 在配置文件中配置work.id + @TableId(value = "id",type = IdType.ASSIGN_ID)
方式二: 注释掉bean中的@TableId,并在配置文件中开启如下配置:
spring.shardingsphere.sharding.tables.product_order.key-generator.column=id
spring.shardingsphere.sharding.tables.product_order.key-generator.type=SNOWFLAKE