Nemo

Nemo

路漫漫其修远兮,吾将上下而求索。

Nemo

Nemo

关注TA

路漫漫其修远兮,吾将上下而求索。

  •  普罗旺斯
  • 负责帅就完事了
  • 写了1,430,174字

最近回复

该文章投稿至Nemo社区   Java  板块 复制链接


SpringBoot 整合 sharding jdbc 做数据库分库分表 DEMO (Sharding-jdbc+mybatis+springboot+druid)

发布于 2020/09/08 16:40 488浏览 0回复 5,790

Demo源码已上传到github。

https://github.com/geeeeeeeeeeeeeeeek/sharding-demo


什么是Sharding?

Sharding 是开源的分布式数据库中间件解决方案集成套件。由Sharding-jdbc、Sharding-proxy、Sharding-Sidecar三款产品组成。


什么时候能用上Sharding?

一般系统在经久运行时,数据量都是在逐步增加的。

1、关系型数据库在数据达到一定的量级,数据库sql优化逐渐也达不到理想的效果,访问量剧增导致单台数据库服务器IO/CPU资源吃紧等一类的场景,这时候需要考虑将数据库或者数据库表拆分或是做数据的读写分离,用以减少单台数据库请求、SQL执行的压力。

这时候Sharding就能派上用场了。


目前Sharding存在的问题?

暂时不支持分布式事务,不过官方据称已经在做相关的开发工作了。(2020/09/08)


SpringBoot整合Sharding做分库分表的示例?

在SpringBoot中整合Sharding还是挺简单的。如是已存在的项目,在几乎不对原有代码逻辑做修改的同时,即可以使用Sharing完成相关分库分表的改造。

下述DEMO描述基于SpringBoot + Mybatis + Druid。

假设需要针对于表sys_user 表作为拆分,分到两个库(sharding-01和shading-02)中,每个库中这个表又被拆分为3个子表(sys_user、sys_user2、sys_user3)。如下:

---- DATABASE FOR SHARDING DEMO

-- create databases
CREATE DATABASE IF NOT EXISTS sharding-01 DEFAULT CHARACTER SET=UTF8 COLLATE UTF8_GENERAL_CI;
CREATE DATABASE IF NOT EXISTS sharding-02 DEFAULT CHARACTER SET=UTF8 COLLATE UTF8_GENERAL_CI;

-- create tables for sharding-01
USE sharding-01;

CREATE TABLE `sys_user1` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL COMMENT '用户名',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `sys_user2` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL COMMENT '用户名',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `sys_user3` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL COMMENT '用户名',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- create tables for sharding-02
USE sharding-02;

CREATE TABLE `sys_user1` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL COMMENT '用户名',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `sys_user2` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL COMMENT '用户名',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `sys_user3` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL COMMENT '用户名',
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


有很多方法可以完成整合,这里使用其中我认为最值得推荐的一种(基于yml配置),三个步骤,即可完成整合。


1、首先,pom需要添加sharding-jdbk相关依赖:

<dependency>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>${sharding.jdbc.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>${sharding.sphere.version}</version>
</dependency>


2、添加分库分表的多数据源配置(dataSource.yml文件):
dataSources:
# 数据源1
ds0: !!com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sharding-01?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
#数据源2
ds1: !!com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/sharding-02?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
shardingRule:
tables:
# sys_user表的分库分表规则
sys_user:
# 可能存在ds0/ds1数据库中的sys_user1或者sys_user2或者sys_user3
actualDataNodes: ds${0..1}.sys_user${1..3}
tableStrategy:
inline:
# 按ID做为分表依据
shardingColumn: id
algorithmExpression: sys_user0{id % 3 + 1}
databaseStrategy:
inline:
# 同时按ID作为分库依据
shardingColumn: id
algorithmExpression: ds${id % 2}
# 需要使用ID生成器生成的列,分布式数据库中,ID应统一分配
keyGeneratorColumnName: id
# 自定义的ID生成器,如不指定,会默认使用sharding提供的雪花算法生成器
keyGeneratorClass: com.nemo.sharding.key.UserIdGenerator
# 绑定的表列表
bindingTables:
- sys_user
#默认一些配置,如默认使用数据源,默认分库规则,默认分表规则
defaultDataSourceName: ds0
defaultDatabaseStrategy:
inline:
shardingColumn: id
algorithmExpression: ds${id % 2}
defaultTableStrategy:
none:
# 显示实际执行SQL
props:
sql.show: true


3、添加分库分表配置,注入spring容器中。
/**
* 分库分表数据源配置
* @author: Nemo
* @date: 2020/9/4.
*/
@Configuration
public class DataSourceConfig {

@Autowired
private Filter statFilter;

/**
* 分库分表配置文件
*/
private static final String SHARDING_YML_PATH = "dataSource.yml";

/**
* 构建dataSource
* 这里没有使用ShardingDataSourceFactory
* 因为要为durid数据源配置监听Filter
* @return
* @throws SQLException
* @throws IOException
*/
@Bean
public DataSource dataSource() throws SQLException, IOException {
YamlShardingConfiguration config = parse();
ShardingRule rule = config.getShardingRule(Collections.emptyMap());
rule.getDataSourceMap().forEach((k,v)->{
DruidDataSource druidDataSource = (DruidDataSource) v;
druidDataSource.setProxyFilters(Lists.newArrayList(statFilter));
});
return new ShardingDataSource(rule, config.getShardingRule().getConfigMap(), config.getShardingRule().getProps());
}

/**
* 解析yml,得到配置信息
* @return
* @throws IOException
* @throws FileNotFoundException
* @throws UnsupportedEncodingException
*/
private YamlShardingConfiguration parse() throws IOException, FileNotFoundException, UnsupportedEncodingException {
Resource certResource = new ClassPathResource(SHARDING_YML_PATH);
try (
InputStreamReader inputStreamReader = new InputStreamReader(certResource.getInputStream(), "UTF-8")
) {
return new Yaml(new Constructor(YamlShardingConfiguration.class)).loadAs(inputStreamReader, YamlShardingConfiguration.class);
}
}

}



到这里,其实整个整合,也就完成了。

原有的代码逻辑,都不需要改动。

如:

select * from sys_user

这时候对于sys_user 表相关的操作,都会被均匀的落到sharding-1和sharding-2中的三个sys_user*表。



先到这里吧,简单记录下。

=====END=====





点赞(2)
点了个评