使用Sharding-JDBC对数据进行分片处理详解
作者:1024程序猿~嗷~ 发布时间:2021-07-27 23:46:04
标签:Sharding,JDBC,数据,分片
前言
Sharding-JDBC是ShardingSphere的第一个产品,也是ShardingSphere的前身。
它定位为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
适用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等支持任意实现JDBC规范的数据库。
目前支持MySQL,Oracle,SQLServer和PostgreSQL。
Sharding-JDBC的使用需要我们对项目进行一些调整:结构如下
ShardingSphere文档地址
这里使用的是springBoot项目改造
一、加入依赖
<!-- 这里使用了druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<!-- sharding-jdbc 包 -->
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>1.5.4</version>
</dependency>
<!-- 这里使用了雪花算法生成组建,这个算法的实现的自己写的代码,各位客关老爷可以修改为自己的id生成策略 -->
<dependency>
<groupId>org.kcsm.common</groupId>
<artifactId>kcsm-idgenerator</artifactId>
<version>3.0.1</version>
</dependency>
二、修改application.yml配置文件
#启动接口
server:
port: 30009
spring:
jpa:
database: mysql
show-sql: true
hibernate:
# 修改不自动更新表
ddl-auto: none
#数据源0定义,这里只是用了一个数据源,各位客官可以根据自己的需求定义多个数据源
database0:
databaseName: database0
url: jdbc:mysql://kcsm-pre.mysql.rds.aliyuncs.com:3306/dstest?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=Hongkong
username: root
password: kcsm@111
driverClassName: com.mysql.jdbc.Driver
三、数据源定义
package com.lzx.code.codedemo.config;
import com.alibaba.druid.pool.DruidDataSource;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
/**
* 描述:数据源0定义
*
* @Auther: lzx
* @Date: 2019/9/9 15:19
*/
@Data
@ConfigurationProperties(prefix = "database0")
@Component
public class Database0Config {
private String url;
private String username;
private String password;
private String driverClassName;
private String databaseName;
public DataSource createDataSource() {
DruidDataSource result = new DruidDataSource();
result.setDriverClassName(getDriverClassName());
result.setUrl(getUrl());
result.setUsername(getUsername());
result.setPassword(getPassword());
return result;
}
}
四、数据源分配算法实现
package com.lzx.code.codedemo.config;
import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.SingleKeyDatabaseShardingAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 描述:数据源分配算法
*
* 这里我们只用了一个数据源,所以所有的都只返回了数据源0
*
* @Auther: lzx
* @Date: 2019/9/9 15:27
*/
@Component
public class DatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm {
@Autowired
private Database0Config database0Config;
/**
* = 条件时候返回的数据源
* @param collection
* @param shardingValue
* @return
*/
@Override
public String doEqualSharding(Collection collection, ShardingValue shardingValue) {
return database0Config.getDatabaseName();
}
/**
* IN 条件返回的数据源
* @param collection
* @param shardingValue
* @return
*/
@Override
public Collection<String> doInSharding(Collection collection, ShardingValue shardingValue) {
List<String> result = new ArrayList<String>();
result.add(database0Config.getDatabaseName());
return result;
}
/**
* BETWEEN 条件放回的数据源
* @param collection
* @param shardingValue
* @return
*/
@Override
public Collection<String> doBetweenSharding(Collection collection, ShardingValue shardingValue) {
List<String> result = new ArrayList<String>();
result.add(database0Config.getDatabaseName());
return result;
}
}
五、数据表分配算法
package com.lzx.code.codedemo.config;
import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm;
import com.google.common.collect.Range;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.LinkedHashSet;
/**
* 描述: 数据表分配算法的实现
*
* @Auther: lzx
* @Date: 2019/9/9 16:19
*/
@Component
public class TableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> {
/**
* = 条件时候返回的数据源
* @param collection
* @param shardingValue
* @return
*/
@Override
public String doEqualSharding(Collection<String> collection, ShardingValue<Long> shardingValue) {
for (String eaach:collection) {
Long value = shardingValue.getValue();
value = value >> 22;
if(eaach.endsWith(value%10+"")){
return eaach;
}
}
throw new IllegalArgumentException();
}
/**
* IN 条件返回的数据源
* @param tableNames
* @param shardingValue
* @return
*/
@Override
public Collection<String> doInSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(tableNames.size());
for (Long value : shardingValue.getValues()) {
for (String tableName : tableNames) {
value = value >> 22;
if (tableName.endsWith(value % 10 + "")) {
result.add(tableName);
}
}
}
return result;
}
/**
* BETWEEN 条件放回的数据源
* @param tableNames
* @param shardingValue
* @return
*/
@Override
public Collection<String> doBetweenSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
Collection<String> result = new LinkedHashSet<>(tableNames.size());
Range<Long> range = shardingValue.getValueRange();
for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
for (String each : tableNames) {
Long value = i >> 22;
if (each.endsWith(i % 10 + "")) {
result.add(each);
}
}
}
return result;
}
}
六、数据源配置
package com.lzx.code.codedemo.config;
import com.dangdang.ddframe.rdb.sharding.api.ShardingDataSourceFactory;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.keygen.DefaultKeyGenerator;
import com.dangdang.ddframe.rdb.sharding.keygen.KeyGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 描述:数据源配置
*
* @Auther: lzx
* @Date: 2019/9/9 15:21
*/
@Configuration
public class DataSourceConfig {
@Autowired
private Database0Config database0Config;
@Autowired
private DatabaseShardingAlgorithm databaseShardingAlgorithm;
@Autowired
private TableShardingAlgorithm tableShardingAlgorithm;
@Bean
public DataSource getDataSource() throws SQLException {
return buildDataSource();
}
private DataSource buildDataSource() throws SQLException {
//分库设置
Map<String, DataSource> dataSourceMap = new HashMap<>(2);
//添加两个数据库database0和database1
dataSourceMap.put(database0Config.getDatabaseName(), database0Config.createDataSource());
//设置默认数据库
DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap, database0Config.getDatabaseName());
//分表设置,大致思想就是将查询虚拟表Goods根据一定规则映射到真实表中去
TableRule orderTableRule = TableRule.builder("user")
.actualTables(Arrays.asList("user_0", "user_1", "user_2", "user_3", "user_4", "user_5", "user_6", "user_7", "user_8", "user_9"))
.dataSourceRule(dataSourceRule)
.build();
//分库分表策略
ShardingRule shardingRule = ShardingRule.builder()
.dataSourceRule(dataSourceRule)
.tableRules(Arrays.asList(orderTableRule))
.databaseShardingStrategy(new DatabaseShardingStrategy("ID", databaseShardingAlgorithm))
.tableShardingStrategy(new TableShardingStrategy("ID", tableShardingAlgorithm)).build();
DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule);
return dataSource;
}
@Bean
public KeyGenerator keyGenerator() {
return new DefaultKeyGenerator();
}
}
七、开始测试
定义一个实体
package com.lzx.code.codedemo.entity;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.*;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
/**
* 描述: 用户
*
* @Auther: lzx
* @Date: 2019/7/11 15:39
*/
@Entity(name = "USER")
@Getter
@Setter
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
@AllArgsConstructor
@NoArgsConstructor
public class User {
/**
* 主键
*/
@Id
@GeneratedValue(generator = "idUserConfig")
@GenericGenerator(name ="idUserConfig" ,strategy="org.kcsm.common.ids.SerialIdGeneratorSnowflakeId")
@Column(name = "ID", unique = true,nullable=false)
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 用户名
*/
@Column(name = "USER_NAME",length = 100)
private String userName;
/**
* 密码
*/
@Column(name = "PASSWORD",length = 100)
private String password;
}
定义实体DAO
package com.lzx.code.codedemo.dao;
import com.lzx.code.codedemo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
/**
* 描述: 用户dao接口
*
* @Auther: lzx
* @Date: 2019/7/11 15:52
*/
@RepositoryRestResource(path = "user")
public interface UserDao extends JpaRepository<User,Long>,JpaSpecificationExecutor<User> {
}
测试类,插入1000条user数据
package com.lzx.code.codedemo;
import com.lzx.code.codedemo.dao.RolesDao;
import com.lzx.code.codedemo.dao.UserDao;
import com.lzx.code.codedemo.entity.Roles;
import com.lzx.code.codedemo.entity.User;
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
public class CodeDemoApplicationTests {
@Autowired
private UserDao userDao;
@Autowired
private RolesDao rolesDao;
@Test
public void contextLoads() {
User user = null;
Roles roles = null;
for(int i=0;i<1000;i++){
user = new User(
null,
"lzx"+i,
"123456"
);
roles = new Roles(
null,
"角色"+i
);
rolesDao.save(roles);
userDao.save(user);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
效果:数据被分片存储到0~9的数据表中
来源:https://blog.csdn.net/github_35976996/article/details/100690778


猜你喜欢
- 可能我们用惯了 Newtonsoft.Json.dll 等第三方的类库来实现序列化等类似的操作,但是有时只是简单的用一下,感觉没必要那么费事
- Unity中的PostProcessScene:深入解析与实用案例在Unity游戏开发中,我们经常需要对场景进行后处理,以实现更丰富的视觉效
- 本文实例讲述了C#实现基于XML配置MenuStrip菜单的方法。分享给大家供大家参考。具体如下:1.关于本程序的说明用XML配置MenuS
- 1 简介Solace是一个强大的实时性的事件驱动消息队列。本文将介绍如何在Spring中使用,虽然代码使用的是Spring Boot,但并没
- using System; using System.Drawing; using System.Collec
- 一、前言前面我们学习了多态中的转型,那么现在我们开始学习抽象类的概述和使用二、抽象类生活大多事物是具有抽象含义的,比如我说一个生物,你想不到
- 目录题目及要求:提示:原创代码:代码思路:题目及要求:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。提示:0 <
- 你要学会:流的概念处理字节流的类处理字符流的类Java标准输入输出文件管理类Java语言的输入输出类库1.流的概念流是指计算机各部件之间的数
- 本文实例为大家分享了OpenGL实现多段Bezier曲线拼接的具体代码,供大家参考,具体内容如下运行程序的交互方式有点类似corelDraw
- 引入第三方jar包或者查看Java源码的时候,经常遇到问题如下:decompiled.class file bytecode version
- list stream: reduce的使用stream 中的 reduce 的主要作用就是stream中元素进行组合,组合的方式可以是加减
- 什么是JavaMemoryModel(JMM)?JMM通过构建一个统一的内存模型来屏蔽掉不同硬件平台和不同操作系统之间的差异,让Java开发
- Collection 接口 :Collection是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法。Set和
- 简介网上对于 Camera2 的介绍有很多,在 Github 上也有很多关于 Camera2 的封装库,但是对于那些库,封装性太强,有时候我
- 基于Java语言实现Socket通信由于近日项目需求,需要在服务器中增加Socket通信的功能,接收硬件设备发送的心跳包和相关数据,因此又重
- 用Canvas画贝塞尔曲线,要画贝塞尔曲线首先了解贝塞尔曲线:由于用计算机画图大部分时间是操作鼠标来掌握线条的路径,与手绘的感觉和效果有很大
- Android 自定义dialog的实现代码搜索相关关键字网上一大堆实现,但是看完总觉得缺胳膊少腿,绕了不少弯路,终于弄好了自定义dialo
- 本文实例为大家分享了Java中Stream流去除List重复元素的具体代码,供大家参考,具体内容如下业务场景在开发中我们常常需要过滤List
- 递归方法定义本身调用方法本身的现象叫做递归在这之前我们学的东西:例如StringBuffer.append().append().appen
- 本文实例讲述了Struts2+Hibernate实现数据分页的方法。分享给大家供大家参考,具体如下:1.用Hibernate实现分页技术:/