Подтаблица подтаблицы базы данных SpringBoot 2.x ShardingSphere, фактический бой

Spring Boot
Подтаблица подтаблицы базы данных SpringBoot 2.x ShardingSphere, фактический бой

1. Требования к проекту

Когда я раньше работал над проектом, объем данных был относительно большим, а одна таблица исчислялась десятками миллионов, ее нужно было разделить на базы данных и таблицы, поэтому я искал в Интернете фреймворки с открытым исходным кодом в этой области. Самые распространенные это mycat и sharding-sphere.В итоге после того как я выбрал его проще использовать для создания подбиблиотеки и подтаблицы.

2. Введение в шардинг-сферу

Адрес официального сайта:shardingsphere.apache.org/

  • ShardingSphere — это экосистема промежуточного ПО для распределенных баз данных с открытым исходным кодом, состоящая из трех независимых продуктов: Sharding-JDBC, Sharding-Proxy и Sharding-Sidecar (планируется). Все они обеспечивают стандартизированное разделение данных, распределенные транзакции и функции управления базами данных, которые можно применять к различным сценариям приложений, таким как изоморфизм Java, гетерогенные языки, контейнеры и облачные среды.
  • ShardingSphere позиционируется как промежуточное ПО для реляционных баз данных, целью которого является полное и разумное использование вычислительных возможностей и возможностей хранения реляционных баз данных в распределенных сценариях, а не реализация новой реляционной базы данных. Это не является взаимоисключающим с NoSQL и NewSQL. NoSQL и NewSQL, являющиеся авангардом исследования новых технологий, настоятельно рекомендуются для того, чтобы смотреть в будущее и принимать изменения. И наоборот, вы также можете посмотреть на проблему другим способом мышления, заглянуть в будущее, обратить внимание на то, что не изменилось, а затем понять суть вещей. Реляционные базы данных по-прежнему занимают огромный рынок сегодня и являются краеугольным камнем основного бизнеса каждой компании. В будущем его будет трудно поколебать. На данном этапе нас больше беспокоит приращение на основе исходного фундамента, а не подрывная деятельность.

  • sharding-jdbc позиционируется как облегченная платформа Java, предоставляющая дополнительные услуги на уровне JDBC Java. Он использует клиент для прямого подключения к базе данных и предоставляет услуги в виде пакетов jar без дополнительного развертывания и зависимостей.Его можно понимать как расширенную версию драйвера JDBC, полностью совместимую с JDBC и различными ORM-фреймворками.
  • Работает с любой инфраструктурой ORM на основе Java, такой как: JPA, Hibernate, Mybatis, Spring JDBC Template или с использованием JDBC напрямую. На основе любого стороннего пула подключений к базе данных, например: DBCP, C3P0, BoneCP, Druid, HikariCP и т. д. Поддерживается любая база данных, реализующая спецификацию JDBC. В настоящее время поддерживаются MySQL, Oracle, SQLServer и PostgreSQL.

3. Спроектируйте реальный бой

В этом проекте используется шардинг-сфера + Mybatis-Plus для реализации подбазы данных и подтаблицы на основе Spring Boot 2.1.5.

1. pom.xml вводит зависимости

<?xml version="1.0" encoding="UTF-8"?>
<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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.xd</groupId>
    <artifactId>spring-boot-sharding-table</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-sharding-table</name>
    <description>基于 Spring Boot 2.1.5 使用sharding-sphere + Mybatis-Plus 实现分库分表</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--Mybatis-Plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.1</version>
        </dependency>
        <!--shardingsphere start-->
        <!-- for spring boot -->
        <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!-- for spring namespace -->
        <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-namespace</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!--shardingsphere end-->
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
        </dependency>
    </dependencies>

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

</project>

2. Создайте базу данных и таблицы

ds0
  ├── user_0 
  └── user_1 
ds1
  ├── user_0 
  └── user_1 

Поскольку это подбиблиотека и подтаблица, структура библиотеки и структура таблицы должны быть согласованы. База данных: ds0

CREATE DATABASE IF NOT EXISTS `ds0` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */;
USE `ds0`;

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user_0
-- ----------------------------
DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Table structure for user_1
-- ----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

SET FOREIGN_KEY_CHECKS = 1;

База данных: ds1

CREATE DATABASE IF NOT EXISTS `ds1` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */;
USE `ds1`;

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user_0
-- ----------------------------
DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- ----------------------------
-- Table structure for user_1
-- ----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

SET FOREIGN_KEY_CHECKS = 1;

3. application.properties (выделено)

# 数据源 ds0,ds1
sharding.jdbc.datasource.names=ds0,ds1
# 第一个数据库
sharding.jdbc.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/ds0?characterEncoding=utf-8
sharding.jdbc.datasource.ds0.username=root
sharding.jdbc.datasource.ds0.password=root

# 第二个数据库
sharding.jdbc.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
sharding.jdbc.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/ds1?characterEncoding=utf-8
sharding.jdbc.datasource.ds1.username=root
sharding.jdbc.datasource.ds1.password=root

# 水平拆分的数据库(表) 配置分库 + 分表策略 行表达式分片策略
# 分库策略
sharding.jdbc.config.sharding.default-database-strategy.inline.sharding-column=id
sharding.jdbc.config.sharding.default-database-strategy.inline.algorithm-expression=ds$->{id % 2}

# 分表策略 其中user为逻辑表 分表主要取决于age行
sharding.jdbc.config.sharding.tables.user.actual-data-nodes=ds$->{0..1}.user_$->{0..1}
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.sharding-column=age
# 分片算法表达式
sharding.jdbc.config.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{age % 2}

# 主键 UUID 18位数 如果是分布式还要进行一个设置 防止主键重复
#sharding.jdbc.config.sharding.tables.user.key-generator-column-name=id

# 打印执行的数据库以及语句
sharding.jdbc.config.props..sql.show=true
spring.main.allow-bean-definition-overriding=true

На этот раз я использую метод файла конфигурации для реализации подбиблиотек и подтаблиц.
Приведенные выше инструкции по настройке:

пользователь логической таблицы

Общий термин для таблиц с одинаковой логикой и структурой данных для горизонтально разделенной базы данных (таблицы). Пример: Пользовательские данные разбиты на 2 таблицы в соответствии с мантиссом первичного ключа, а именно от user_0 до user_1, и их логическое имя таблицы — user.

реальный стол

Физические таблицы, которые фактически существуют в сегментированной базе данных. то есть от user_0 до user_1 в предыдущем примере

Алгоритм шардинга:

Алгоритм разделения подсказки
Соответствует HintShardingAlgorithm, который используется для обработки сценариев с использованием сегментирования строк Hint. Необходимо использовать с HintShardingStrategy.

Стратегия разделения:

стратегия сегментирования выражений строк Соответствует InlineShardingStrategy. Используя выражения Groovy, он обеспечивает поддержку операций сегментирования для = и IN в операторах SQL и поддерживает только один ключ сегмента. Для простого алгоритма сегментирования его можно использовать с помощью простой конфигурации, чтобы избежать громоздкой разработки кода Java, например: user_$->{id % 2} означает, что пользовательская таблица делится на две таблицы в соответствии с идентификатором по модулю 2, имя таблицы от user_0 до user_1.

Стратегия генерации первичного ключа с автоинкрементом

Путем генерации самоувеличивающегося первичного ключа на стороне клиента вместо собственного самоувеличивающегося первичного ключа базы данных распределенный первичный ключ не дублируется. Используйте UUID.randomUUID() для генерации распределенных первичных ключей. или СНЕЖИНКА

4. Класс сущности

package com.xd.springbootshardingtable.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import groovy.transform.EqualsAndHashCode;
import lombok.Data;
import lombok.experimental.Accessors;

/**
 * @Classname User
 * @Description 用户实体类
 * @Author 李号东 lihaodongmail@163.com
 * @Date 2019-05-26 17:24
 * @Version 1.0
 */
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("user")
public class User extends Model<User> {

    /**
     * 主键Id
     */
    private int id;

    /**
     * 名称
     */
    private String name;

    /**
     * 年龄
     */
    private int age;
}

5. слой дао

package com.xd.springbootshardingtable.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xd.springbootshardingtable.entity.User;

/**
 * user dao层
 * @author lihaodong
 */
public interface UserMapper extends BaseMapper<User> {

}

6. Сервисный уровень и класс реализации

UserService

package com.xd.springbootshardingtable.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.xd.springbootshardingtable.entity.User;

import java.util.List;

/**
 * @Classname UserService
 * @Description 用户服务类
 * @Author 李号东 lihaodongmail@163.com
 * @Date 2019-05-26 17:31
 * @Version 1.0
 */
public interface UserService extends IService<User> {

    /**
     * 保存用户信息
     * @param entity
     * @return
     */
    @Override
    boolean save(User entity);

    /**
     * 查询全部用户信息
     * @return
     */
    List<User> getUserList();
}



UserServiceImpl

package com.xd.springbootshardingtable.service.Impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xd.springbootshardingtable.entity.User;
import com.xd.springbootshardingtable.mapper.UserMapper;
import com.xd.springbootshardingtable.service.UserService;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Classname UserServiceImpl
 * @Description 用户服务实现类
 * @Author 李号东 lihaodongmail@163.com
 * @Date 2019-05-26 17:32
 * @Version 1.0
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Override
    public boolean save(User entity) {
        return super.save(entity);
    }

    @Override
    public List<User> getUserList() {
        return baseMapper.selectList(Wrappers.<User>lambdaQuery());
    }

}

####7. Класс управления тестом

package com.xd.springbootshardingtable.controller;

import com.xd.springbootshardingtable.entity.User;
import com.xd.springbootshardingtable.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @Classname UserController
 * @Description 用户测试控制类
 * @Author 李号东 lihaodongmail@163.com
 * @Date 2019-05-26 17:36
 * @Version 1.0
 */
@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/select")
    public List<User> select() {
        return userService.getUserList();
    }

    @GetMapping("/insert")
    public Boolean insert(User user) {
        return userService.save(user);
    }

}

4. Тест

Стартовый проект
Откройте браузер и посетите:

http://localhost:8080/insert?id=1&name=lhd&age=12
http://localhost:8080/insert?id=2&name=lhd&age=13
http://localhost:8080/insert?id=3&name=lhd&age=14
http://localhost:8080/insert?id=4&name=lhd&age=15

Затем выполните вставку данных и просмотрите журнал консоли:

В соответствии с алгоритмом и стратегией сегментирования разные идентификаторы и возрастные модули попадают в разные таблицы базы данных для достижения результата сегментирования и сегментирования.

Некоторые люди говорят, что мы должны делать, если мы наводим справки?На самом деле, это помогло нам сделать это хорошо. Откройте браузер, чтобы посетить:
http://localhost:8080/select

консольная печать:

Запросите результаты из двух таблиц в базе данных ds0 и двух таблиц в базе данных ds1, а затем верните нам агрегированные результаты.

Друг спросил меня перед тем, что количество данных в одной таблице достигает 10 млн. Если я хочу сделать горизонтальное деление, независимо от базы данных, это возможно?
Это вполне возможно, пока вы изменяете конфигурацию файла конфигурации, это очень гибко.

Вы также можете видеть в коде, что мой код бизнес-уровня такой же, как и обычная операция с одной таблицей, просто нужно ввести конфигурацию sh и логическую таблицу, чтобы сохранить существующие неудобства, используя ненавязчивый наш код может быть основан на исходном Можно сказать, что очень удобно менять

Как разделить чтение и запись и использовать в сочетании с подбазой данных и подтаблицей в более поздних обновлениях
адрес проекта:GitHub.com/l ИХ Аодонг 88…