Spring Boot中整合Sharding-JDBC单库分表示例

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

在我《Spring Cloud微服务-全栈技术与案例解析》书中都是通过XML方式配置。

今天给大家演示的是单库中分表的操作,如果用XML方式配置,那么就是下面的配置:


<!-- 数据源 -->
<bean id="ds_0" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" primary="true">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/ds_0?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>


<!-- algorithm-class="com.fangjia.sharding.UserSingleKeyTableShardingAlgorithm" -->
<!-- user_0,user_1,user_2,user_3 -->
<rdb:strategy id="userTableStrategy" sharding-columns="id" algorithm-expression="user_${id.longValue() % 4}"/>

<rdb:data-source id="dataSource">
<rdb:sharding-rule data-sources="ds_0">
<rdb:table-rules>
<rdb:table-rule logic-table="user" actual-tables="user_${0..3}" table-strategy="userTableStrategy"/>
</rdb:table-rules>
<rdb:default-database-strategy sharding-columns="none" algorithm-class="com.dangdang.ddframe.rdb.sharding.api.strategy.database.NoneDatabaseShardingAlgorithm"/>
</rdb:sharding-rule>
</rdb:data-source>

我们将user表分成了4个,分别是user_0,user_1,user_2,user_3,通过id取模的方式决定数据落在哪张表上面。

如果用Spring Boot方式配置自然就简单多了,如下:


sharding.jdbc.datasource.names=ds_master
# 数据源
sharding.jdbc.datasource.ds_master.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.ds_master.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds_master.url=jdbc:mysql://localhost:3306/ds_0?characterEncoding=utf-8
sharding.jdbc.datasource.ds_master.username=root
sharding.jdbc.datasource.ds_master.password=123456
# 分表配置
sharding.jdbc.config.sharding.tables.user.actual-data-nodes=ds_master.user_${0..3}
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.sharding-column=id
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.algorithm-expression=user_${id.longValue() % 4}
●  actual-data-nodes:真实数据节点,由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持inline表达式。
●  table-strategy.inline.sharding-column:分片字段配置

● table-strategy.inline.algorithm-expression:分片算法表达式

自定义分片算法

在1.x版本中,单分片算法是通过实现SingleKeyTableShardingAlgorithm,示例代码如下:


import java.util.Collection;
import java.util.LinkedHashSet;

import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm;
import com.google.common.collect.Range;

public class UserSingleKeyTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> {

public String doEqualSharding(Collection<String> availableTargetNames, ShardingValue<Long> shardingValue) {
for (String each : availableTargetNames) {
System.out.println(each+"\t"+shardingValue.getValue()+"\t"+shardingValue.getValue() % 4 );
if (each.endsWith(shardingValue.getValue() % 4 + "")) {
return each;
}
}
throw new IllegalArgumentException();
}

public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
for (Long value : shardingValue.getValues()) {
for (String tableName : availableTargetNames) {
if (tableName.endsWith(value % 4 + "")) {
result.add(tableName);
}
}
}
return result;
}

public Collection<String> doBetweenSharding(Collection<String> availableTargetNames,
ShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
Range<Long> range = (Range<Long>) shardingValue.getValueRange();
for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
for (String each : availableTargetNames) {
if (each.endsWith(i % 4 + "")) {
result.add(each);
}
}
}
return result;
}

}

我们这边引入的Spring Boot Starter包是2.x的版本,在这个版本中,分片算法的接口有调整,我们需要用到标准分片策略StandardShardingStrategy。提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。

StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。

PreciseShardingAlgorithm是必选的,用于处理=和IN的分片。RangeShardingAlgorithm是可选的,用于处理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND将按照全库路由处理。

自定义一个单分片算法:


import java.util.Collection;
import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
/**
* 自定义分片算法
*
* @author yinjihuan
*
*/
public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {

@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
for (String tableName : availableTargetNames) {
if (tableName.endsWith(shardingValue.getValue() % 4 + "")) {
return tableName;
}
}
throw new IllegalArgumentException();
}

}

使用需要修改我们之前的配置:


sharding.jdbc.config.sharding.tables.user.actual-data-nodes=ds_master.user_${0..3}
sharding.jdbc.config.sharding.tables.user.table-strategy.standard.sharding-column=id
sharding.jdbc.config.sharding.tables.user.table-strategy.standard.precise-algorithm-class-name=com.fangjia.sharding.MyPreciseShardingAlgorithm

源码参考:
https://github.com/yinjihuan/spring-cloud/tree/master/fangjia-sjdbc-sharding-table-springboot

参考代码中测试的代码也写好了,在Controller中,启动后通过调用接口的方式测试数据的添加和查询。


原文发布时间为:2018-09-10

本文作者:尹吉欢

本文来自云栖社区合作伙伴“猿天地”,了解相关信息可以关注“猿天地”。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
55 0
|
3月前
|
Java API Maven
敏感数据的保护伞——SpringBoot Jasypt加密库的使用
我们经常会在yml配置文件中存放一些敏感数据,比如数据库的用户名、密码,第三方应用的秘钥等等。这些信息直接以明文形式展示在文件中,无疑是存在较大的安全隐患的,所以今天这篇文章,我会借助jasypt实现yml文件中敏感信息的加密处理。
213 1
敏感数据的保护伞——SpringBoot Jasypt加密库的使用
|
1月前
|
关系型数据库 MySQL Java
MySQL的主从复制 && SpringBoot整合Sharding-JDBC解决读写分离
MySQL的主从复制 && SpringBoot整合Sharding-JDBC解决读写分离
39 0
|
5天前
|
SQL Java 数据库连接
JDBC Java标准库提供的一些api(类+方法) 统一各种数据库提供的api
JDBC Java标准库提供的一些api(类+方法) 统一各种数据库提供的api
10 0
|
14天前
|
SQL Java 数据库连接
Springboot框架整合Spring JDBC操作数据
JDBC是Java数据库连接API,用于执行SQL并访问多种关系数据库。它包括一系列Java类和接口,用于建立数据库连接、创建数据库操作对象、定义SQL语句、执行操作并处理结果集。直接使用JDBC涉及七个步骤,包括加载驱动、建立连接、创建对象、定义SQL、执行操作、处理结果和关闭资源。Spring Boot的`spring-boot-starter-jdbc`简化了这些步骤,提供了一个在Spring生态中更便捷使用JDBC的封装。集成Spring JDBC需要添加相关依赖,配置数据库连接信息,并通过JdbcTemplate进行数据库操作,如插入、更新、删除和查询。
|
15天前
|
Java 关系型数据库 MySQL
【JDBC编程】基于MySql的Java应用程序中访问数据库与交互数据的技术
【JDBC编程】基于MySql的Java应用程序中访问数据库与交互数据的技术
|
26天前
|
安全 Java 应用服务中间件
江帅帅:Spring Boot 底层级探索系列 03 - 简单配置
江帅帅:Spring Boot 底层级探索系列 03 - 简单配置
33 0
江帅帅:Spring Boot 底层级探索系列 03 - 简单配置
|
28天前
|
XML Java C++
【Spring系列】Sping VS Sping Boot区别与联系
【4月更文挑战第2天】Spring系列第一课:Spring Boot 能力介绍及简单实践
【Spring系列】Sping VS Sping Boot区别与联系
|
1月前
|
设计模式 Java 数据库连接
【Spring源码】JDBC数据源访问实现
我们再来看看阅读线索三,这方面我们从设计模式进行入手。阅读线索三:从这个模块可以学到什么我们看下以下代码,PreparedStatement实例的是由PreparedStatementCreator实现的。再来看看PreparedStatementCreator接口,一共有三个子类实现。也就是说PreparedStatement的三种不同实现被封装到三个子类中,而具体需要哪种实现,只需要传入不同。
25 1
【Spring源码】JDBC数据源访问实现
|
2月前
|
Java 数据库
SpringBoot出现com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Incorrect datetime va
SpringBoot出现com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Incorrect datetime va
17 0