对于Sharding-JDBC的介绍这里就过多阐述,Sharding-JDBC是当当网自研的关系型数据库的水平扩展框架,现已捐献给Apache。具体了解可以看官方文档。
shardingsphere文档地址
本文使用的sharding-jdbc版本为3.1.0
1、创建数据库:
模拟订单数据库,有两个数据库ds_0、ds_1,依据于user_id进行分库。每个库中,将t_order表依据order_id进行拆分为t_order_0,t_order_1两个表,依据order_id进行分表。
CREATE DATABASE IF NOT EXISTS `ds_0`;
USE `ds_0`;
CREATE TABLE IF NOT EXISTS `t_order_0` (
`order_id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`status` varchar(50) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `t_order_1` (
`order_id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`status` varchar(50) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE DATABASE IF NOT EXISTS `ds_1`;
USE `ds_1`;
-- Dumping structure for table demo_ds_0.t_order_0
CREATE TABLE IF NOT EXISTS `t_order_0` (
`order_id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`status` varchar(50) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
-- Dumping structure for table demo_ds_0.t_order_1
CREATE TABLE IF NOT EXISTS `t_order_1` (
`order_id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`status` varchar(50) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2、pom文件
io.shardingsphere
sharding-jdbc-spring-boot-starter
3.1.0
io.shardingsphere
sharding-transaction-2pc-xa
3.1.0
io.shardingsphere
sharding-transaction-spring
3.1.0
org.postgresql
postgresql
runtime
3、application.properties配置
mybatis.mapper-locations=classpath:mapping/*.xml
spring.profiles.active=sharding
sharding.jdbc.datasource.names=ds0,ds1
sharding.jdbc.datasource.ds0.type=org.apache.commons.dbcp.BasicDataSource
sharding.jdbc.datasource.ds0.driver-class-name=org.postgresql.Driver
sharding.jdbc.datasource.ds0.url=jdbc:postgresql://127.0.0.1:5432/ds_0
sharding.jdbc.datasource.ds0.username=postgres
sharding.jdbc.datasource.ds0.password=123456
sharding.jdbc.datasource.ds1.type=org.apache.commons.dbcp.BasicDataSource
sharding.jdbc.datasource.ds1.driver-class-name=org.postgresql.Driver
sharding.jdbc.datasource.ds1.url=jdbc:postgresql://127.0.0.1:5432/ds_1
sharding.jdbc.datasource.ds1.username=postgres
sharding.jdbc.datasource.ds1.password=123456
#设置默认数据库
sharding.jdbc.config.sharding.default-data-source-name=ds0
#分库策略--对哪个字段进行分库
sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=user_id
#分库对user_id % 2进行分库选择
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=ds$->{user_id % 2}
# 分表
sharding.jdbc.config.sharding.tables.t_order.logic-table=t_order
sharding.jdbc.config.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
sharding.jdbc.config.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2}
sharding.jdbc.config.sharding.tables.t_order.key-generator-column-name=order_id
至此,就可以正常集成mybatis进行数据库操作,并能征程进行分库分表。读者可自行测试。
由于性能方面的考虑,shard-jdbc不支持强一致性分布式事务,所以针对某些特定的场景,又提出了柔性事务的概念。这里只进行柔性事务的一种实现,不过多阐述概念性问题,可自行了解。
最大努力送达型:在分布式数据库的场景下,相信对于该数据库的操作最终一定可以成功,所以通过最大努力反复尝试送达操作。
使用最大努力送达型柔性事务的SQL需要满足幂等性。
INSERT语句要求必须包含主键,且不能是自增主键。
UPDATE语句要求幂等,不能是UPDATE xxx SET x=x+1
DELETE语句无要求。
采用注解方式实现,须在方法前加:
@ShardingTransactionType(TransactionType.XA)
@Transactional(rollbackFor = Exception.class)
启动类
import com.linewell.storage.service.CodeConvertApiImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication(exclude = JtaAutoConfiguration.class)
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
}
}
我们进行分库分表的字段一般定义为Integer,但由于此类型范围的限制,若是参数长度过长,则会出现问题。解决办法为将字段定义为String,手动将字段取后几位进行类型转换后模运算即可,具体实现:
sharding.jdbc.config.sharding.default-database-strategy.standard.sharding-column=user_id
sharding.jdbc.config.sharding.default-database-strategy.standard.precise-algorithm-class-name=com.demo.config.DatabaseShardingAlgorithm
DatabaseShardingAlgorithm类:
import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import java.util.Collection;
/**
* @anthor h_s
* @date 2019/10/29 0029
* @description 分库规则类,取user_id后面一位进行取模
*/
public class DatabaseShardingAlgorithm implements PreciseShardingAlgorithm {
@Override
public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {
for (String tableName : availableTargetNames) {
if (tableName.endsWith(Long.parseLong(shardingValue.getValue().substring(shardingValue.getValue().length()-1)) % 2 + "")) {
return tableName;
}
}
throw new IllegalArgumentException();
}
}
即将原先分库策略改为标准分片策略(StandardShardingStrategy)的PreciseShardingAlgorithm实现。
参考:
https://blog.csdn.net/bohu83/article/details/80657169
https://www.jianshu.com/p/92af4d298fea
https://blog.csdn.net/xl890727/article/details/97674968