mybatis plus整合sharding-jdbc在基于spring boot的项目中的单库分表应用
2018.08.10
PKAQ
后台开发
 热度
℃
共
引言
在产品应用中,当某些业务数据量过大时会导致数据库读写性能急剧下降甚至拖慢其它业务的情况。此时便需要对数据库进行不同维度的拆分,例如水平拆分或者垂直拆分。
垂直拆分(分库):按业务相关度将相关业务的表拆分到不同数据库中,例如订单库、商品库。通过这种拆分相关业务模块仅需请求其业务相关的库即可。
水平拆分(分表):按数据相关度将单表拆分为多张表,与垂直拆分不同的是水平拆分是针对单表,当系统中某张表数据量太大时可以采用水平拆分的方式根据定义的规则拆分成多张表以提高读写性能。
具体选择哪种拆分方式还需要结合实际业务情况。在实际应用中,采用两种方式进行联合拆分的情况也是非常常见的,当然,如果在小规模应用的情况下非要做两种拆分,那除了炫技之外同时还会增加开发运维成本,是毫无意义的。
本文讨论的情况仅限于水平拆分,即对单库大数据量表进行拆分。具体原理也很简单,只要把mybatis plus的数据源换成shardingJdbcDatasource即可。下面的示例是以订单表为例,按表中的month字段按月分表。
版本
- sharding-jdbc: 3.0.0.M2
- mybatis plus: 2.3
- druid: 1.1.10
步骤
规则定义
拆分之前首先要确定好拆分规则,并且根据拆分规则在数据库中建立好相关表
依赖引入
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| ext { druid = "1.1.10" mybatis_plus = "2.3" mybatis_plus_starter = "1.0.5" sharding_jdbc = "3.0.0.M2" }
compile "io.shardingsphere:sharding-jdbc:${sharding_jdbc}", "com.baomidou:mybatis-plus-core:${mybatis_plus}"
compile("com.alibaba:druid-spring-boot-starter:${druid}"){ exclude group: 'com.alibaba', module: 'jconsole' exclude group: 'com.alibaba', module: 'tools' }
|
规则配置
** 配置类 **
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| package org.pkaq.config;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean; import io.shardingsphere.core.api.ShardingDataSourceFactory; import io.shardingsphere.core.api.config.ShardingRuleConfiguration; import io.shardingsphere.core.api.config.TableRuleConfiguration; import io.shardingsphere.core.api.config.strategy.StandardShardingStrategyConfiguration; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct; import javax.sql.DataSource; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Properties;
@Slf4j @Configuration @AutoConfigureAfter(DataSource.class) public class ShardingJDBCConfiguration {
private final DataSource dataSource;
private DataSource shardingDataSource;
@Autowired public ShardingJDBCConfiguration(DataSource dataSource) { this.dataSource = dataSource; }
@PostConstruct public void shardingDataSource() throws SQLException { ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration(); shardingRuleConfig.getTableRuleConfigs().add(getOrderTableRuleConfiguration()); this.shardingDataSource = ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, new HashMap<>(1), new Properties()); }
private TableRuleConfiguration getOrderTableRuleConfiguration() { TableRuleConfiguration rule = new TableRuleConfiguration(); rule.setLogicTable("T_ORDER"); rule.setActualDataNodes("ds0.T_ORDER_$->{2018..2019}_$->{['01','08','12']}"); StandardShardingStrategyConfiguration strategyConfiguration = new StandardShardingStrategyConfiguration("month", new MonthTableShardingAlgorithm()); rule.setTableShardingStrategyConfig(strategyConfiguration); rule.setKeyGeneratorColumnName("id"); return rule; }
private Map<String, DataSource> createDataSourceMap() { Map<String, DataSource> result = new HashMap<>(1); result.put("ds0", dataSource); return result; }
@Bean public MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean() { MybatisSqlSessionFactoryBean mysqlplus = new MybatisSqlSessionFactoryBean(); mysqlplus.setDataSource(this.getShardingDataSource()); return mysqlplus; }
public DataSource getShardingDataSource(){ return this.shardingDataSource; } }
|
** 分片规则实现 **
这里的分片规则理论上是可选配置,只是如果不配置的话默认会进行全表路由,即从所有拆分的表中进行查询。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package org.pkaq.config;
import cn.hutool.core.date.DateUtil; import io.shardingsphere.core.api.algorithm.sharding.PreciseShardingValue; import io.shardingsphere.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import java.util.Collection; import java.util.Date;
public class MonthTableShardingAlgorithm implements PreciseShardingAlgorithm<Date> {
@Override public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) { String tableExt = DateUtil.format(shardingValue.getValue(), "yyyy_MM");
for (String availableTableName : availableTargetNames) { if (availableTableName.endsWith(tableExt)) { return availableTableName; } } return null; } }
|