ShardingSphere 之ShardingJDBC扩展功能:分片审计、数据加密、读写分离、广播表、绑定表

news2025/1/23 9:17:32

文章目录

      • 分片审计
      • 数据加密
      • 读写分离
      • 广播表
      • 绑定表

分片审计

开发者手册



分片审计功能是针对数据库分片场景下对执行的 SQL 语句进行审计操作。可以对我们要执行的sql进行拦截并进行审核。

目前ShardingSphere内置的分片审计算法只有一个,DML_SHARDING_CONDITIONS。他的功能是要求对逻辑表查询时,必须带上分片键。

# 分片审计规则: SQL查询必须带上分片键
spring.shardingsphere.rules.sharding.tables.sys_user.audit-strategy.auditor-names[0]=course_auditor

spring.shardingsphere.rules.sharding.auditors.course_auditor.type=DML_SHARDING_CONDITIONS



yml完整配置

server:
  port: 8084


spring:
  shardingsphere:
    props:
      # 打印shardingjdbc的日志  shardingsphere5之前的版本配置项是 spring.shardingsphere.props.sql.show,而这里是sql-show
      sql-show: true
    # 数据源配置
    datasource:
      # 虚拟库的名字,并指定对应的真实库
      names: hsdb0,hsdb1
      hsdb0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234
      hsdb1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234

    # 分布式序列算法配置
    rules:
      sharding:
        # 分片键生成策略
        key-generators:
          # 雪花算法,生成Long类型主键。
          # alg_snowflake为我们程序员自定义的字符串名字,可以更改
          alg_snowflake:
            type: COSID_SNOWFLAKE
            props:
              worker:
                id: 1
        # 分片算法
        sharding-algorithms:
          # 指定分库策略 按2取模方式  sys_user_db_alg是我们程序员自定义的字符串名字,可以更改
          sys_user_db_alg:
            type: MOD
            props:
              sharding-count: 2
          # 指定分表策略  sys_user_tbl_alg是我们自定义string 可以更改
          sys_user_tbl_alg:
            type: INLINE
            props:
              algorithm-expression: sys_user$->{((uid+1)%4).intdiv(2)+1}
        # 分片审计
        auditors:
          # sys_user_audit是我们自定义string 可以更改
          sys_user_audit:
            type: DML_SHARDING_CONDITIONS



        # 指定分布式主键生成策略
        tables:
          # sys_user为虚拟表名,可以更改,但需要和实体类中的表名对应上
          sys_user:
            # 配置实际分片节点 $->{1..2}表达式的功能就是[1,2]  hsdb0.sys_user1  hsdb0.sys_user2  hsdb1.sys_user1  hsdb1.sys_user2
            actual-data-nodes: hsdb$->{0..1}.sys_user$->{1..2}
            # 指定虚拟表的分片键,以及分片键的生成策略
            key-generate-strategy:
              # 指定分片建为 uid 这个是和数据表中的字段对应的
              column: uid
              # 指定分片键字段的生成策略, alg_snowflake 也就是我们上面自定义的雪花算法
              key-generator-name: alg_snowflake
            # 配置分库策略,按uid字段取模
            database-strategy:
              standard:
                sharding-column: uid
                sharding-algorithm-name: sys_user_db_alg
            # 指定分表策略  standard-按单一分片键进行精确或范围分片
            table-strategy:
              standard:
                sharding-column: uid
                sharding-algorithm-name: sys_user_tbl_alg
            # 开启分片审计功能
            audit-strategy:
              # 指定分片审计是sys_user_audit
              auditorNames[0]: sys_user_audit

在这里插入图片描述



因为我上方的配置文件中是使用uid进行的分片键,我现在查询如果不带uid就会报错

@Test
public void testInline(){
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//  queryWrapper.eq("uid", 1819587788580864004L);
    List<User> users = userMapper.selectList(queryWrapper);
    System.out.println(users);
}




在这里插入图片描述



数据加密

官方开发手册

我们可以对真实表中的某个字段进行加密保存

全限定类名org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm

配置标识详细说明全限定类名
MD5基于 MD5 的数据加密算法org.apache.shardingsphere.encrypt.algorithm.MD5EncryptAlgorithm.java
AES基于 AES 的数据加密算法org.apache.shardingsphere.encrypt.algorithm.AESEncryptAlgorithm.java
RC4基于 RC4 的数据加密算法org.apache.shardingsphere.encrypt.algorithm.RC4EncryptAlgorithm.java
SM3基于 SM3 的数据加密算法org.apache.shardingsphere.encrypt.sm.algorithm.SM3EncryptAlgorithm.java
SM4基于 SM4 的数据加密算法org.apache.shardingsphere.encrypt.sm.algorithm.SM4EncryptAlgorithm.java
# 数据加密:对password字段进行加密
# 存储明文的字段,逻辑列名需要和java实体类中操作的列名对应上, value是真实数据表中的列名
spring.shardingsphere.rules.encrypt.tables.逻辑表名.columns.逻辑列名.plainColumn = password
# 存储密文的字段
spring.shardingsphere.rules.encrypt.tables.逻辑表名.columns.逻辑列名.cipherColumn = password_cipher
# 加密器  sys_user_password_encry为我们自定义加密器
spring.shardingsphere.rules.encrypt.tables.逻辑表名.columns.逻辑列名.encryptorName = sys_user_password_encry
# AES加密器
#spring.shardingsphere.rules.encrypt.encryptors.sys_user_password_encry.type=AES
#spring.shardingsphere.rules.encrypt.encryptors.sys_user_password_encry.props.aes-key-value=123456
# MD5加密器
#spring.shardingsphere.rules.encrypt.encryptors.sys_user_password_encry.type=MD5
# SM3加密器
spring.shardingsphere.rules.encrypt.encryptors.sys_user_password_encry.type=SM3
spring.shardingsphere.rules.encrypt.encryptors.sys_user_password_encry.props.sm3-salt=12345678

# sm4加密器
#spring.shardingsphere.rules.encrypt.encryptors.sys_user_password_encry.type=SM4



完整yml配置

server:
  port: 8084


spring:
  shardingsphere:
    props:
      # 打印shardingjdbc的日志  shardingsphere5之前的版本配置项是 spring.shardingsphere.props.sql.show,而这里是sql-show
      sql-show: true
    # 数据源配置
    datasource:
      # 虚拟库的名字,并指定对应的真实库
      names: hsdb0,hsdb1
      hsdb0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234
      hsdb1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234

    # 分布式序列算法配置
    rules:
      sharding:
        # 分片键生成策略
        key-generators:
          # 雪花算法,生成Long类型主键。
          # alg_snowflake为我们程序员自定义的字符串名字,可以更改
          alg_snowflake:
            type: COSID_SNOWFLAKE
            props:
              worker:
                id: 1
        # 分片算法
        sharding-algorithms:
          # 指定分库策略 按2取模方式  sys_user_db_alg是我们程序员自定义的字符串名字,可以更改
          sys_user_db_alg:
            type: MOD
            props:
              sharding-count: 2
          # 指定分表策略  sys_user_tbl_alg是我们自定义string 可以更改
          sys_user_tbl_alg:
            type: INLINE
            props:
              algorithm-expression: sys_user$->{((uid+1)%4).intdiv(2)+1}

        # 指定分布式主键生成策略
        tables:
          # sys_user为虚拟表名,可以更改,但需要和实体类中的表名对应上
          sys_user:
            # 配置实际分片节点 $->{1..2}表达式的功能就是[1,2]  hsdb0.sys_user1  hsdb0.sys_user2  hsdb1.sys_user1  hsdb1.sys_user2
            actual-data-nodes: hsdb$->{0..1}.sys_user$->{1..2}
            # 指定虚拟表的分片键,以及分片键的生成策略
            key-generate-strategy:
              # 指定分片建为 uid 这个是和数据表中的字段对应的
              column: uid
              # 指定分片键字段的生成策略, alg_snowflake 也就是我们上面自定义的雪花算法
              key-generator-name: alg_snowflake
            # 配置分库策略,按uid字段取模
            database-strategy:
              standard:
                sharding-column: uid
                sharding-algorithm-name: sys_user_db_alg
            # 指定分表策略  standard-按单一分片键进行精确或范围分片
            table-strategy:
              standard:
                sharding-column: uid
                sharding-algorithm-name: sys_user_tbl_alg

      # 定义加密器
      encrypt:
        encryptors:
          # sys_user_password_encry为我们自定义string 可以更改
          sys_user_password_encry:
            type: SM3
            props:
              sm3-salt: 12345678
        tables:
          # 逻辑表名
          sys_user:
            columns:
              # 逻辑列名
              password:
                # 这下面的password就是加密之后的密文保存在数据表的哪一个字段中
                cipher-column: password
                encryptor-name: sys_user_password_encry

在这里插入图片描述



进行插入测试

@Test
public void testAdd(){
    for (int i = 0; i < 10; i++) {
        User user = new User();
        user.setUsername("husahng" + i);
        user.setPassword("123456");
        user.setName("name");
        user.setDescription("描述信息");
        user.setStatus(1);
        userMapper.insert(user);
    }
}



从日志信息就能看出来这里进行了加密

在这里插入图片描述

在这里插入图片描述



查询测试

@Test
public void testInline(){
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("uid", 1026796515198238724L);
    queryWrapper.eq("password", "123456");
    List<User> users = userMapper.selectList(queryWrapper);
    System.out.println(users);
}



打印日志信息

# 逻辑表查询
Logic SQL: SELECT  uid,username,password,name,description,status,create_time,update_time  FROM sys_user WHERE (uid = ? AND password = ?)

# sql路由之后的分片查询
Actual SQL: hsdb0 ::: SELECT  uid,username,password AS password,name,description,status,create_time,update_time  FROM sys_user1 
WHERE (uid = ? AND password = ?) ::: [1026796515198238724, 950d9aac597a86c9df5f35e5055ea5e7e92364a9983fd37a057e39a8c9894239]

# 输出结果
[User(uid=1026796515198238724, username=husahng3, password=950d9aac597a86c9df5f35e5055ea5e7e92364a9983fd37a057e39a8c9894239, name=name, description=描述信息, status=1, createTime=Sun Aug 04 10:02:46 CST 2024, updateTime=Sun Aug 04 10:02:46 CST 2024)]



读写分离

开发者手册

在ShardingSphere中,实现读写分离也非常简单。只需要创建一个类型为readwrite-splitting的分片规则即可。

下方案例就使用sharding_sphere1和sharding_sphere2数据库中的sys_user1数据表进行读写分离的测试



移除数据分片相关的策略,添加读写分离的配置

#-----------------------配置读写分离
# 要配置成读写分离的虚拟库
spring.shardingsphere.rules.sharding.tables.逻辑表名.actual-data-nodes=readwrite-splitting的逻辑库.真实表名
# 配置读写分离虚拟库 主库一个,从库多个  下方的逻辑库名就和上方readwrite-splitting的逻辑库名对应上  hsdb0是上文中配置的普通逻辑库名
spring.shardingsphere.rules.readwrite-splitting.data-sources.逻辑库名.static-strategy.write-data-source-name=hsdb0
spring.shardingsphere.rules.readwrite-splitting.data-sources.逻辑库名.static-strategy.read-data-source-names[0]=hsdb1
# 指定负载均衡器
spring.shardingsphere.rules.readwrite-splitting.data-sources.逻辑库名.load-balancer-name=自定义负载均衡器名
# 配置负载均衡器
# 按操作轮训
spring.shardingsphere.rules.readwrite-splitting.load-balancers.自定义负载均衡器名.type=ROUND_ROBIN
# 按事务轮训
#spring.shardingsphere.rules.readwrite-splitting.load-balancers.user_lb.type=TRANSACTION_ROUND_ROBIN
# 按操作随机
#spring.shardingsphere.rules.readwrite-splitting.load-balancers.user_lb.type=RANDOM
# 按事务随机
#spring.shardingsphere.rules.readwrite-splitting.load-balancers.user_lb.type=TRANSACTION_RANDOM
# 读请求全部强制路由到主库
#spring.shardingsphere.rules.readwrite-splitting.load-balancers.user_lb.type=FIXED_PRIMARY

完整配置如下

server:
  port: 8084


spring:
  shardingsphere:
    props:
      # 打印shardingjdbc的日志  shardingsphere5之前的版本配置项是 spring.shardingsphere.props.sql.show,而这里是sql-show
      sql-show: true
    # 数据源配置
    datasource:
      # 虚拟库的名字,并指定对应的真实库
      names: hsdb0,hsdb1
      hsdb0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234
      hsdb1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234

    # 分布式序列算法配置
    rules:
      sharding:
        # 分片键生成策略
        key-generators:
          # 雪花算法,生成Long类型主键。
          # alg_snowflake为我们程序员自定义的字符串名字,可以更改
          alg_snowflake:
            type: COSID_SNOWFLAKE
            props:
              worker:
                id: 1

        # 指定分布式主键生成策略
        tables:
          # sys_user为虚拟表名,可以更改,但需要和实体类中的表名对应上
          sys_user:
            # 配置实际分片节点 改为 要配置成读写分离的虚拟库  hsuserdb为读写分离虚拟库    sys_user1为真实表
#            actual-data-nodes: hsdb$->{0..1}.sys_user$->{1..2}
            actual-data-nodes: hsuserdb.sys_user1
            # 指定虚拟表的分片键,以及分片键的生成策略
            key-generate-strategy:
              # 指定分片建为 uid 这个是和数据表中的字段对应的
              column: uid
              # 指定分片键字段的生成策略, alg_snowflake 也就是我们上面自定义的雪花算法
              key-generator-name: alg_snowflake
      readwrite-splitting:
        # 配置负载均衡器
        load-balancers:
          # sys_user_lb为自定义string 可以更改
          sys_user_lb:
            type: ROUND_ROBIN
        # 配置读写分离数据库
        data-sources:
          hsuserdb:
            # 指定负载均衡器
            load-balancer-name: sys_user_lb
            # 使用静态策略
            static-strategy:
              # 指定一个写库  可以指定多个从库,如果有多个从库就会使用上方的负载均衡器
              write-data-source-name: hsdb0
              read-data-source-names[0]: hsdb1



在这里插入图片描述



测试写入操作

@Test
public void testAdd(){
    for (int i = 0; i < 10; i++) {
        User user = new User();
        user.setUsername("husahng" + i);
        user.setPassword("123456");
        user.setName("name");
        user.setDescription("描述信息");
        user.setStatus(1);
        userMapper.insert(user);
    }
}



数据全都写入到了sharding_sphere1数据库的sys_user1数据表中了

在这里插入图片描述



测试查询操作

@Test
public void testInline(){
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    List<User> users = userMapper.selectList(queryWrapper);
    System.out.println(users);
}

打印日志,从打印日志就可以发现,这里的查询只会去hsdb1数据库进行读取

Logic SQL: SELECT  uid,username,password,name,description,status,create_time,update_time  FROM sys_user

Actual SQL: hsdb1 ::: SELECT  uid,username,password,name,description,status,create_time,update_time  FROM sys_user1



广播表

广播表表指所有的分片数据源中都存在的表,表结构及其数据在每个数据库中均完全一致。适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表。示例如下:

CREATE TABLE `sharding_sphere1`.`dict`  (
                                    `dictId` bigint(0) NOT NULL,
                                    `dictkey` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
                                    `dictVal` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
                                    PRIMARY KEY (`dictId`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

CREATE TABLE `sharding_sphere2`.`dict`  (
                                    `dictId` bigint(0) NOT NULL,
                                    `dictkey` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
                                    `dictVal` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
                                    PRIMARY KEY (`dictId`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;



创建实体

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("dict")
public class Dict {
    private Long dictid;
    private String dictkey;
    private String dictval;
}



创建Mapper

@Mapper
public interface DictMapper extends BaseMapper<Dict> {
}



主要核心配置为最后一行

# 分布式主键生成类型
spring.shardingsphere.rules.sharding.key-generators.自定义主键生成策略名.type=COSID_SNOWFLAKE
# 指定分布式主键生成策略
spring.shardingsphere.rules.sharding.tables.虚拟表名.key-generate-strategy.column=主键字段 或者是 分片字段名
spring.shardingsphere.rules.sharding.tables.虚拟表名.key-generate-strategy.key-generator-name=自定义主键生成策略名
#-----------------------配置读写分离
# 指定虚拟表访问的虚拟库与真实表
spring.shardingsphere.rules.sharding.虚拟表名.dict.actual-data-nodes=m$->{0..1}.dict

# 指定广播表。广播表会忽略分表的逻辑,只往多个库的同一个表中插入数据。 这里要和上方的虚拟表名对应上
spring.shardingsphere.rules.sharding.broadcast-tables=dict



完整的yml配置

server:
  port: 8084


spring:
  shardingsphere:
    props:
      # 打印shardingjdbc的日志  shardingsphere5之前的版本配置项是 spring.shardingsphere.props.sql.show,而这里是sql-show
      sql-show: true
    # 数据源配置
    datasource:
      # 虚拟库的名字,并指定对应的真实库
      names: hsdb0,hsdb1
      hsdb0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234
      hsdb1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234

    # 分布式序列算法配置
    rules:
      sharding:
        # 分片键生成策略
        key-generators:
          # 雪花算法,生成Long类型主键。 alg_snowflake为我们程序员自定义的字符串名字,可以更改
          alg_snowflake:
            type: COSID_SNOWFLAKE
            props:
              worker:
                id: 1

        # 指定分布式主键生成策略
        tables:
          # dict虚拟表名,可以更改,但需要和实体类中的表名对应上
          dict:
            # 配置实际分片节点
            actual-data-nodes: hsdb$->{0..1}.dict
            # 指定虚拟表的分片键,以及分片键的生成策略
            key-generate-strategy:
              column: dictid
              # 指定分片键字段的生成策略, alg_snowflake 也就是我们上面自定义的雪花算法
              key-generator-name: alg_snowflake

        # 指定广播表 dict要和上方的虚拟表名对应上
        broadcast-tables[0]: dict

在这里插入图片描述



新增测试

@Test
public void testAdd(){
    Dict dict = new Dict();
    dict.setDictkey("name");
    dict.setDictval("hushang");
    dictMapper.insert(dict);
}

打印日志如下,这里会往两个数据库都进行插入操作

Logic SQL: INSERT INTO dict  ( dictkey,dictval )  VALUES  ( ?,? )

Actual SQL: hsdb0 ::: INSERT INTO dict  ( dictkey,dictval , dictid)  VALUES  (?, ?, ?) ::: [name, hushang, 1026819603256311809]
Actual SQL: hsdb1 ::: INSERT INTO dict  ( dictkey,dictval , dictid)  VALUES  (?, ?, ?) ::: [name, hushang, 1026819603256311809]



绑定表

绑定表指分片规则一致的一组分片表。 就比如两个数据表都使用的同一个关联字段作为分片键

使用绑定表进行多表关联查询时,必须使用分片键进行关联,否则会出现笛卡尔积关联或跨库关联,从而影响查询效率。

此时我们已经有两用户表,我们再来为sys_user数据表创建一个关联表用户信息表

在这里插入图片描述

创建实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user_info")
public class UserInfo {
    private Long ifid;
    private Long uid;
    private String userinfo;
}

Mapper接口

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}



yml配置内容如下

server:
  port: 8084


spring:
  shardingsphere:
    props:
      # 打印shardingjdbc的日志  shardingsphere5之前的版本配置项是 spring.shardingsphere.props.sql.show,而这里是sql-show
      sql-show: true
    # 数据源配置
    datasource:
      # 虚拟库的名字,并指定对应的真实库
      names: hsdb0
      hsdb0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234

    # 分布式序列算法配置
    rules:
      sharding:
        # 分片键生成策略
        key-generators:
          # 雪花算法,生成Long类型主键。 alg_snowflake为我们程序员自定义的字符串名字,可以更改
          alg_snowflake:
            type: COSID_SNOWFLAKE
            props:
              worker:
                id: 1
        sharding-algorithms:
          # 定义sys_user的分表策略
          sys_user_tab_alg:
            type: INLINE
            props:
              algorithm-expression: sys_user$->{((uid+1)%4).intdiv(2)+1}
          # 定义user_info的分表策略
          user_info_tab_alg:
            type: INLINE
            props:
              algorithm-expression: user_info$->{((uid+1)%4).intdiv(2)+1}

        tables:
          # sys_user逻辑表的处理
          sys_user:
            # 配置实际分片节点
            actual-data-nodes: hsdb0.sys_user$->{1..2}
            # 分表策略
            table-strategy:
              standard:
                sharding-column: uid	
                sharding-algorithm-name: sys_user_tab_alg
          # user_info逻辑表的处理
          user_info:
            # 配置实际分片节点
            actual-data-nodes: hsdb0.user_info$->{1..2}
            # 配置主键生成策略
            key-generate-strategy:
              column: ifid
              key-generator-name: alg_snowflake
            # 分表策略
            table-strategy:
              standard:
                sharding-column: uid
                sharding-algorithm-name: user_info_tab_alg

在这里插入图片描述



进行插入操作

@Test
public void testAdd(){
    for (int i = 1; i <= 10; i++) {
        User user = new User();
        // uid 给两张表的关联字段进行赋值
        Long uid = (long)i;
        user.setUid(uid);
        user.setUsername("husahng" + i);
        user.setPassword("123456");
        user.setName("name");
        user.setDescription("描述信息");
        user.setStatus(1);
        userMapper.insert(user);

        for (int j = 0; j < 5; j++) {
            UserInfo userInfo = new UserInfo();
            userInfo.setUid(uid);
            userInfo.setUserinfo("test user info");
            userInfoMapper.insert(userInfo);
        }
    }
}



接下来再进行关联查询

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {

    @Select("select info.* from sys_user as u, user_info as info where u.uid = info.uid")
    List<UserInfo> queryUserInfo();
}

查看日志,我们就可以发现,这里竟然执行了四次sql。我两个数据表都是用的uid进行的分表,按理说一条uid数据要么同时在sys_user1 和 user_info1 数据表中,要么同时在sys_user2 和 user_info2 数据表中 根本就不需要进行四次sql执行。

Logic SQL: select info.* from sys_user as u, user_info as info where u.uid = info.uid

Actual SQL: hsdb0 ::: select info.* from sys_user1 as u, user_info1 as info where u.uid = info.uid
Actual SQL: hsdb0 ::: select info.* from sys_user1 as u, user_info2 as info where u.uid = info.uid
Actual SQL: hsdb0 ::: select info.* from sys_user2 as u, user_info1 as info where u.uid = info.uid
Actual SQL: hsdb0 ::: select info.* from sys_user2 as u, user_info2 as info where u.uid = info.uid

这种查询明显性能是非常低的,如果两张表的分片数更多,执行的SQL也会更多。而实际上,用户表和用户信息表,他们都是按照uid进行分片的,他们的分片规则是一致的。



这样,再把绑定关系加上,此时查询,就会按照相同的uid分片进行查询。

# 指定绑定表 ,这里使用的都是虚拟表名
spring.shardingsphere.rules.sharding.binding-tables[0]=sys_user,user_info

在这里插入图片描述

# 此时就只有两条sql执行了
Logic SQL: select info.* from sys_user as u, user_info as info where u.uid = info.uid

Actual SQL: hsdb0 ::: select info.* from sys_user1 as u, user_info1 as info where u.uid = info.uid
Actual SQL: hsdb0 ::: select info.* from sys_user2 as u, user_info2 as info where u.uid = info.uid





如果是下面这种分库分表的情况下

在这里插入图片描述

server:
  port: 8084


spring:
  shardingsphere:
    props:
      # 打印shardingjdbc的日志  shardingsphere5之前的版本配置项是 spring.shardingsphere.props.sql.show,而这里是sql-show
      sql-show: true
    # 数据源配置
    datasource:
      # 虚拟库的名字,并指定对应的真实库
      names: hsdb0,hsdb1
      hsdb0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234
      hsdb1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/sharding_sphere2?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: 1234

    # 分布式序列算法配置
    rules:
      sharding:
        # 分片键生成策略
        key-generators:
          # 雪花算法,生成Long类型主键。 alg_snowflake为我们程序员自定义的字符串名字,可以更改
          alg_snowflake:
            type: COSID_SNOWFLAKE
            props:
              worker:
                id: 1
        sharding-algorithms:
          # 定义分库策略  db_alg为自定义string 可以更改
          db_alg:
            type: MOD
            props:
              sharding-count: 2
          # 定义sys_user的分表策略
          sys_user_tab_alg:
            type: INLINE
            props:
              algorithm-expression: sys_user$->{((uid+1)%4).intdiv(2)+1}
          # 定义user_info的分表策略
          user_info_tab_alg:
            type: INLINE
            props:
              algorithm-expression: user_info$->{((uid+1)%4).intdiv(2)+1}

        tables:
          # sys_user逻辑表的处理
          sys_user:
            # 配置实际分片节点
            actual-data-nodes: hsdb$->{0..1}.sys_user$->{1..2}
            # 分库策略
            database-strategy:
              standard:
                sharding-column: uid
                sharding-algorithm-name: db_alg
            # 分表策略
            table-strategy:
              standard:
                sharding-column: uid
                sharding-algorithm-name: sys_user_tab_alg
          # user_info逻辑表的处理
          user_info:
            # 配置实际分片节点
            actual-data-nodes: hsdb$->{0..1}.user_info$->{1..2}
            # 配置主键生成策略
            key-generate-strategy:
              column: ifid
              key-generator-name: alg_snowflake
            # 分库策略
            database-strategy:
              standard:
                sharding-column: uid
                sharding-algorithm-name: db_alg
            # 分表策略
            table-strategy:
              standard:
                sharding-column: uid
                sharding-algorithm-name: user_info_tab_alg



未加关联表的查询

Logic SQL: select info.* from sys_user as u, user_info as info where u.uid = info.uid

Actual SQL: hsdb0 ::: select info.* from sys_user1 as u, user_info1 as info where u.uid = info.uid
Actual SQL: hsdb0 ::: select info.* from sys_user1 as u, user_info2 as info where u.uid = info.uid
Actual SQL: hsdb0 ::: select info.* from sys_user2 as u, user_info1 as info where u.uid = info.uid
Actual SQL: hsdb0 ::: select info.* from sys_user2 as u, user_info2 as info where u.uid = info.uid
Actual SQL: hsdb1 ::: select info.* from sys_user1 as u, user_info1 as info where u.uid = info.uid
Actual SQL: hsdb1 ::: select info.* from sys_user1 as u, user_info2 as info where u.uid = info.uid
Actual SQL: hsdb1 ::: select info.* from sys_user2 as u, user_info1 as info where u.uid = info.uid
Actual SQL: hsdb1 ::: select info.* from sys_user2 as u, user_info2 as info where u.uid = info.uid



添加关联表的查询

Logic SQL: select info.* from sys_user as u, user_info as info where u.uid = info.uid

Actual SQL: hsdb0 ::: select info.* from sys_user1 as u, user_info1 as info where u.uid = info.uid
Actual SQL: hsdb0 ::: select info.* from sys_user2 as u, user_info2 as info where u.uid = info.uid
Actual SQL: hsdb1 ::: select info.* from sys_user1 as u, user_info1 as info where u.uid = info.uid
Actual SQL: hsdb1 ::: select info.* from sys_user2 as u, user_info2 as info where u.uid = info.uid

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1978145.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

教您一键批量下载拼多多批发图片信息,节省时间

图片是电商的核心展示手段&#xff0c;高质量、吸引人的图片能显著提升商品吸引力&#xff0c;增强用户体验&#xff0c;促进购买决策。良好的视觉呈现有助于品牌形象的塑造&#xff0c;提高转化率和客户满意度&#xff0c;对电商平台的流量和销售业绩具有直接影响。 使用图快…

InnoDB锁机制

目录 第一节&#xff1a;锁的基本概念 1. 锁的定义与作用 2. Lock与Latch的区别 3. 锁的占有模式 4. 锁的类型 图文结合示例 Lock与Latch对比图 锁的占有模式兼容性图 锁的类型层次图 第二节&#xff1a;事务隔离级别与MVCC 事务隔离级别 MVCC&#xff08;多版本并发…

《机器人SLAM导航核心技术与实战》第1季:第8章_激光SLAM系统

视频讲解 【第1季】8.第8章_激光SLAM系统-视频讲解【第1季】8.1.第8章_激光SLAM系统_Gmapping算法-视频讲解【第1季】8.2.第8章_激光SLAM系统_Cartographer算法-视频讲解【第1季】8.3.第8章_激光SLAM系统_LOAM算法-视频讲解 第1季&#xff1a;第8章_激光SLAM系统 先 导 课第…

用2点结构标定3点结构的顺序

在行列可自由变换的平面上2点结构只有3个 (A,B)---6*30*2---(0,1)(1,0) 让A分别是2a1&#xff0c;2&#xff0c;3&#xff0c;让B全是0。当收敛误差为7e-4&#xff0c;收敛199次取迭代次数平均值&#xff0c;得到 结构 迭代次数 2a1 58742.717 1.00001 2a2 80796.605 1…

如何在uniapp上隐藏默认导航栏

当要定义导航栏&#xff0c;使用uni.switchTab来跳转页面时&#xff0c;需要将默认的导航栏进行隐藏。 比如使用 uni.hideTabBar(); 去隐藏的话&#xff0c;可能会有闪现出现的可能性。 我们可以在package.json当中的 tabBar加"custom": true。例: "tabBar&q…

【TS】TypeScript类型断言:掌握类型转换的艺术

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 TypeScript类型断言&#xff1a;掌握类型转换的艺术1. 引言2. 什么是类型断言&a…

基于特性价值来确认测试重点

目录 核心特性&#xff1a; 潜力特性&#xff1a; 噱头特性&#xff1a; 辅助特性&#xff1a; 无人问津的特性&#xff1a; 测试重点的确立&#xff1a; 软件的特性包含如下几种&#xff0c;核心特性&#xff0c;潜力特性&#xff0c;噱头特性&#xff0c;无人问津特性&…

Project Euler_Problem 277_A Modified Collatz Sequence

原题目&#xff1a; 题目大意&#xff1a; 一串字母可以视作迭代过程中每一轮除3余多少&#xff0c;问最小的大于1e15的满足那串序列的数是多大 解题思路&#xff1a;可以把那一大串字母&#xff0c;看作是不停地对初始数值x做连续运算&#xff0c;且每一轮运算的结果都应当是…

03:【stm32】GPIO

GPIO 1、芯片的引脚分布2、IO复用与重映射3、片上外设GPIO3.1、GPIO的寄存器组3.2、8种工作模式3.3、最大输出速度3.4、GPIO的内部结构 1、芯片的引脚分布 STM32F103C8T6这款芯片一共有48个引脚&#xff0c;他们分为了特殊功能引脚和普通的IO引脚。其中特殊功能的引脚有如下几个…

一键搬运TEMU、SHEIN店铺起新店。商品一键复制,商品裂变,TEMU商品复制

店铺搬家&#xff0c;一键搬运TEMU、SHEIN店铺起新店。商品一键复制&#xff0c;裂变新类目。铺店群必备 店铺搬家是什么&#xff1f; 店铺搬家就是将Temu一个店铺的所有商品快速搬到另一个店铺&#xff0c;只需要半个小时就能起一个全新的店铺&#xff0c;可以帮助商家快速起新…

comfyUI-MuseTalk的参数设置

comfyUI-MuseTalk的参数设置 目录 comfyUI-MuseTalk的参数设置 一、ComfyUI-VideoHelperSuite 二、comfyUI-MuseV合成的参考视频 2.1、什么时候会用到MuseV&#xff1f; 2.2、MuseV特别消耗系统内存 2.2.1、测试图片序列的像素比 2.2.2、影响运动范围和生成结果的参数 …

无法安装Python包,出现OSError: 拒绝访问错误

无法安装Python包&#xff0c;出现OSError: 拒绝访问错误 在安装Python包时&#xff0c;可能会遇到各种错误&#xff0c;其中“OSError: 拒绝访问”是一个比较常见的问题。这个错误通常表明在安装过程中&#xff0c;Python没有足够的权限去访问某个文件或目录。本文将深入探讨…

【LeetCode】45.跳跃游戏II

1. 题目 2. 分析 很久没有写贪心的题了&#xff0c;在这题上卡了很久时间&#xff0c;我这个还是不会贪心。 核心思想就一句话&#xff1a;维护在到达本次最远位置之前能达到的最远位置。每到边界时就更新步数&#xff0c;便得到正确答案。 3. 代码 class Solution:def jum…

微软商店无法加载,检查你的连接-解决方案

微软商店默认直连国内的服务器。 如果有代理&#xff0c;关闭代理就可以恢复网络了。 但是我就是想用代理&#xff0c;我感觉代理更快&#xff0c; 搜索了很多办法&#xff0c;都没有生效。 然后我在哔哩哔哩的视频下方&#xff0c;看到大家留言&#xff0c;测试了一下&#x…

Qt/C++项目积累: 2.主机监控器 - 2.3 实时数据及其他功能完善

相关链接&#xff1a; 链接1&#xff1a;Qt/C项目积累&#xff1a; 2.主机监控器 - 2.1 项目介绍-CSDN博客https://blog.csdn.net/qq_22122811/article/details/140254896 链接2&#xff1a;Qt/C项目积累&#xff1a; 2.主机监控器 - 2.2 历史功能实现-CSDN博客https://blog.…

ARM 架构硬件新趋势:嵌入式领域的未来

目录 目录 一、ARM 架构概述 二、新趋势一&#xff1a;AI 加速器集成 三、新趋势二&#xff1a;更高效的电源管理 四、新趋势三&#xff1a;安全性增强 五、结语 随着物联网 (IoT) 和边缘计算的发展&#xff0c;ARM 架构在嵌入式系统中的应用越来越广泛。从智能手机到智能…

STM32H7无RTOS应用堆栈机制与检测

摘要&#xff1a;单片机堆栈溢出会引发不可预知的错误。本文探讨了基于STM32CubeIDE设置STM32H7xx堆栈在无RTOS时的使用与检测方法。 一、堆栈的设置 STM32CubeIDE对工程设置堆栈很简单&#xff0c;在CubeMX中设置最小size如下图 堆&#xff08;Heap&#xff09;为0x400&#…

低空经济-低空智联网技术体系白皮书

目录 低空定义 低空政策 低空市场规模 低空应用场景 通信需求 监管需求 低空智联网技术体系 低空定义 低空经济是指在3000米以下&#xff0c;以低空空域为依托&#xff0c;以各种有人和无人驾驶航空器的低空飞行活动为牵引&#xff0c;辐射带动相关领域融合发展的综合性…

【MySQL是怎样运行的 | 第三篇】MySQL的MVCC机制

文章目录 3.MySQL的MVCC机制3.1前言3.2undo log日志3.3三个隐藏字段3.4undo log版本链3.5当前读VS快照读3.6ReadView3.7举例3.7.1RC&#xff08;读已提交&#xff09;3.7.2RR&#xff08;可重复读&#xff09; 3.8扩展&#xff1a;RR能解决幻读问题吗&#xff1f; 4.白云 3.MyS…

【Python系列】深入理解 Python 中的 `nonlocal` 关键字

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…