# SpringBoot分库分表

# ShardingJDBC基于Mybatis单库分表

# 引入依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.0</version>
</dependency>
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.10</version>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

# yml配置

spring:
  shardingsphere:
    datasource:
      names: ds  # 数据源名称,唯一标识
      ds:
        type: com.zaxxer.hikari.HikariDataSource  # 数据源类型
        driver-class-name: com.mysql.cj.jdbc.Driver # 驱动名称
        jdbc-url: jdbc:mysql://localhost:3306/test_db_sharding?allowPublicKeyRetrieval=true&useSSL=false&autoReconnect=true&characterEncoding=utf8
        username: root
        password: 123456
    sharding:
      tables:
        tb_user:  # 要分库分表的名称
          actual-data-nodes: ds.tb_user_$->{0..1} # 数据节点 tb_user_0 tb_user_1
          table-strategy: # 分表策略
            inline: # 内联方式
              sharding-column: id # 切片的列
              algorithm-expression: tb_user_$->{id % 2} # 奇数在tb_user_1 偶数在tb_user_0
          key-generator: # 主键生成策略
            column: id # 主键列名
            type: SNOWFLAKE
            props:
              worker: # 工作节点为123
                id: 123
      binding-tables: tb_user
      
  mybatis:
    type-aliases-package: #实体对象包全限定名
    configuration:
      cache-enabled: true
      use-generated-keys: true
      default-executor-type: REUSE
      use-actual-param-name: true

# 注意事项

  1. 数据分片后,原有的数据库自动增长ID以及ORM层框架的配置不能再使用
  2. 使用SNOWFLAKE 雪花算法,64为LONG类型,所以需要设置相关字段为BIGINT
  3. 注意项目中springboot、jdk的版本号

# ShardingJDBC基于JPA单库分表

# 引入依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
<dependency>
    <groupId>com.github.wenhao</groupId>
    <artifactId>jpa-spec</artifactId>
    <version>3.1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

# yml配置

# sharding部分配置和前文mybatis方式相同
  jpa:
    open-in-view: false # 每个请求处理完毕关闭数据库连接
    generate-ddl: false # 一般在开发阶段使用,根据entity生成数据库的ddl
    show-sql: false # 控制台不显示sql语句
    properties: 
      hibernate:
        dialect: org.hibernate.dialect.MySQLDialect  # 数据库方言
        format_sql: true 
        use-new-id-generator-mappings: false # 新的主键映射策略

# 注意事项

  1. jpa方式要使用@Table标注表名 @Repository标注dao

# ShardingJSBD基于jpa读写分离

# 读写分离介绍

设计目标:让使用方像使用一个数据库一样使用主从数据库集群

读写分离则是根据SQL语义的分析,将读操作和写操作分别路由至主库与从库。

读写分离可以提升系统的吞吐量和可用性,但也带来了数据不一致的问题

# 引入依赖

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <dependency>
            <groupId>com.github.wenhao</groupId>
            <artifactId>jpa-spec</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.1</version>
        </dependency>

# yml配置

spring:
  shardingsphere:
    datasource:
      names: master,slave0 # 定义多个数据源
      master:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/test_db_sharding_master?allowPublicKeyRetrieval=true&useSSL=false&autoReconnect=true&characterEncoding=utf8
        username: test
        password: test
      slave0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/test_db_sharding_slave0?allowPublicKeyRetrieval=true&useSSL=false&autoReconnect=true&characterEncoding=utf8
        username: test
        password: test
    sharding:  # 分片
      tables:
        tb_user:
          database-strategy:
            inline:
              sharding-column: id
              algorithm-expression: master
          key-generator:
            column: id
            type: SNOWFLAKE
            props:
              worker:
                id: 123
 		# 其他表
    master-slave: #主从配置
        name: ms
        load-balance-algorithm-type: round_robin  # 负载均衡算法为轮询
        master-data-source-name: master # 主数据库名称
        slave-data-source-names: slave0 # 从数据库名称
    props:
      sql:
        show: true
  jpa:
    open-in-view: false
    generate-ddl: false
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQLDialect
        format_sql: true
        use-new-id-generator-mappings: false

# 注意事项

  1. 主库和从库的数据同步不是shardingJDBC做的,需要自行同步
  2. 查询操作会发生在从库,修改、添加,操作会发生在主库

原文链接 https://www.pdai.tech/md/spring/springboot/springboot-x-mysql-shardingjdbc-jpa-masterslave.html

# ShardingJDBC基于JPA的DB隔离

# 知识准备

  1. 逻辑表:水平拆分的数据库的相同逻辑和数据结构表的总称。例如订单数据有10张表,分别是t_order_0到t_order_9,逻辑表名为t_order

  2. 真实表:分片数据库中真实存在的物理表,t_order_0到t_order_9

  3. 数据节点: 数据源名称和数据表,例如ds_0.t_order_0

  4. 绑定表:分片规则一致的主表和子表,如t_order和t_order_item,均按照order_id分片

    • 绑定表之间的多表关联查询不会出现笛卡尔积
  5. 广播表: 分布式计算中,将小表的副本发送到集群的每个节点,以便提高访问效率。

  6. 分片键:用于分片的数据库字段

  7. 分片算法:精确分片算法(单字段)、范围分片算法、复合分片算法(多字段)、Hint分片算法

  8. 分片策略:标准分片策略、复合分片策略、行表达式分片策略(groovy表达式)、Hint分片策略

# yml配置

  shardingsphere:
    datasource:
      names: tenant-a,tenant-b
      tenant-a:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/test_db_tenant_a?allowPublicKeyRetrieval=true&useSSL=false&autoReconnect=true&characterEncoding=utf8
        username: root
        password: 123456
      tenant-b:
			...
    sharding:
      default-database-strategy:
        hint:
          algorithm-class-name: 
          	# hint算法全限定类名
      tables:
        tb_user:
          actual-data-nodes: tenant-${['a','b']}.tb_user
          key-generator:
			...
        tb_role:
          actual-data-nodes: tenant-${['a','b']}.tb_role
          key-generator:
			...
        tb_user_role:
          actual-data-nodes: tenant-${['a','b']}.tb_user_role
          key-generator:
			...
      binding-tables: tb_user,tb_role,tb_user_role
    props:
      sql:
        show: true

# 使用

@Aspect
@Order(1)
@Component
public class TenantDatasourceAspect {
    /**
     * 定义切点.
     */
    @Pointcut("execution(* tech.pdai.springboot.shardingjdbc.jpa.tenant.dbhint.dao.*.*(..))")
    public void useTenantDSPointCut() {
        // no impl
    }
    
    // 前置逻辑
    @Before("useTenantDSPointCut()")
    public void doDs0Before() {
        HintManager.clear();
        HintManager hintManager = HintManager.getInstance();
        // 实际环境将client信息放在xxxContext中(由ThreadLocal承接),并通过client-id来获取tenant.
        // 这里为了方便演示,只是使用了tenant-a
        hintManager.setDatabaseShardingValue("tenant-a");
    }

    // 后置逻辑
    @After("useTenantDSPointCut()")
    public void doDs0after() {
        HintManager.clear();
    }
}
Last Updated: 12/23/2024, 4:18:13 AM