Arrangement complet de la sous-base de données MySQL, de la table, de la partition et de la sphère de partitionnement

introduction:

  • De manière générale, si 单表la quantité de données dépasse 100 2000w%, la vitesse des requêtes sera très lente car la mémoire ne peut pas stocker son index, donc les requêtes SQL ultérieures généreront des E/S disque, entraînant une dégradation des performances.
  • Solution : mysql 分区,分表处理

Sous-bibliothèque et sous-table :

  • Raison : lorsque le niveau de données atteint une certaine échelle, lorsque la concurrence est trop élevée et que le nombre de connexions à la base de données n'est pas suffisant
  • Objectif : Diviser une table en N tables, contrôler la plage de données de chaque table et garantir les performances SQL. Il est recommandé que la quantité de données ne dépasse pas500W

concept:

  • Découpage vertical de la bibliothèque : découpage de la bibliothèque par métier, différentes bases de données pour différents métiers
  • Fendez la montre avec un marteau : divisez la grande montre en petite montre
  • Division horizontale : répartissez les données dans différentes tables selon les normes de dimension et stockez-les discrètement ; ou partitionnez, une table est divisée en différents fichiers disque en fonction du stockage des dimensions, et la table n'en fait toujours qu'une.
  • Séparation de la lecture et de l'écriture : la requête de données et le stockage des données sont séparés séparément.
    • Cela doit être mis en œuvre mysql主从复制de la même manière quesharding-spere插件整合

Implémentation de la partition MySQL :

  • La version est supérieure à mysql 5.1.3, après partitionnement, il s'agit toujours d'une table en surface, mais les données ont été hachées vers plusieurs emplacements.
  • Type de partition :
    • RANGEPartition, basée sur une plage continue donnée de valeurs de colonne, telle que la date, la taille numérique
    • LISTPartition, le type est un tableau de liste, si la valeur est incluse dans la plage de liste, elle appartient à la partition
    • HASHPartitionner, précisez le nombre de partitions, calculez les valeurs d'une ou plusieurs colonnes du tableau Hash(Key), puis répartissez-les sur différentes partitions.key对应列值为整数
    • KEYLe partitionnement, similaire au partitionnement par hachage, peut spécifier d'autres types de colonnes, à l'exception des BLOB et du Texte, comme clés de partition.
  • Précautions:
    • Lors du partitionnement, ne définissez pas la clé primaire ou ajoutez le champ de partition à la clé primaire.
    • Le champ de partition ne peut pas être NULL

SQL couramment utilisé pour le partitionnement :

-- 查询表分区
SELECT table_schema,table_name,partition_name,partition_ordinal_position,partition_method,partition_expression
 from information_schema.PARTITIONS
where table_schema = schema()
and table_name = '表名称'

-- 清除表分区,不清除数据
alter table dymc_from_input_info remove partitioning;

-- 定义 表 list 分区 ,表:dymc_from_input_info,字段:template_id
-- 这个业务是,当前表存储数据量很大,数据以模板id导入,可以按模板id分区,所有一个模板id一个分区
ALTER TABLE `dymc_from_input_info` PARTITION BY
LIST(template_id)(
    PARTITION p_1613559290235248642 VALUES IN (1613559290235248642),
    PARTITION p_1613910831752355842 VALUES IN (1613910831752355842),
    PARTITION p_1613910831752355843 VALUES IN (1613910831752355843)
);

-- 添加表list分区,在以有分区再添加list分区
alter table dymc_from_input_info add partition
(
PARTITION p_1 VALUES IN (1)
);

-- 添加 key分区,PARTITIONS 5, 是指定分区数为5
ALTER TABLE `dymc_from_input_info` PARTITION BY KEY(template_id) PARTITIONS 5;

-- 添加 hash分区
ALTER TABLE `dymc_from_input_info` PARTITION BY HASH(template_id) PARTITIONS 3;

-- 查询是否命中分区
EXPLAIN
select * from dymc_from_input_info where template_id=1613559290235248642

Stockage des fichiers de partition :

  • Si le moteur de stockage est InnoDB, .frm– fichiers pour la structure des tables, .ibdfichiers pour les données des tables et les index

Avant le partitionnement :

Insérer la description de l'image ici

Après partitionnement : le fichier .ibd est divisé en deux partitions ; 2 #p#分区名.ibdfichiers sont générés, plusieurs partitions et plusieurs fichiers ; stockés séparément

Insérer la description de l'image ici
Insérer la description de l'image ici

intégration de code

@ApiModel(value = "mysql表分区Vo")
@Data
public class MysqlPartitionVo implements Serializable {
    
    
    private static final long serialVersionUID = -4548301443478563468L;

    @ApiModelProperty(value = "库名称")
    private String tableSchema;

    @ApiModelProperty(value = "表名称")
    private String tableName;

    @ApiModelProperty(value = "分区名称")
    private String partitionName;

    @ApiModelProperty(value = "分区位置")
    private String partitionOrdinalPosition;

    @ApiModelProperty(value = "分区类型")
    private String partitionMethod;

    @ApiModelProperty(value = "分区字段")
    private String partitionExpression;

}
public interface PartitionMapper {
    
    

    /**
     * 查询mysql 对应表-分区列表
     * @param tableName 表名称
     * @return List<MysqlPartitionVo>
     */
    List<MysqlPartitionVo> getPartitionByTable(@Param("tableName") String tableName);

    /**
     * 删除对应表分区,保留分区
     * @param tableName 表名称
     * @return Boolean
     */
    void removePartitionByTable(@Param("tableName") String tableName);

}
<?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.PartitionMapper">

    <update id="removePartitionByTable">
        alter table ${
    
    tableName} remove partitioning;
    </update>


    <select id="getPartitionByTable" resultType="com.vo.mysql.MysqlPartitionVo">
        SELECT table_schema,table_name,partition_name,partition_ordinal_position,partition_method,partition_expression
        from information_schema.PARTITIONS
        where table_schema = schema()
        and table_name = #{
    
    tableName}
    </select>

</mapper>
/**
 * @author xiaoshu
 * @description mysql 分区处理
 * @date 2023年01月15日 18:53
 */
public interface PartitionService {
    
    

    /**
     *  初始化分区 表:dymc_from_input_info
     */
    void checkPartition();

    /**
     * 查询该模板是否存在分区,没有则创建
     * @param templateId 模板id
     * @return Boolean
     */
    Boolean checkExistTemplateId(Long templateId);
}
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.constant.CommonConstants;
import com.mapper.DymcFromInputInfoMapper;
import com.mapper.PartitionMapper;
import com.service.PartitionService;
import com.vo.mysql.MysqlPartitionVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xiaoshu
 * @description
 * @date 2023年01月15日 18:54
 */
@Slf4j
@Service
public class PartitionServiceImpl implements PartitionService {
    
    

    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;

    @Resource
    private Redisson redisson;

    @Resource
    private PartitionMapper partitionMapper;

    @Resource
    private DymcFromInputInfoMapper dymcFromInputInfoMapper;

    private static final String tableName="dymc_from_input_info";

    //初始化定义分区sql
    private static final String sql =" ALTER TABLE `%s` PARTITION BY\n" +
            "LIST(%s)(\n" +
            " %s "+
            "); ";

    //添加分区sql
    private static final String add_sql =" ALTER TABLE `%s` add partition( %s )";

    private static final String partitionSql="PARTITION %s VALUES IN (%s)";

    @Override
    public void checkPartition() {
    
    
        RLock redissonLock = redisson.getLock(CommonConstants.REDIS_LOCK+"partitionTash");
        try {
    
    
            redissonLock.lock();
            List<Long> templateIds = dymcFromInputInfoMapper.getTemplateIds();
            if (CollectionUtil.isEmpty(templateIds)){
    
    
                log.info("表单列详情没有数据,不建立分区");
            }else {
    
    
                int requiredSize = templateIds.size();
                log.info("需要分区数量:"+ requiredSize);
                //分区列表
                List<MysqlPartitionVo> partitionByTable = partitionMapper.getPartitionByTable(tableName);
                if (CollectionUtil.isNotEmpty(partitionByTable)){
    
    
                    //查询表对应分区数量
                    List<MysqlPartitionVo> partitionVos = partitionByTable.stream().filter(e -> StrUtil.isNotEmpty(e.getPartitionName())).collect(Collectors.toList());
                    int actualSize = partitionVos.size();
                    log.info("实际分区数量:"+ actualSize);
                    //分区为空
                    if (CollectionUtil.isEmpty(partitionVos)){
    
    
                        //需要分区数量 > 实际分区数量
                        log.info("初始化分区");
                        //拼接分区sql
                        StringBuilder partitionSql = getPartitionSql(templateIds);
                        initPartition(partitionSql);
                    }else {
    
    
                        //分区不为空
                        if (requiredSize>actualSize){
    
    
                            //添加分区
                            Map<String, String> templateMap = partitionByTable.stream().collect(Collectors.toMap(MysqlPartitionVo::getPartitionName, MysqlPartitionVo::getPartitionOrdinalPosition));
                            templateIds.forEach(e->{
    
    
                                String partitionName="p_" + e;
                                String existFlag = templateMap.get(partitionName);
                                //不存在分区,模板id
                                List<Long> unPartitionTemplate = new LinkedList<>();
                                if (StrUtil.isEmpty(existFlag)){
    
    
                                    unPartitionTemplate.add(e);
                                }
                                if (CollectionUtil.isNotEmpty(unPartitionTemplate)){
    
    
                                    log.info("添加分区数量:"+unPartitionTemplate.size());
                                    //拼接分区sql
                                    StringBuilder partitionSql = getPartitionSql(unPartitionTemplate);
                                    addPartition(partitionSql);
                                }
                            });
                        }
                    }
                }
                //清空表分区
                //partitionMapper.removePartitionByTable(tableName);
            }
        }catch (Exception e){
    
    
            e.printStackTrace();
        }finally {
    
    
            redissonLock.unlock();
        }
    }

    @Override
    public Boolean checkExistTemplateId(Long templateId) {
    
    
        //分区列表
        try {
    
    
            List<MysqlPartitionVo> partitionByTable = partitionMapper.getPartitionByTable(tableName);
            if (CollectionUtil.isNotEmpty(partitionByTable)){
    
    
                //查询表对应分区数量
                List<MysqlPartitionVo> partitionVos = partitionByTable.stream().filter(e -> StrUtil.isNotEmpty(e.getPartitionName())).collect(Collectors.toList());
                //分区不为空
                if (CollectionUtil.isNotEmpty(partitionVos)){
    
    
                    log.info("当前分区数量:"+partitionVos.size());
                    //已有分区map
                    Map<String, String> templatePartitionMap = partitionByTable.stream().collect(Collectors.toMap(MysqlPartitionVo::getPartitionName, MysqlPartitionVo::getPartitionOrdinalPosition));
                    String partitionName = templatePartitionMap.get(String.valueOf(templateId));
                    //如果不存在分区
                    if (StrUtil.isEmpty(partitionName)){
    
    
                        partitionName="p_"+templateId;
                        log.info("该分区不存在:"+partitionName);
                        StringBuilder partitionSql = getPartitionSql(Collections.singletonList(templateId));
                        //添加分区
                        addPartition(partitionSql);
                    }
                }else {
    
    
                    //分区为空
                    String partitionName = "p_"+templateId;
                    log.info("该分区不存在:"+partitionName);
                    StringBuilder partitionSql = getPartitionSql(Collections.singletonList(templateId));
                    //初始化分区
                    initPartition(partitionSql);
                }
                return Boolean.TRUE;
            }
        }catch (Exception e){
    
    
            return Boolean.FALSE;
        }
        return Boolean.FALSE;
    }


    /**
     * 拼接分区sql
     * @param templateIds 待添加分区模板id列表
     * @return partitionSql
     */
    private synchronized StringBuilder getPartitionSql(List<Long> templateIds) {
    
    
        List<String> partitionSqls = new LinkedList<>();
        //拼接分区sql
        for (Long templateId : templateIds) {
    
    
            String partitionName = String.format(partitionSql, "p_" + templateId, templateId);
            partitionSqls.add(partitionName);
        }
        StringBuilder partitionSql= new StringBuilder();
        for (int i = 0; i < partitionSqls.size(); i++) {
    
    
            if (i!=partitionSqls.size()-1){
    
    
                partitionSql.append(partitionSqls.get(i)).append(",");
            }else {
    
    
                partitionSql.append(partitionSqls.get(i));
            }
        }
        return partitionSql;
    }

    /**
     * 定义表分区
     * @param partitionSql 分区sql
     */
    private synchronized void initPartition(StringBuilder partitionSql) {
    
    
        Connection connection;
        Statement statement;
        String executeSql = String.format(sql, tableName, "template_id", partitionSql);
        try {
    
    
            connection = DriverManager.getConnection(url, username, password);
            statement = connection.createStatement();
            statement.execute(executeSql);
            log.info("分区添加成功");
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
    }
    /**
     * 添加表分区
     * @param partitionSql 分区sql
     */
    private synchronized void addPartition(StringBuilder partitionSql) {
    
    
        Connection connection;
        Statement statement;
        String executeSql = String.format(add_sql, tableName,partitionSql);
        try {
    
    
            connection = DriverManager.getConnection(url, username, password);
            statement = connection.createStatement();
            statement.execute(executeSql);
            log.info("分区添加成功");
        } catch (SQLException e) {
    
    
            e.printStackTrace();
        }
    }

}

concept de sphère de partitionnement

  • Apache ShardingSphereLa philosophie de conception est Database Plus, qui vise à créer des normes et une écologie pour la couche supérieure des bases de données hétérogènes.
  • ShardingSphere-JDBCPositionné comme un framework Java léger, fournissant des services supplémentaires au niveau de la couche JDBC de Java
  • ShardingSphere-ProxyPositionné comme un agent de base de données transparent, il assure le support des langages hétérogènes en implémentant le protocole binaire de base de données.
  • Site officiel : https://shardingsphere.incubator.apache.org/index_zh.html

organigramme :

Insérer la description de l'image ici

sharding-shpere implémente la séparation en lecture et en écriture :

  • Pour obtenir une séparation en lecture et en écriture, vous devez d'abord le configurer mysql的 主从复制, puis utiliser sharding-shpere pour obtenir une séparation en lecture et en écriture.

Configuration de la réplication maître-esclave MySQL :

  • La réplication maître-esclave (également appelée réplication AB) permet de répliquer les données d'un serveur de base de données MySQL (serveur maître) vers un ou plusieurs serveurs de base de données MySQL (serveurs esclaves).
  • 流程概念:Activez la fonction de journal binaire de la base de données et les enregistrements d'opérations de données (modifications de données) - "seront stockés dans le fichier binaire du journal binaire, signalés au fichier journal de relais (journal de relais) de la bibliothèque esclave via une connexion TCP et le SQL L'instruction sera réexécutée pour réaliser la synchronisation des données.
    Insérer la description de l'image ici

La configuration maître-esclave de Mysql prend 5.7.10 comme exemple :

  1. Modifiez le fichier de configuration de la base de données principale, /etc/my.cnf ; activez la fonction de journalisation binaire, puis redémarrez le serveur.
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M

## 同一局域网内注意要唯一
server-id=100  
## 开启二进制日志功能,可以随便取(关键)
log-bin=mysql-bin
## 复制过滤:不需要备份的数据库,不输出(mysql库一般不同步)
binlog-ignore-db=mysql
## 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed

validate_password_policy=0
validate_password_length=0

datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
  1. Assurez-vous que les services maître et esclave peuvent envoyer une requête ping et ouvrir le pare-feu.
  2. Assurer l'accès à distance
  3. mysql -uroot -p, connectez-vous à la base de données ; show master status;- Afficher l'état du fichier binaire
    Insérer la description de l'image ici
-- 修改远程访问 ,'%' 可为从服务器ip
use mysql;
update user set host = '%' where user = 'root';
FLUSH PRIVILEGES;
  1. Acceptez de modifier la configuration des données depuis MySQL, en vous assurantserver-id 不一致
  2. Exécutez la liaison SQL du serveur vers le serveur maître. master_log_file, master_log_pospuis show master status;commande pour afficher
change master to master_host='master服务器ip', master_user='root', 
master_password='master密码', master_port=3306, master_log_file='mysql-bin.000002',master_log_pos=2079;
  1. État de synchronisation des requêtes show slave status\G;
    Insérer la description de l'image ici
    Gestion des problèmes :
--建议处理:
stop slave;
--删除多余库
set global sql_slave_skip_counter=1;
start slave;
show slave status\G ;

Intégration de codes :

<!-- <sharding-sphere.version>4.0.0-RC1</sharding-sphere.version> -->

		<!--依赖sharding-->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>${sharding-sphere.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-core-common</artifactId>
            <version>${sharding-sphere.version}</version>
        </dependency>

Configuration de séparation en lecture et en écriture :

spring:
  #读写分离配置
  shardingsphere:
    # 参数配置,显示sql
    props:
      sql:
        show: true
    # 配置数据源
    datasource:
      # 给每个数据源取别名,下面的ds1,ds2,ds3任意取名字
      names: master,slave
      # 给master-ds1每个数据源配置数据库连接信息
      master:
        # 配置druid数据源
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.1.21:3306/sharding-test?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
        username: root
        password: 123456
        maxPoolSize: 100
        minPoolSize: 5
      # 配置slave
      slave:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding-test?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
        username: root
        password: 730730
        maxPoolSize: 100
        minPoolSize: 5
    # 配置默认数据源ds1
    sharding:
      # 默认数据源,主要用于写,注意一定要配置读写分离 ,注意:如果不配置,那么就会把三个节点都当做从slave节点,新增,修改和删除会出错。
      default-data-source-name: master
    # 配置数据源的读写分离,但是数据库一定要做主从复制
    masterslave:
      # 配置主从名称,可以任意取名字
      name: ms
      # 配置主库master,负责数据的写入
      master-data-source-name: master
      # 配置从库slave节点
      slave-data-source-names: slave
      # 配置slave节点的负载均衡均衡策略,采用轮询机制
      load-balance-algorithm-type: round_robin

Intégration réussie :

Insérer la description de l'image ici

Interroger la base de données esclave

Insérer la description de l'image ici

Écrire dans la bibliothèque principale

Insérer la description de l'image ici

Configurez le partage des données :

  • La notion de sous-table : Si usersla table est traitée, userselle 逻辑表n'existe pas réellement ;
    Insérer la description de l'image ici
  • Selon les règles configurées dans yml, la table users_1 ou users_2 est finalement atteinte.

configuration yml

  • Description de l'expression : ds$->{0..1}, l'alias de base de données nommé ci-dessus dans le code ds, 表达式的值si le sharding est atteint, la valeur de la $->{0..N}plage correspondante
spring:
  #数据分片配置
  shardingsphere:
    # 参数配置,显示sql
    props:
      sql:
        show: true
    # 配置数据源
    datasource:
      # 给每个数据源取别名,下面的ds1,ds2,ds3任意取名字
      names: ds0,ds1
      # 给master-ds1每个数据源配置数据库连接信息
      ds0:
        # 配置druid数据源
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.1.21:3306/sharding-test?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
        username: root
        password: 123456
        maxPoolSize: 100
        minPoolSize: 5
      # 配置ds2-slave
      ds1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding-test?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
        username: root
        password: 730730
        maxPoolSize: 100
        minPoolSize: 5
    # 配置默认数据源ds1
    sharding:
      # 默认数据源,主要用于写,注意一定要配置读写分离 ,注意:如果不配置,那么就会把三个节点都当做从slave节点,新增,修改和删除会出错。
      default-data-source-name: ds0
      # 配置分表的规则
      tables:
        # users 逻辑表名
        users:
          # 数据节点:数据源$->{0..N}.逻辑表名$->{0..N}
          actual-data-nodes: ds$->{
    
    0..1}.users$->{
    
    0..1}
          # 拆分库策略,也就是什么样子的数据放入放到哪个数据库中。
          database-strategy:
            inline:
              sharding-column: age    # 分片字段(分片键)
              algorithm-expression: ds$->{
    
    age % 2} # 分片算法表达式
          # 拆分表策略,也就是什么样子的数据放入放到哪个数据表中。
          table-strategy:
            inline:
              sharding-column: age    # 分片字段(分片键)
              algorithm-expression: users$->{
    
    age % 2} # 分片算法表达式

Lorsque l'âge des données = 20 est soumis, ds0 est atteint.
Insérer la description de l'image ici
Lorsque l'âge des données = 21 est soumis, ds1 est atteint.Insérer la description de l'image ici

Un partitionnement standard, par exemple par date, est requisimplements PreciseShardingAlgorithm ;

spring:
  #读写分离配置
  shardingsphere:
    # 参数配置,显示sql
    props:
      sql:
        show: true
    # 配置数据源
    datasource:
      # 给每个数据源取别名,下面的ds1,ds2,ds3任意取名字
      names: ds0,ds1
      # 给master-ds1每个数据源配置数据库连接信息
      ds0:
        # 配置druid数据源
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.1.21:3306/sharding-test?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
        username: root
        password: 123456
        maxPoolSize: 100
        minPoolSize: 5
      # 配置ds2-slave
      ds1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding-test?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
        username: root
        password: 730730
        maxPoolSize: 100
        minPoolSize: 5
    # 配置默认数据源ds1
    sharding:
      # 默认数据源,主要用于写,注意一定要配置读写分离 ,注意:如果不配置,那么就会把三个节点都当做从slave节点,新增,修改和删除会出错。
      default-data-source-name: ds0
      # 配置分表的规则
      tables:
        # users 逻辑表名
        users:
          # 数据节点:数据源$->{0..N}.逻辑表名$->{0..N}
          actual-data-nodes: ds$->{
    
    0..1}.users$->{
    
    0..1}
          # 拆分库策略,也就是什么样子的数据放入放到哪个数据库中。
          database-strategy:
            standard:
              sharding-column: birthday    # 分片字段(分片键)
              preciseAlgorithmClassName: com.config.BirthdayAlgorithm
          # 拆分表策略,也就是什么样子的数据放入放到哪个数据表中。
          table-strategy:
            inline:
              sharding-column: age    # 分片字段(分片键)
              algorithm-expression: users$->{
    
    age % 2} # 分片算法表达式

Écrivez des règles spécifiques :

Insérer la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/hesqlplus730/article/details/128714202
conseillé
Classement