Sharding-Jdbc

Sharding-Jdbc介绍

Sharding-Jdbc在3.0后改名为ShardingSphere它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。他们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。

Sharding-Sphere定位为关系型数据库中间件,旨在充分合理地在分布式的场景下利用关系型数据库的计算和存储能力,而并非实现一个全新的关系型数据库。它通过关注不变,进而抓住事物本质。关系型数据库当今依然占有巨大市场,是各个公司核心业务的基石,未来也难于撼动,我们目前阶段更加关注在原有基础上的增量,而非颠覆。

应用场景:

  1. 数据库读写分离
  2. 数据库分表分库

相关资料:
Sharding-Jdbc官方网址: http://shardingsphere.io/index_zh.html

在这里插入图片描述


Sharding-Jdbc与MyCat区别

  1. MyCat 是一个基于第三方应用中间件数据库代理框架,客户端所有的jdbc请求都必须要先交给MyCat,再有MyCat转发到具体的真实服务器中。

  2. Sharding-Jdbc 是一个Jar形式,在本地应用层重写Jdbc原生的方法,实现数据库分片形式。

  3. MyCat 属于服务器端数据库中间件,Sharding-Jdbc 是一个本地数据库中间件框架。

从设计理念上看确实有一定的相似性。

主要流程都是 SQL 解析 -> SQL 路由 -> SQL 改写 -> SQL 执行 -> 结果归并

但架构设计上是不同的。

Mycat 是基于 Proxy,它复写了 MySQL 协议,将 Mycat Server 伪装成一个 MySQL 数据库。
Sharding-JDBC 是基于 JDBC 的扩展,是以 jar 包的形式提供轻量级服务的。

Sharding-Jdbc实现读写分离

Sharding-Jdbc 实现读写分离原理,非常容易。只需要在项目中集成主和从的数据源,Sharding-Jdbc自动根据DMLDQL 语句类型连接主或者从数据源。

注意: Sharding-Jdbc只是实现连接主或者从数据源,不会实现主从复制功能,需要自己配置数据库自带主从复制方式。

查看MasterSlaveDataSource即可查看该类getDataSource方法获取当前数据源名称

DML:数据查询语言DQL基本结构是由SELECT子句,FROM子句,WHERE 子句组成的查询块: SELECT <字段名表> FROM <表或视图名> WHERE <查询条件>
DQL:数据操纵语言DML主要有三种形式: 1) 插入:INSERT 2) 更新:UPDATE 3) 删除:DELETE

Sharding-Jdbc分表分库

LogicTable
数据分片的逻辑表,对于水平拆分的数据库(表),同一类表的总称。
订单信息表拆分为2张表,分别是t_order_0、t_order_1,他们的逻辑表名为t_order。
ActualTable
在分片的数据库中真实存在的物理表。即上个示例中的t_order_0、t_order_1。
DataNode
数据分片的最小单元。由数据源名称和数据表组成,例:test_msg0.t_order_0。配置时默认各个分片数据库的表结构均相同,直接配置逻辑表和真实表对应关系即可。
ShardingColumn
分片字段。用于将数据库(表)水平拆分的关键字段。SQL中如果无分片字段,将执行全路由,性能较差。Sharding-JDBC支持多分片字段。
ShardingAlgorithm
分片算法。Sharding-JDBC通过分片算法将数据分片,支持通过等号、BETWEEN和IN分片。分片算法目前需要业务方开发者自行实现,可实现的灵活度非常高。未来Sharding-JDBC也将会实现常用分片算法,如range,hash和tag等。

SpringBoot整合Sharding-Jdbc分为两种方式

第一种:原生配置方式,自己需要实现接口。

  1. 分库算法类需要实现SingleKeyDatabaseShardingAlgorithm接口
  2. 分表算法类需要实现SingleKeyTableShardingAlgorithm接口

第二种:通过配置文件形式配置。
3. 案例比如:t_order 拆分程t_order_0 t_order _1

SpringBoot整合Sharding-Jdbc读写分离

<dependency>
	<groupId>io.shardingjdbc</groupId>
	<artifactId>sharding-jdbc-core</artifactId>
	<version>2.0.3</version>
</dependency>

application配置

server:
  port: 9002
mybatis-plus:
#  mapper-locations: classpath*:/mapper/*.xml
  global-config:
    db-config:
      column-underline: true
#shardingjdbc配置      
sharding:
  jdbc:
    data-sources:
     ###配置第一个从数据库
      ds_slave_0:
        password: root
        jdbc-url: jdbc:mysql://192.168.212.203:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true
        driver-class-name: com.mysql.jdbc.Driver
        username: root
      ###主数据库配置  
      ds_master:
        password: root
        jdbc-url: jdbc:mysql://192.168.212.202:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true
        driver-class-name: com.mysql.jdbc.Driver
        username: root
    ###配置读写分离    
    master-slave-rule:
    ###配置从库选择策略,提供轮询与随机,这里选择用轮询
      load-balance-algorithm-type: round_robin
      ####指定从数据库
      slave-data-source-names: ds_slave_0
      name: ds_ms
      ####指定主数据库
      master-data-source-name: ds_master

多从配置

slave-data-source-names: ds_slave_0,ds_slave_1,ds_slave_2

Config配置信息

@Data
@ConfigurationProperties(prefix = "sharding.jdbc")
public class ShardingMasterSlaveConfig {

	// 存放本地多个数据源
	private Map<String, HikariDataSource> dataSources = new HashMap<>();

	private MasterSlaveRuleConfiguration masterSlaveRule;
}

@Configuration
@EnableConfigurationProperties(ShardingMasterSlaveConfig.class)
@Log4j2
// 读取ds_master主数据源和读写分离配置
@ConditionalOnProperty({ "sharding.jdbc.data-sources.ds_master.jdbc-url",
		"sharding.jdbc.master-slave-rule.master-data-source-name" })
public class ShardingDataSourceConfig {

	@Autowired
	private ShardingMasterSlaveConfig shardingMasterSlaveConfig;

	@Bean
	public DataSource masterSlaveDataSource() throws SQLException {
		final Map<String, DataSource> dataSourceMap = Maps.newHashMap();
		dataSourceMap.putAll(shardingMasterSlaveConfig.getDataSources());
		final Map<String, Object> newHashMap = Maps.newHashMap();
		// 创建 MasterSlave数据源
		DataSource dataSource = MasterSlaveDataSourceFactory.createDataSource(dataSourceMap,
				shardingMasterSlaveConfig.getMasterSlaveRule(), newHashMap);
		log.info("masterSlaveDataSource config complete");
		return dataSource;
	}

}

SpringBoot整合Sharding-Jdbc分表

<!-- shardingjdbc 依赖信息 -->
<dependency>
	<groupId>io.shardingjdbc</groupId>
	<artifactId>sharding-jdbc-core</artifactId>
	<version>2.0.3</version>
</dependency>

<!-- Sharding-jdbc分布式id -->
<dependency>
	<groupId>com.dangdang</groupId>
	<artifactId>sharding-jdbc-self-id-generator</artifactId>
	<version>1.4.2</version>
</dependency>


application 配置

###数据库访问连接
spring:
  jdbc:
    db0:
      password: root
      className: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/%s?characterEncoding=utf-8
      username: root
  jpa: 
    database: mysql 
    show-sql: true 
    hibernate: 
    ## 自己建表 
      ddl-auto: none 
  application: 
    name: sharding-jdbc-first

DataSourceConfig

// 数据源相关配置信息
@Configuration
public class DataSourceConfig {
	@Value("${spring.jdbc.db0.className}")
	private String className;
	@Value("${spring.jdbc.db0.url}")
	private String url;
	@Value("${spring.jdbc.db0.username}")
	private String username;
	@Value("${spring.jdbc.db0.password}")
	private String password;

	// 配置自动增长策略(ID)
	@Bean
	public IdGenerator getIdGenerator() {
		return new CommonSelfIdGenerator();
	}

	// 创建数据源
	@Bean
	public DataSource getDataSource() {
		return buildDataSource();
	}

	private DataSource buildDataSource() {
		// 1.设置分库映射
		Map<String, DataSource> dataSourceMap = new HashMap<>(2);
		dataSourceMap.put("ds_0", createDataSource("ds_0"));
		// dataSourceMap.put("ds_1", createDataSource("ds_1"));
		// 设置默认db为ds_0,也就是为那些没有配置分库分表策略的指定的默认库
		// 如果只有一个库,也就是不需要分库的话,map里只放一个映射就行了,只有一个库时不需要指定默认库,
		// 但2个及以上时必须指定默认库,否则那些没有配置策略的表将无法操作数据
		DataSourceRule rule = new DataSourceRule(dataSourceMap, "ds_0");
		// 2.设置分表映射,将t_order_0和t_order_1两个实际的表映射到t_order逻辑表
		TableRule orderTableRule = TableRule.builder("t_order").actualTables(Arrays.asList("t_order_0", "t_order_1"))
				.dataSourceRule(rule).build();
		// 3.具体的分库分表策略
		ShardingRule shardingRule = ShardingRule.builder().dataSourceRule(rule)
				.tableRules(Arrays.asList(orderTableRule))
				// 根据userid分片字段
				.tableShardingStrategy(new TableShardingStrategy("user_id", new TableShardingAlgorithm())).build();
		// 创建数据源
		DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule);
		return dataSource;
	}

	private DataSource createDataSource(String dataSourceName) {
		// 使用druid连接数据库
		DruidDataSource druidDataSource = new DruidDataSource();
		druidDataSource.setDriverClassName(className);
		druidDataSource.setUrl(String.format(url, dataSourceName));
		druidDataSource.setUsername(username);
		druidDataSource.setPassword(password);
		return druidDataSource;
	}
}

TableShardingAlgorithm

public class TableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> {

	// sql 中关键字 匹配符为 =的时候,表的路由函数。配置分片算法
	public String doEqualSharding(Collection<String> availableTargetNames, ShardingValue<Long> shardingValue) {
		// availableTargetNames 分表的集合 如t_order_0 t_order_1这两张表
		for (String tableName : availableTargetNames) {
			// shardingValue.getValue() 就是 分片字段值 (ID)
			// 假如 tableName = t_order_0 shardingValue.getValue() = (ID)2
			// t_order_0 里的 0 包含  2%2= 0 
			if (tableName.endsWith(shardingValue.getValue() % 2 + "")) {
				// 如果 0包含0 返回 t_order_0 
				return tableName;
			}
		}
		throw new IllegalArgumentException();
	}

	@Override
	public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<Long> shardingValue) {

		return null;
	}

	@Override
	public Collection<String> doBetweenSharding(Collection<String> availableTargetNames,
			ShardingValue<Long> shardingValue) {

		return null;
	}

}

SpringBoot整合Sharding-Jdbc分库

DataSourceConfig

// 数据源相关配置信息
@Configuration
public class DataSourceConfig {
	@Value("${spring.jdbc.db0.className}")
	private String className;
	@Value("${spring.jdbc.db0.url}")
	private String url;
	@Value("${spring.jdbc.db0.username}")
	private String username;
	@Value("${spring.jdbc.db0.password}")
	private String password;

	@Bean
	public IdGenerator getIdGenerator() {
		return new CommonSelfIdGenerator();
	}

	@Bean
	public DataSource getDataSource() {
		return buildDataSource();
	}

	private DataSource buildDataSource() {
		// 1.设置分库映射
		Map<String, DataSource> dataSourceMap = new HashMap<>(2);
		dataSourceMap.put("ds_0", createDataSource("ds_0"));
		dataSourceMap.put("ds_1", createDataSource("ds_1"));
		// 设置默认db为ds_0,也就是为那些没有配置分库分表策略的指定的默认库
		// 如果只有一个库,也就是不需要分库的话,map里只放一个映射就行了,只有一个库时不需要指定默认库,
		// 但2个及以上时必须指定默认库,否则那些没有配置策略的表将无法操作数据
		DataSourceRule rule = new DataSourceRule(dataSourceMap, "ds_0");
		// 2.设置分表映射,将t_order_0和t_order_1两个实际的表映射到t_order逻辑表
		TableRule orderTableRule = TableRule.builder("t_order").dataSourceRule(rule).build();
		// 3.具体的分库分表策略
		ShardingRule shardingRule = ShardingRule.builder().dataSourceRule(rule)
				.tableRules(Arrays.asList(orderTableRule))
				// 根据userid进行分库
				.databaseShardingStrategy(new DatabaseShardingStrategy("user_id", new DatabaseShardingAlgorithm()))
				.build();
		// 创建数据源
		DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule);
		return dataSource;
	}

	private DataSource createDataSource(String dataSourceName) {
		// 使用druid连接数据库
		DruidDataSource druidDataSource = new DruidDataSource();
		druidDataSource.setDriverClassName(className);
		druidDataSource.setUrl(String.format(url, dataSourceName));
		druidDataSource.setUsername(username);
		druidDataSource.setPassword(password);
		return druidDataSource;
	}
}


DatabaseShardingAlgorithm

public class DatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Long> {

	@Override
	public String doEqualSharding(Collection<String> databases, ShardingValue<Long> shardingValue) {
		for (String tableName : databases) {
			System.out.println("tableName:" + tableName + ",----" + shardingValue.getValue());
			if (tableName.endsWith(shardingValue.getValue() % 2 + "")) {
				return tableName;
			}
		}
		throw new IllegalArgumentException();
	}

	@Override
	public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<Long> shardingValue) {

		return null;
	}

	@Override
	public Collection<String> doBetweenSharding(Collection<String> availableTargetNames,
			ShardingValue<Long> shardingValue) {

		return null;
	}

}

SpringBoot整合Sharding-Jdbc 配置文件形式

spring:
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
sharding:
  jdbc:
  ####ds1
    datasource:
      names: ds1
      ds1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/ds_1
        username: root
        password: root
    # 分片配置    
    config:
      sharding:
        tables:
          t_order:
            table-strategy:
              inline:
              #### 根据userid 进行分片
                sharding-column: user_id
                algorithm-expression: ds_1.t_order_$->{user_id % 2}
            # 分表总数 0-1
            actual-data-nodes: ds1.t_order_$->{0..1}
        props:
          sql: 
          ### 开启分片日志
            show: true


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值