SpringBoot使用Sharding-JDBC对PostgreSQL数据库分库分表

SpringBoot使用Sharding-JDBC对PostgreSQL数据库分库分表

  • 关于Sharding-JDBC
    • 集成sharding-jdbc
    • 关于sharding-jdbc柔性事务
    • 可能存在问题

关于Sharding-JDBC

对于Sharding-JDBC的介绍这里就过多阐述,Sharding-JDBC是当当网自研的关系型数据库的水平扩展框架,现已捐献给Apache。具体了解可以看官方文档。
shardingsphere文档地址

集成sharding-jdbc

本文使用的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进行数据库操作,并能征程进行分库分表。读者可自行测试。

关于sharding-jdbc柔性事务

由于性能方面的考虑,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

你可能感兴趣的:(Java#Springboot)