利用Sharding-Jdbc实现分表
闲来无事,喜欢研究一些自己未接触过的技术~
看到了当当开源的Sharding-JDBC组件,它可以在几乎不修改代码的情况下完成分库分表的实现。摘抄其中一段介绍:
Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零:
可适用于任何基于java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
可基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid等。
理论上可支持任意实现JDBC规范的数据库。虽然目前仅支持MySQL,但已有支持Oracle,SQLServer,DB2等数据库的计划。
先做一个最简单的试用,不做分库,仅做分表。选择数据表bead_information,首先复制成三个表:bead_information_0、bead_information_1、bead_information_2
测试实现过程
前提:已经实现srping+mybatis对单库单表做增删改查的项目。
1、修改pom.xml增加dependency
com.dangdang
sharding-jdbc-core
1.4.2
com.dangdang
sharding-jdbc-config-spring
1.4.0
2、新建一个sharding-jdbc.xml文件,实现分库分表的配置
jndi 形式
标记
3、将文件引入spring配置文件中。
需要修改几个地方,把sqlSessionFactory和transactionManager原来关联的dataSource统一修改为shardingDataSource(这一步作用就是把数据源全部托管给sharding去管理)
4、实现分表(分库)逻辑,我们的分表逻辑类需要实现SingleKeyTableShardingAlgorithm接口的三个方法doBetweenSharding、doEqualSharding、doInSharding
(取模除数需要按照自己需求改变,我这里分3个表,所以除以3)
复制代码(分表策略实测)
package com.suning.jupiter.common.utils;
import java.util.Collection;
import java.util.LinkedHashSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 MemberSingleKeyTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm{
public static final Logger logger = LoggerFactory.getLogger(MemberSingleKeyTableShardingAlgorithm.class);
public Collection doBetweenSharding(Collection tableNames, ShardingValue shardingValue) {
Collection result = new LinkedHashSet(tableNames.size());
Range range = (Range) shardingValue.getValueRange();
for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
Long modValue = i % 4;
String modStr = modValue < 4 ? "" + modValue : modValue.toString();
for (String each : tableNames) {
if (each.endsWith(modStr)) {
result.add(each);
}
}
}
return result;
}
public String doEqualSharding(Collection tableNames, ShardingValue shardingValue) {
Number value = (Number)shardingValue.getValue();
logger.info("shardingValue.getValue()::::{}",value.getClass().getName());
Long modValue = value.longValue() % 4;
String modStr = modValue < 4 ? "" + modValue : modValue.toString();
for (String each : tableNames) {
if (each.endsWith(modStr)) {
return each;
}
}
throw new IllegalArgumentException();
}
public Collection doInSharding(Collection tableNames, ShardingValue shardingValue) {
Collection result = new LinkedHashSet(tableNames.size());
for (Long value : shardingValue.getValues()) {
Long modValue = value % 4;
String modStr = modValue < 4 ? "" + modValue : modValue.toString();
for (String tableName : tableNames) {
if (tableName.endsWith(modStr)) {
result.add(tableName);
}
}
}
return result;
}
}
5、配置完成,可以实现增删改查测试。
这里我简单介绍下一些属性的含义
配置分表规则器
sharding-columns:分表规 则依赖的名(根据user_id取模分表),
algorithm-class:分表规则的实现类 ,
logic-table:逻辑表名(mybatis中代替的表名)
actual-tables:数据库实际的表名,这里支持inline表达式,比如:member_index_tbl_KaTeX parse error: Expected group after '_' at position 84: …ember_index_tbl_̲{[a,b,c]}会被解析成member_index_tbl_a,member_index_tbl_b和member_index_tbl_c,两种表达式一起使用的时候,会采取笛卡尔积的方式:member_index_tbl_ [ a , b ] {[a,b]} [a,b]{0…2}解析为member_index_tbl_a0,member_index_tbl_a1 member_index_tbl_a2,member_index_tbl_b0,member_index_tbl_b1,member_index_tbl_b2;
table-strategy:前面定义的分表规则器;