ShardingSphere分库分表----取模和按日期分表
shardingjdbc分库分表----取模和按时间分表每天多学一点点~话不多说,这就开始吧…文章目录shardingjdbc分库分表----取模和按时间分表1.前言2. 取模分库分表配置3. 分片策略简介4. 根据日期分库分表配置5.结语1.前言最近有个业务需要分库分表,遂研究了下sharing。网上列出了一些取模的分库分表实现,但是按照时间分库分表,或者二者结合的很少,遂在这里记录一下。shr
shardingjdbc分库分表----取模和按时间分表
每天多学一点点~
话不多说,这就开始吧…
1.前言
最近有个业务需要分库分表,遂研究了下sharing。网上列出了一些取模的分库分表实现,但是按照时间分库分表,或者二者结合的很少,遂在这里记录一下。
shrdingsphere官网 各位有兴趣的去官网看看,中文的。。。
-
JDBC
定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。 -
proxy
类似于mycat。定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前提供 MySQL 和 PostgreSQL 版本,它可以使用任何兼容 MySQL/PostgreSQL 协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat 等)操作数据,对 DBA 更加友好。 -
Sidecar
定位为 Kubernetes 的云原生数据库代理,以 Sidecar 的形式代理所有对数据库的访问。 通过无中心、零侵入的方案提供与数据库交互的的啮合层,即 Database Mesh,又可称数据库网格。好像还在规划中。
这里我选择了JDBC 方式。
2. 取模分库分表配置
- 引入依赖
简单的springboot工程
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!-- sharding apache最新孵化的版本 -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.1</version>
</dependency>
- 规则
以订单为例,用 user_id 进行取模 分库 , order_id 进行取模分表
boke_0 boke_1 两个库,每个库 t_order_0 t_order_1 两张表 ,共4张表
CREATE TABLE `t_order` (
`order_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单id(雪花算法)',
`user_id` int(20) NOT NULL COMMENT '用户id',
`address_id` bigint(20) NOT NULL COMMENT '地址id',
`status` char(1) DEFAULT NULL COMMENT '订单状态',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`order_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
- properties配置
#配置数据源 boke_1 boke_2
spring.shardingsphere.datasource.names=b0,b1
# boke_0 数据源配置
spring.shardingsphere.datasource.b0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.b0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.b0.jdbc-url=jdbc:mysql://localhost:3306/boke_0?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.b0.username=root
spring.shardingsphere.datasource.b0.password=root
# boke_1 数据源配置
spring.shardingsphere.datasource.b1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.b1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.b1.jdbc-url=jdbc:mysql://localhost:3306/boke_1?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.b1.username=root
spring.shardingsphere.datasource.b1.password=root
# 分库策略(水平) 以 user_id 取模 进行 分库
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=b$->{user_id % 2}
# 绑定表 t_order 与 t_order_item
spring.shardingsphere.sharding.binding-tables=t_order,t_order_item
# t_order 分表策略
# 节点 b0.t_order_0,b1.t_order_1,b0.t_order_0,b1.t_order_1
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=b$->{0..1}.t_order_$->{0..1}
# 分表 id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
# 分表策略 order_id 取模
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2}
# 使用SNOWFLAKE算法生成主键
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
# 雪花算法的workId 机器为标识 0-1024
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123
# t_order_item 分表策略
# 节点 b0.t_order_item_0,b0.t_order_item_1,b1.t_order_item_0,b1.t_order_item_1
spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=b$->{0..1}.t_order_item_$->{0..1}
# 分表策略 order_id 取模
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
# 分表策略 根据id取模,确定数据最终落在那个表中
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item_$->{order_id % 2}
# 使用SNOWFLAKE算法生成主键
spring.shardingsphere.sharding.tables.t_order_item.key-generator.column=order_item_id
spring.shardingsphere.sharding.tables.t_order_item.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order_item.key-generator.props.worker.id=123
# 广播表 address
spring.shardingsphere.sharding.broadcast-tables=t_address
这样配置好之后,其他就和springboot项目一样,直接用mybatis查询就可。
3. 分片策略简介
分片策略官网简介
包含分片键和分片算法,由于分片算法的独立性,将其独立抽离。真正可用于分片操作的是分片键 + 分片算法,也就是分片策略。目前提供 5 种分片策略。
-
标准分片策略
对应 StandardShardingStrategy。提供对 SQ L语句中的 =, >, <, >=, <=, IN 和 BETWEEN AND 的分片操作支持。 StandardShardingStrategy 只支持单分片键,提供 PreciseShardingAlgorithm 和 RangeShardingAlgorithm 两个分片算法。 PreciseShardingAlgorithm 是必选的,用于处理 = 和 IN 的分片。 RangeShardingAlgorithm 是可选的,用于处理 BETWEEN AND, >, <, >=, <=分片,如果不配置 RangeShardingAlgorithm,SQL 中的 BETWEEN AND 将按照全库路由处理。 -
复合分片策略
对应 ComplexShardingStrategy。复合分片策略。提供对 SQL 语句中的 =, >, <, >=, <=, IN 和 BETWEEN AND 的分片操作支持。 ComplexShardingStrategy 支持多分片键,由于多分片键之间的关系复杂,因此并未进行过多的封装,而是直接将分片键值组合以及分片操作符透传至分片算法,完全由应用开发者实现,提供最大的灵活度。 -
Hint分片策略
对应 HintShardingStrategy。通过 Hint 指定分片值而非从 SQL 中提取分片值的方式进行分片的策略。 -
不分片策略
对应 NoneShardingStrategy。不分片的策略。
4. 根据日期分库分表配置
-
规则
以订单为例,db 以 订单id 取模 分库, table 以 订单创建时间 分表
即 boke_0 boke_1 两个库,每个库中 t_order_2020_1 —t_order_2021_12 共24张表。 -
写两个类,实现 PreciseShardingAlgorithm 精确分片算法,一个用于db取模,一个用于table按月份分片。
DBShardingAlgorithm 用于 db 取模
/*
* @author :zjq
* @date :2020/11/9 10:44
* @description: TODO 数据表分表策略 TableShardingAlgorithm
* @version: V1.0
* @slogan: 天下风云出我辈,一入代码岁月催
*/
@Slf4j
public class DBShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
System.out.println("DB PreciseShardingAlgorithm ");
// 真实节点
availableTargetNames.stream().forEach((item) -> {
log.info("actual node db:{}", item);
});
log.info("logic table name:{},rout column:{}", shardingValue.getLogicTableName(), shardingValue.getColumnName());
//精确分片
log.info("column value:{}", shardingValue.getValue());
long orderId = shardingValue.getValue();
long db_index = orderId & (2 - 1);
for (String each : availableTargetNames) {
if (each.equals("b"+db_index)) {
return each;
}
}
throw new IllegalArgumentException();
}
}
TableShardingAlgorithm用于table按月份分片
/*
* @author :zjq
* @date :2020/11/9 10:44
* @description: TODO 数据表分表策略 TableShardingAlgorithm
* @version: V1.0
* @slogan: 天下风云出我辈,一入代码岁月催
*/
@Slf4j
public class TableShardingAlgorithm implements PreciseShardingAlgorithm<Date> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) {
System.out.println("table PreciseShardingAlgorithm ");
// 真实节点
availableTargetNames.stream().forEach((item) -> {
log.info("actual node table:{}", item);
});
log.info("logic table name:{},rout column:{}", shardingValue.getLogicTableName(), shardingValue.getColumnName());
//精确分片
log.info("column value:{}", shardingValue.getValue());
String tb_name = shardingValue.getLogicTableName() + "_";
// 根据当前日期 来 分库分表
Date date = shardingValue.getValue();
String year = String.format("%tY", date);
String mon =String.valueOf(Integer.parseInt(String.format("%tm", date))); // 去掉前缀0
String dat = String.format("%td", date);
// 选择表
tb_name = tb_name + year + "_" + mon;
System.out.println("tb_name:" + tb_name);
for (String each : availableTargetNames) {
System.out.println("t_order_:" + each);
if (each.equals(tb_name)) {
return each;
}
}
throw new IllegalArgumentException();
}
}
- properties 配置
db 以 订单id 取模 table 以 订单创建时间 分库
#配置数据源 boke_1 boke_2
spring.shardingsphere.datasource.names=b0,b1
spring.shardingsphere.sharding.default-data-source-name=b0
# boke_0 数据源配置
spring.shardingsphere.datasource.b0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.b0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.b0.jdbc-url=jdbc:mysql://localhost:3306/boke_0?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&relaxAutoCommit=true&zeroDateTimeBehavior=convertToNull
spring.shardingsphere.datasource.b0.username=root
spring.shardingsphere.datasource.b0.password=root
# boke_1 数据源配置
spring.shardingsphere.datasource.b1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.b1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.b1.jdbc-url=jdbc:mysql://localhost:3306/boke_1?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&relaxAutoCommit=true&zeroDateTimeBehavior=convertToNull
spring.shardingsphere.datasource.b1.username=root
spring.shardingsphere.datasource.b1.password=root
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=b$->{0..1}.t_order_$->{2020..2021}_$->{1..12}
# 自定义 分片算法
# 分库分片健 database-strategy 数据库策略
spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.sharding-column=order_id
# 自定义 分片 策略
spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.precise-algorithm-class-name=com.boke.order.sharding.time.DBShardingAlgorithm
# table-strategy 表 的 策略
spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.sharding-column=create_time
spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.precise-algorithm-class-name=com.boke.order.sharding.time.TableShardingAlgorithm
# 使用SNOWFLAKE算法生成主键
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
# 雪花算法的workId 机器为标识 0-1024
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123
这样就大功告成,经过测试,插入,分页查询,范围,精确查询,事务都是ok,但是因为选择了精确分片算法 ,分页和范围查询,会路由到2个db的24张表上,会有效率问题,所以要好好取舍,再研究研究~
5.结语
世上无难事,只怕有心人,每天积累一点点,fighting!!!
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)