天天看點

springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作

目錄

介紹

springboot整合sharding-jdbc分庫分表

pom依賴

application.properties配置檔案

分庫分表配置

分庫分表配置

分庫規則 

分表規則 

 controller

entity

mapper

mapper.xml

庫表結構

代碼測試

demo網盤連結:https://pan.baidu.com/s/1GRDY2WV35B2tDINNFsYZlw 

提取碼:6rbl

介紹

sharding-jdbc是基于JDBC實作代理的可叫做用戶端分庫分表,MyCat是基于資料庫DB代理的可叫做服務端分庫分表。

springboot整合sharding-jdbc分庫分表

pom依賴

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.sharding</groupId>
  <artifactId>sharding</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.3.RELEASE</version>
	</parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
 
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
 
        <!--sharding-jdbc -->
        <dependency>
            <groupId>com.dangdang</groupId>
            <artifactId>sharding-jdbc-core</artifactId>
            <version>1.5.4</version>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>
	
           

application.properties配置檔案

mybatis.config-locations=classpath:mybatis/mybatis-config.xml
 
#datasource
spring.devtools.remote.restart.enabled=false
 
#data source1
spring.datasource.test1.driverClassName=com.mysql.jdbc.Driver
spring.datasource.test1.jdbcUrl=jdbc:mysql://127.0.0.1:3306/test_0?serverTimezone=UTC
spring.datasource.test1.username=root
spring.datasource.test1.password=root
 
#data source2
spring.datasource.test2.driverClassName=com.mysql.jdbc.Driver
spring.datasource.test2.jdbcUrl=jdbc:mysql://127.0.0.1:3306/test_1?serverTimezone=UTC
spring.datasource.test2.username=root
spring.datasource.test2.password=root
           

分庫分表配置

配置多資料源、根據那個字段進行分庫、分表政策

/**
 * 分庫分表配置 - 需要關聯查詢的表不建議進行分庫,但是可以同庫分表!
 * 
 * @Description: 資料源配置和Mybatis配置和分庫分表規則
 */
@Configuration
@MapperScan(basePackages = "com.mapper", sqlSessionTemplateRef  = "test1SqlSessionTemplate")
public class DataSourceConfig {

    // >>>>>>> 配置多資料源 <<<<<<<<
    /**
     * 指定配置檔案中的配置資料源0,資料源的名稱最好要有一定的規則,友善配置分庫的計算規則
     */
    @Bean(name="test_0")
    @ConfigurationProperties(prefix = "spring.datasource.test1")
    public DataSource test_0(){
        return DataSourceBuilder.create().build();
    }
    /**
     * 指定配置檔案中的配置資料源1,資料源的名稱最好要有一定的規則,友善配置分庫的計算規則
     */
    @Bean(name="test_1")
    @ConfigurationProperties(prefix = "spring.datasource.test2")
    public DataSource test_1(){
        return DataSourceBuilder.create().build();
    }
 
    /**
     * 配置資料源規則,即将多個資料源交給sharding-jdbc管理,并且可以設定預設的資料源,
     * 當表沒有配置分庫規則時會使用預設的資料源
     * 
     * @param test_0 執行個體化資料庫名
     * @param test_1 執行個體化資料庫名
     * @return
     */
    @Bean
    public DataSourceRule dataSourceRule(@Qualifier("test_0") DataSource test_0,
                                         @Qualifier("test_1") DataSource test_1){
        Map<String, DataSource> dataSourceMap = new HashMap<>(); //設定分庫映射
        dataSourceMap.put("test_0", test_0);
        dataSourceMap.put("test_1", test_1);
        return new DataSourceRule(dataSourceMap, "test_0"); //設定預設庫,兩個庫以上時必須設定預設庫。預設庫的資料源名稱必須是dataSourceMap的key之一
    }


    // >>>>>>> 配置分表政策 <<<<<<<<
    /**
     * 配置資料源政策和表政策,具體政策需要自己實作
     * @param dataSourceRule
     * @return
     */
    @Bean
    public ShardingRule shardingRule(DataSourceRule dataSourceRule){
        //具體分庫分表政策,多個不同表可裝入List中
        TableRule orderTableRule = TableRule.builder("user")// 去掉字尾的表名
                .actualTables(Arrays.asList("user_0", "user_1"))// 水準拆分後相同屬性的所有表名
                .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()))// 指定表分片政策根據那個字段(或者傳入的數值)進行取模算法
                .dataSourceRule(dataSourceRule)
                .build();
 
        //綁定表政策,在查詢時會使用主表政策計算路由的資料源,是以需要約定綁定表政策的表的規則需要一緻,可以一定程度提高效率
        List<BindingTableRule> bindingTableRules = new ArrayList<BindingTableRule>();
        bindingTableRules.add(new BindingTableRule(Arrays.asList(orderTableRule)));
        return ShardingRule.builder()
                .dataSourceRule(dataSourceRule)
                .tableRules(Arrays.asList(orderTableRule))
                .bindingTableRules(bindingTableRules)
                // 分庫-通過user_id(字段名稱可随意修改,和資料庫對應上即可)字段來進行取模算法
                .databaseShardingStrategy(new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm()))
                // 分表-通過order_id(字段名稱可随意修改,和資料庫對應上即可)字段來進行取模算法   (先分庫再分表)
                .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()))
                .build();
    }
    
    
 
    /**
     * 建立sharding-jdbc的資料源DataSource,MybatisAutoConfiguration會使用此資料源
     * @param shardingRule
     * @return
     * @throws SQLException
     */
    @Bean(name="dataSource")
    public DataSource shardingDataSource(ShardingRule shardingRule) throws SQLException {
        return ShardingDataSourceFactory.createDataSource(shardingRule);
    }
 
    /**
     * 需要手動配置事務管理器
     * @param dataSource
     * @return
     */
    @Bean
    public DataSourceTransactionManager transactitonManager(@Qualifier("dataSource") DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
 
    @Bean(name = "test1SqlSessionFactory")
    @Primary
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/*.xml"));
        return bean.getObject();
    }
 
    @Bean(name = "test1SqlSessionTemplate")
    @Primary
    public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
           

分庫規則 

/**
 * @Auther: Tinko
 * @Date: 2018/12/19 16:31
 * @Description: 分庫規則
 */
public class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Long> {
 
    @Override
    public String doEqualSharding(Collection<String> databaseNames, ShardingValue<Long> shardingValue) {
        for (String each : databaseNames) {
            if (each.endsWith(Long.parseLong(shardingValue.getValue().toString()) % 2 + "")) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }
 
    @Override
    public Collection<String> doInSharding(Collection<String> databaseNames, ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(databaseNames.size());
        for (Long value : shardingValue.getValues()) {
            for (String tableName : databaseNames) {
                if (tableName.endsWith(value % 2 + "")) {
                    result.add(tableName);
                }
            }
        }
        return result;
    }
 
    @Override
    public Collection<String> doBetweenSharding(Collection<String> databaseNames, ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(databaseNames.size());
        Range<Long> range = (Range<Long>) shardingValue.getValueRange();
        for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
            for (String each : databaseNames) {
                if (each.endsWith(i % 2 + "")) {
                    result.add(each);
                }
            }
        }
        return result;
    }
}
           

分表規則 

/**
 * @Auther: Tinko
 * @Date: 2018/12/19 16:30
 * @Description: 分表規則
 */
public class ModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> {
 
    @Override
    public String doEqualSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
        for (String each : tableNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }
 
    @Override
    public Collection<String> doInSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(tableNames.size());
        for (Long value : shardingValue.getValues()) {
            for (String tableName : tableNames) {
                if (tableName.endsWith(value % 2 + "")) {
                    result.add(tableName);
                }
            }
        }
        return result;
    }
 
    @Override
    public Collection<String> doBetweenSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(tableNames.size());
        Range<Long> range = (Range<Long>) shardingValue.getValueRange();
        for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
            for (String each : tableNames) {
                if (each.endsWith(i % 2 + "")) {
                    result.add(each);
                }
            }
        }
        return result;
    }
}
           

 controller

@RestController
public class UserController {
	
	@Autowired
	private UserMapper userMapper;

	/**
	 * 新增使用者資訊
	 * @param user
	 */
	@RequestMapping("/add")
	public Object add(User user) throws SQLException{
		System.out.println(user.toString());
		return userMapper.insert(user);
	}

	/**
	 * 根據使用者id查詢使用者資訊
	 * @param id 使用者id
	 */
	@RequestMapping("/select")
	public Object select(Integer id) throws SQLException{
		return userMapper.select(id);
	}

}
           

entity

@Data
public class User {
    private Long id;
    private Long order_id;
    private Long user_id;
    private String name;
    private String address;
}
           

mapper

public interface UserMapper {
    Long insert(User user);
    List<Map<String, Object>> select(@Param("id")Integer id);
}
           

mapper.xml

springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mapper.UserMapper" >

    <insert id="insert" parameterType="com.entity.User" >
        -- 表名不要寫字尾,字尾由sharding-jdbc根據政策生成
        INSERT INTO  user
        (order_id,user_id,name,address)
        VALUES
        (#{order_id},#{user_id},#{name}, #{address})
    </insert>

    <select id="select" parameterType="map" resultType="map">
        -- 表名不要寫字尾,字尾由sharding-jdbc根據政策生成
        select * from user where id = #{id}
    </select>
 
</mapper>
           

庫表結構

建立test_0、test_1庫,兩個庫分别導入以下user_0、user_1表結構

DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` varchar(100) DEFAULT NULL COMMENT '用來分表政策',
  `user_id` varchar(100) DEFAULT NULL COMMENT '用來分庫政策',
  `name` varchar(100) DEFAULT NULL,
  `address` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for user_1
-- ----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` varchar(100) DEFAULT NULL COMMENT '用來分表政策',
  `user_id` varchar(100) DEFAULT NULL COMMENT '用來分庫政策',
  `name` varchar(100) DEFAULT NULL,
  `address` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
           

單庫多表測試

倆庫四個表:

springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作
springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作

1. 在多次調用/insert解決存儲資料庫,檢視資料庫會發現:test_0庫中的user_0、user_1表中的資料是均攤存放的

springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作
springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作
springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作
springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作

2. 調用/select接口傳入id,擷取到資料

springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作
springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作

多庫多表測試

以下查到的資料是存在test_1庫的user_1表中

springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作

分析庫表資料,不難發現所配置的存儲/查詢規律

test_0庫

springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作
springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作

test_1庫

springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作

結論:

根據上圖分析不難發現sharding-jdbc分庫分表規則,

首先根據指定字段進行分庫,落實庫索引後,第二步才是分表,

分庫規則:指定分庫字段 % 2 = 餘數   >>> 拿到餘數後,拼接庫名,如:餘數為0的話拼接test庫名就得到test_0。

分表規則:指定分表字段 % 2 = 餘數  >>> 拿到餘數後,拼接表名,如:餘數為1的話拼接user表名就得到user_1。

注:指定分庫、分表的字段和取模數值可在以上的(分庫分表規則)标題中配置。

limit 分頁操作

官網:歸并引擎 :: ShardingSphere

springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作
springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作
springboot整合sharding-jdbc分庫分表介紹springboot整合sharding-jdbc分庫分表分析庫表資料,不難發現所配置的存儲/查詢規律結論:limit 分頁操作

繼續閱讀