ShardingSphere

1.简介

  • 1.开源的分布式数据生态项目
    • ShardingSphere-JDBC:轻量级Java框架
    • ShardingSphere-Proxy:数据库代理
    • ShardingSphere-Sidecar(规划中):Kubernetes的云原生数据库代理
  • 2.使用版本:ShardingSphere5.1.1
  • 3.定位:关系型数据库中间件

1.数据库集群架构

  • 1.出现原因:单个数据库服务器无法满足海量数据加海量用户的业务需求
  • 2.解决方式:采用数据库集群架构提高应用程序的性能
  • 3.具体实现
    • 1.读写分离
    • 2.数据分片

1.读写分离

在这里插入图片描述
在这里插入图片描述

  • 1.原理:将数据库读写操作分散到不同的节点上,分散了数据库读写的压力
  • 2.主机:负责事务性的增删改操作;从机:负责查询操作
  • 3.读写分离机制建立在数据库主从复制的基础上,可参考MySQL文章中主从复制
  • 4.优点:通过读写分离可以有效避免数据更新导致的行锁,也可将查询负载均衡的分散到多个从机中,从而提高查询性能
  • 5.问题
    • 1.主机向从机复制数据的过程中会有时间的延迟,如果将数据写入主机,立即从从机读取数据,这时数据可能还未从主机完全复制到从机,所以会出现数据不一致问题,即CAP定理
    • 2.读写分离分散了数据库读写压力,但没有分散存储压力,为了业务数据存储的需求,需将存储分散到多台数据库服务器
1.CAP定理
  • 1.定义:分布式系统中,当涉及读写操作时,只能保证一致性(Consistence)可用性(Availability)分区容错性(Partition Tolerance)三者中的两个
    • 1.C一致性,对某个指定的客户端,读操作保证能够返回最新的写操作结果,即读写结果一致
    • 2.A可用性,非故障的节点在合理的时间内返回合理的响应(非错误和超时的响应)
    • 3.P分区容错性,当出现网络分区(多个服务器数据交换)后,系统能够继续履行职责(继续执行,可返回超时或历史数据)
  • 2.特点:实际设计过程中,每个系统不可能只处理一种数据,有的数据必须选择CP,有的数据必须选择AP,分布式系统理论上不可能选择CA
  • 3.CAP理论中的C在实践中不可能完美实现,数据复制的过程中,节点N1和节点N2的数据并不一致(强一致性);即使无法做到强一致性,但应用可以采用合适的方式达到最终一致性
    • 1.基本可用(Basically Available):分布式系统在出现故障时,允许损失部分可用性,保证核心可用
    • 2.软状态(Soft State):允许系统存在中间状态,该中间状态不会影响系统的整体可用性,这里的中间状态就是CAP理论中的数据不一致
    • 3.最终一致性(Eventual Consisitency),系统中的所有数据副本经过一定时间后,最终能够达到一致的状态
1.CP

在这里插入图片描述

  • 1.如图所示,为了保证一致性,当发生分区现象(丢包)后,N1节点上数据已经更新到y,但由于N1N2之间的复制通道中断,数据y无法同步到N2N2节点上的数据还是x
  • 2.此时客户端c访问N2时,N2需要返回Error,提示客户端C系统现在发生了错误,该处理方式违背了可用性的要求,此时CAP三者只能满足CP
2.AP

在这里插入图片描述

  • 1.如图所示,为了保证可用性,当发生分区现象后,N1节点上的数据已经更新到y,但由于N1N2之间的复制通道中断,数据y无法同步到N2N2节点上的数据还是x
  • 2.此时客户端C访问N2时,N2将当前自己拥有的数据x返回给客户端C,而实际当前最新的数据是y,不满足一致性的要求,此时CAP只能满足AP.

2.数据分片(分库分表)

  • 1.读写分离问题读写分离分散了数据库读写压力,从而缓解了单台服务器的访问压力,但没有分散存储压力,为了满足业务数据存储需求,需将存储分散到多台数据库服务器
  • 2.数据分片定义:将存放在单一数据库或表中的数据分散地存放至多个数据库或表中,以达到提升性能瓶颈以及可用性的效果
  • 3.数据分片的拆分方式
    • 1.垂直分片
    • 2.水平分片
  • 4.适用场景:《阿里开发手册》建议单表超过500万条记录或单表大小超过2GB需要考虑分库分表
    在这里插入图片描述
1.垂直分片
  • 1.定义:按照业务拆分的方式称为垂直分片/纵向拆分
  • 2.垂直分片可细分为
    • 1.垂直分库
    • 2.垂直分表
1.垂直分库

在这里插入图片描述
在这里插入图片描述

  • 1.定义:核心理念是专库专用
    • 1.拆分之前:一个数据库由多个数据表构成,每个表对应着不同的业务
    • 2.拆分之后:按照业务将表进行归类,分布到不同的专用数据库,从而将压力分散至不同的数据库
  • 2.问题:垂直分库可以缓解数据库数据量和访问量的问题,即缓解对IO性能;但无法处理单表数据量过大问题,此时需要水平分片进一步处理
2.垂直分表
  • 1.定义:核心理念是专表专用
    • 1.拆分之前:一个数据表由多个字段构成,每个字段对应着不同的业务
    • 2.拆分之后:按照业务将字段进行归类,分布到不同的专用数据表,从而将压力分散至不同的数据表
  • 2.问题
    • 1.垂直分表可以缓解数据表访问量和占用量的问题,但无法处理单表数据量过大问题,此时需要水平分片进一步处理
    • 2.垂直分表会引入额外的复杂度,原来只要一次查询,现在需要两次查询
  • 3.适用范围:垂直分表适合将表中不常用的列或是占了大量空间的列拆分出去
  • 4.注意:垂直分表对应的主键id应该保持一致
2.水平分片
  • 1.定义:通过某个字段(或某几个字段),根据某种规则将数据分散至多个库或表中的方式称为水平分片/横向拆分
  • 2.水平分片可细分为
    • 1.水平分库
    • 2.水平分表
1.水平分库

在这里插入图片描述

  • 1.定义:相对于垂直分库,不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个库中,每个数据库的分片仅包含数据的一分部(例:根据主键分片,偶数主键的记录放入0库,奇数主键的记录放入1库)
  • 2.单表进行切分后,是否将多个表分散在不同的数据库服务器中,可以根据实际的切分效果来确定
  • 3.适用场景:如果单表拆分为多表后,单台服务器依然无法满足性能要求,那就需要将多个表分散在不同的数据库服务器中
2.水平分表

在这里插入图片描述

  • 1.定义:相对于垂直分表,不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个表中,每个数据表的分片仅包含数据的一分部(例:根据主键分片,偶数主键的记录放入0表,奇数主键的记录放入1表)
  • 2.适用范围:水平分表适合表行数特别大的表
    在这里插入图片描述
  • 3.注意
    • 1.单表切分为多表后,新的表即使在同一个数据库服务器中,也可能带来可观的性能提升;如果性能能够满足业务要求,可不拆分到多台数据库服务器,因为业务分库也会引入更多复杂性
    • 2.将拆分的表引入多台数据库会更复杂(例:分布式事务,跨库关联,数据库成本)
3.产生原因
  • 1.分表
    • 1.随着表数据的不断增大,查询变得缓慢
    • 2.如果添加过多索引,会影响到新增和删除的性能
    • 3.将数据分散到不同的表上,使单表的索引大小得到控制
  • 2.分库
    • 1.数据库实例的吞吐量达到性能的瓶颈,需要扩展数据库实例,让每个数据库实例分担一部分请求,分解总体大请求量的压力
    • 2.数据库扩容时需要对配置改变最少则需要在每个数据库实例中预留足够的数据库数量
4.适用范围及问题
1.适用范围
  • 1.数据库设计时考虑垂直分库和垂直分表
  • 2.随着数据库数据量增加,首先考虑缓存处理读写分离索引等方式,如果这些方式不能根本解决问题,再考虑水平分库和水平分表
2.问题
  • 1.跨节点连接查询问题(分页,排序)
  • 2.多数据源管理问题
  • 3.分布式主键
  • 4.分布式事务

3.读写分离和数据分片

在这里插入图片描述

  • 1.上图展示将数据分片与读写分离一同使用时,应用程序与数据库集群之间的复杂拓扑关系
1.实现方式
  • 1.读写分离和数据分片具体的实现方式一般有两种
    • 1.程序代码封装
    • 2.中间件封装
1.程序代码封装
  • 1.定义:指在代码中抽象一个数据访问层(或中间层封装),对程序进行一个封装,让数据访问层直接去访问不同数据库集群中的数据源,实现读写分离操作和数据库服务器连接的管理
    在这里插入图片描述
2.中间件封装
  • 1.中间件封装是指的是独立一套系统出来提供数据访问层的功能,从而实现读写操作分离和数据库服务器连接的管理
  • 2.对于程序服务器而言,访问中间件和访问数据库没有区别
  • 3.常用的中间件有ShardingSphereMyCat,其中已经封装好了数据访问层供程序使用
  • 4.Apache ShardingSphere既提供了程序级别也提供了中间件级别两种解决方案;MyCat只提供了中间件解决方案

2.ShardingSphere JDBC

1.简介

  • 1.ShardingSphere JDBC定位为轻量级Java框架,在JavaJDBC层提供的额外服务,类似生成一个数据访问层,使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架
    • 1.适用于任何基于JDBCORM框架(JPAHibetnatemybatisSpring JDBC Template或直接使用JDBC
    • 2.支持任何第三方的数据库连接池(DBCPC3P0BoneCPHikariCP等)
    • 3.支持任意实现JDBC规范的数据库(MySQLPostgreSQLOracleSQLServer以及任何可使用JDBC访问的数据库)
  • 2.如图所示ShardingSphere JDBC充当一个数据访问层,如果应用程序是集群模式可采用服务治理组件(zookeeper
    在这里插入图片描述

2.读写分离搭建步骤

1.搭建Mysql主从复制

  • 参考数据库-MySQL文章中的主从复制

2.创建Maven项目

在这里插入图片描述
在这里插入图片描述

3.导入架包

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.demp</groupId>
   <artifactId>ShardingSphere</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>ShardingSphere</name>
   <description>Demo project for ShardingSphere</description>
   
   <properties>
       <java.version>1.8</java.version>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
       <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
   </properties>

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

       <dependency>
           <groupId>org.apache.shardingsphere</groupId>
           <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
           <version>5.1.1</version>
       </dependency>

       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <scope>runtime</scope>
       </dependency>

       <dependency>
           <groupId>com.baomidou</groupId>
           <artifactId>mybatis-plus-boot-starter</artifactId>
           <version>3.3.1</version>
       </dependency>

       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
           <exclusions>
               <exclusion>
                   <groupId>org.junit.vintage</groupId>
                   <artifactId>junit-vintage-engine</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
   </dependencies>

   <dependencyManagement>
       <dependencies>
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-dependencies</artifactId>
               <version>${spring-boot.version}</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
       </dependencies>
   </dependencyManagement>

   <build>
       <plugins>
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
               <version>3.8.1</version>
               <configuration>
                   <source>1.8</source>
                   <target>1.8</target>
                   <encoding>UTF-8</encoding>
               </configuration>
           </plugin>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
               <version>2.3.7.RELEASE</version>
               <configuration>
                   <mainClass>com.atguigu.shargingjdbcdemo.ShargingJdbcDemoApplication</mainClass>
               </configuration>
               <executions>
                   <execution>
                       <id>repackage</id>
                       <goals>
                           <goal>repackage</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
       </plugins>
   </build>

</project>

4.配置文件

1.application.properties
# 应用名称
spring.application.name=ShardingSphere
# 开发环境设置
spring.profiles.active=dev
# 内存模式
spring.shardingsphere.mode.type=Memory

# 配置真实数据源
spring.shardingsphere.datasource.names=master,slave1,slave2

# 配置第 1 个数据源
spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=root

# 配置第 2 个数据源
spring.shardingsphere.datasource.slave1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.slave1.username=root
spring.shardingsphere.datasource.slave1.password=root

# 配置第 3 个数据源
spring.shardingsphere.datasource.slave2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.slave2.jdbc-url=jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.slave2.username=root
spring.shardingsphere.datasource.slave2.password=root

# 读写分离类型,如: Static,Dynamic
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.type=Static
# 写数据源名称
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.props.write-data-source-name=master
# 读数据源名称,多个从数据源用逗号分隔
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.props.read-data-source-names=slave1,slave2

# 负载均衡算法名称
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.load-balancer-name=alg_weight

# 负载均衡算法配置
# 负载均衡算法类型
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_round.type=ROUND_ROBIN
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_random.type=RANDOM
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_weight.type=WEIGHT
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_weight.props.slave1=1
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_weight.props.slave2=2

# 打印SQl
spring.shardingsphere.props.sql-show=true
2.application.yml
版本1
server:
 port: 8091
spring:
 profiles:
   active: test
 shardingsphere:
   mode:
     type: Memory
   datasource:
     names: master,slave1,slave2
     master:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       jdbc-url: jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
     slave1:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       jdbc-url: jdbc:mysql://169.254.73.102:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
     slave2:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       jdbc-url: jdbc:mysql://169.254.73.103:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
   rules:
     readwrite-splitting:
       data-sources:
         myds:
           type: Static
           load-balancer-name: alg_round
           props:
             write-data-source-name: master
             read-data-source-names: slave1,slave2
         load-balancers:
           alg_round:
             type: ROUND_ROBIN
           alg_random:
             type: RANDOM
           alg_weight:
             type: WEIGHT
             props:
               slave1: 1
               slave2: 2
   props:
     sql-show: true
  • 注意:
    • 1.上述配置使用ShardingSphere5.0.0-alpha5.0.0版本会报错
    • 2.使用ShardingSphere5.1.05.1.1版本不会报错
      在这里插入图片描述
版本2
server:
 port: 8091
spring:
 profiles:
   active: test
 shardingsphere:
   mode:
     type: Memory
   datasource:
     common:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
     names: master,slave1,slave2
     master:
       jdbc-url: jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
     slave1:
       jdbc-url: jdbc:mysql://169.254.73.102:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
     slave2:
       jdbc-url: jdbc:mysql://169.254.73.103:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
   rules:
     readwrite-splitting:
       data-sources:
         myds:
           type: Static
           load-balancer-name: alg_round
           props:
             write-data-source-name: master
             read-data-source-names: slave1,slave2
         load-balancers:
           alg_round:
             type: ROUND_ROBIN
           alg_random:
             type: RANDOM
           alg_weight:
             type: WEIGHT
             props:
               slave1: 1
               slave2: 2
   props:
     sql-show: true
  • 注意:
    • 1.上述数据源配置使用ShardingSphere的和5.0.05.1.05.1.1版本会报错
    • 2.使用ShardingSphere5.0.0-alpha版本不会报错
    • 3.所以使用5.0.0-alpha版本必须使用common配置数据源5.1.05.1.1版本不能使用common配置数据源5.0.0版本数据源无法配置成功
    • 4.当前使用ShardingSphere5.1.1版本

5.通过MybatisX快速生成

在这里插入图片描述
在这里插入图片描述

6.创建启动类

package com.demp;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.demp.mapper")
public class  ShardingSphereStartApplication {
   public static void main(String[] args) {
       SpringApplication.run(ShardingSphereStartApplication.class,args);
       System.out.println("---------------------项目启动成功!---------------------");
   }
}

7.读写分离测试

package com.demp;

import com.demp.domain.NyEnergyData;
import com.demp.mapper.NyEnergyDataMapper;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@SpringBootTest
public class ShardingSphereStartApplicationTest {

   @Resource
   NyEnergyDataMapper nyEnergyDataMapper;

   @Test
   public void insert(){
       NyEnergyData nyEnergyData = new NyEnergyData(null,111L,new Date(),1,1L,1L,"A111","D111","111",new Date(),null,null,0,"111",0,"测试");
       nyEnergyDataMapper.insert(nyEnergyData);
   }

   @Test
   public void select(){
       List<NyEnergyData> nyEnergyDataList = nyEnergyDataMapper.selectList(null);
       nyEnergyDataList.forEach(nyEnergyData -> System.out.println(nyEnergyData));
   }
}
2023-03-03 15:16:30.436  INFO 41736 --- [main] 
ShardingSphere-SQL : Logic SQL: 
INSERT INTO ny_energy_data  
(id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,is_delete,row_id,is_statistics,remark )  
VALUES  
( ?,?,?,?,?,?,?,?,?,?,?,?,?,? )
2023-03-03 15:16:30.436  INFO 41736 --- [main] 
ShardingSphere-SQL : SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2023-03-03 15:16:30.436  INFO 41736 --- [main] 
ShardingSphere-SQL : Actual SQL: master ::: 
INSERT INTO ny_energy_data  
(id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,is_delete,row_id,is_statistics,remark )  
VALUES  
( ?,?,?,?,?,?,?,?,?,?,?,?,?,? ) ::: 
[1631554118550081537, 222, 2023-03-03 15:16:29.275, 2, 2, 2, A222, D222, 222, 2023-03-03 15:16:29.275, 0, 222, 0, 测试]
2023-03-03 15:25:42.902  INFO 19944 --- [main] ShardingSphere-SQL: 
Logic SQL: SELECT  id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,update_time,delete_time,is_delete,row_id,is_statistics,remark  FROM ny_energy_data
2023-03-03 15:25:42.903  INFO 19944 --- [main] ShardingSphere-SQL: 
SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2023-03-03 15:25:42.903  INFO 19944 --- [main] ShardingSphere-SQL: 
Actual SQL: slave1 ::: SELECT  id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,update_time,delete_time,is_delete,row_id,is_statistics,remark  FROM ny_energy_data

8.读写分离+事务测试

1.未加事务
@Test
public void testTransactional(){
   NyEnergyData nyEnergyData = new NyEnergyData(null,222L,new Date(),2,2L,2L,"A222","D222","222",new Date(),null,null,0,"222",0,"测试");
   nyEnergyDataMapper.insert(nyEnergyData);
   List<NyEnergyData> nyEnergyDataList = nyEnergyDataMapper.selectList(null);
   nyEnergyDataList.forEach(data -> System.out.println(data));
}
2023-03-03 15:50:40.875  INFO 31528 --- [main] ShardingSphere-SQL: 
Logic SQL: INSERT INTO ny_energy_data  (id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,is_delete,row_id,is_statistics,remark )  
VALUES  ( ?,?,?,?,?,?,?,?,?,?,?,?,?,? )
2023-03-03 15:50:40.876  INFO 31528 --- [main] ShardingSphere-SQL: 
SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2023-03-03 15:50:40.876  INFO 31528 --- [main] ShardingSphere-SQL: 
Actual SQL: master ::: INSERT INTO ny_energy_data  (id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,is_delete,row_id,is_statistics,remark )  
VALUES  ( ?,?,?,?,?,?,?,?,?,?,?,?,?,? ) ::: 
[1631562716718092289, 222, 2023-03-03 15:50:39.194, 2, 2, 2, A222, D222, 222, 2023-03-03 15:50:39.194, 0, 222, 0, 测试]
2023-03-03 15:50:41.153  INFO 31528 --- [main] ShardingSphere-SQL: 
Logic SQL: SELECT id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,update_time,delete_time,is_delete,row_id,is_statistics,remark  FROM ny_energy_data
2023-03-03 15:50:41.153  INFO 31528 --- [main] ShardingSphere-SQL: 
SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2023-03-03 15:50:41.153  INFO 31528 --- [main] ShardingSphere-SQL: 
Actual SQL: slave1 ::: SELECT  id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,update_time,delete_time,is_delete,row_id,is_statistics,remark  FROM ny_energy_data
2.加事务
@Test
@Transactional
public void testTransactional(){
   NyEnergyData nyEnergyData = new NyEnergyData(null,222L,new Date(),2,2L,2L,"A222","D222","222",new Date(),null,null,0,"222",0,"测试");
   nyEnergyDataMapper.insert(nyEnergyData);
   List<NyEnergyData> nyEnergyDataList = nyEnergyDataMapper.selectList(null);
   nyEnergyDataList.forEach(data -> System.out.println(data));
}
2023-03-03 16:03:37.964  INFO 34092 --- [main] 
o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@446a1e84 testClass = ShardingSphereStartApplicationTest, testInstance = com.demp.ShardingSphereStartApplicationTest@188bf4d8, testMethod = testTransactional@ShardingSphereStartApplicationTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@4f0f2942 testClass = ShardingSphereStartApplicationTest, locations = '{}', classes = '{class com.demp.ShardingSphereStartApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7b98f307, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@59474f18, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@5b7a5baa, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@1573f9fc, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@4cb2c100], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]; 
transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@7dd7ec56]; rollback [true]
2023-03-03 16:03:40.070  INFO 34092 --- [main] ShardingSphere-SQL: 
Logic SQL: INSERT INTO ny_energy_data  (id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,is_delete,row_id,is_statistics,remark )  VALUES  ( ?,?,?,?,?,?,?,?,?,?,?,?,?,? )
2023-03-03 16:03:40.071  INFO 34092 --- [main] ShardingSphere-SQL: 
SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2023-03-03 16:03:40.071  INFO 34092 --- [main] ShardingSphere-SQL: 
Actual SQL: master ::: INSERT INTO ny_energy_data  (id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,is_delete,row_id,is_statistics,remark )  VALUES  ( ?,?,?,?,?,?,?,?,?,?,?,?,?,? ) ::: 
[1631565984982728705, 222, 2023-03-03 16:03:38.43, 2, 2, 2, A222, D222, 222, 2023-03-03 16:03:38.43, 0, 222, 0, 测试]
2023-03-03 16:03:40.403  INFO 34092 --- [main] ShardingSphere-SQL: 
Logic SQL: SELECT id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,update_time,delete_time,is_delete,row_id,is_statistics,remark  FROM ny_energy_data
2023-03-03 16:03:40.404  INFO 34092 --- [main] ShardingSphere-SQL: 
SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2023-03-03 16:03:40.404  INFO 34092 --- [main] ShardingSphere-SQL: 
Actual SQL: master ::: SELECT id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,create_time,update_time,delete_time,is_delete,row_id,is_statistics,remark  FROM ny_energy_data
。。。。。。
2023-03-03 16:03:40.807  INFO 34092 --- [main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@446a1e84 testClass = ShardingSphereStartApplicationTest, testInstance = com.demp.ShardingSphereStartApplicationTest@188bf4d8, testMethod = testTransactional@ShardingSphereStartApplicationTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@4f0f2942 testClass = ShardingSphereStartApplicationTest, locations = '{}', classes = '{class com.demp.ShardingSphereStartApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7b98f307, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@59474f18, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@5b7a5baa, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@1573f9fc, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@4cb2c100], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]
  • 1.为了保证主从库间的事务一致性,避免跨服务的分布式事务,ShardingSphere-JDBC的主从模型中,事务中的数据读写均用主库
    • 1.不添加@Transactional写操作对主库操作,读操作对从库操作
    • 2.添加@Transactional读写操作均对主库操作
  • 2.注意
    • JUnit环境下的@Transactional注解,默认情况下就会对事务进行回滚(即使在没加注解@Rollback,也会对事务回滚)

9.负载均衡算法及测试

类型名称参数参数类型
ROUND_ROBIN轮询transaction-read-query-strategyString
RANDOM随机transaction-read-query-strategyString
WEIGHT权重读库名称Double
# 配置规则
rules:
# 读写分离
readwrite-splitting:
 # 数据源
 data-sources:
 	# 自定义数据源名称
   myds:
     # 数据源类型:静态,动态
     type: Static
     # 采用的负载均衡算法名称(对应下面)
     load-balancer-name: alg_round
     props:
     	# 写数据源名称
       write-data-source-name: master
       # 读数据源名称
       read-data-source-names: slave1,slave2
   # 负载均衡算法
   load-balancers:
     # 算法名称 
     alg_round:
     	# 算法类型:轮询
       type: ROUND_ROBIN
     # 算法名称 
     alg_random:
     	# 算法类型:随机
       type: RANDOM
     # 算法名称 
     alg_weight:
     	# 算法类型:权重
       type: WEIGHT
       props:
         # 数据源权重
         slave1: 1
         slave2: 2
  • 1.经过测试以上算法均成功,注意权重只是概率设置,并非绝对比

3.数据分片搭建步骤

1.创建Maven项目

  • 同上

2.导入架包

  • 同上

3.配置文件

1.行表达式
  • 1.作用:行表达式是为了有效地简化数据节点配置
  • 2.使用方法
    • 1.$->{begin..end}:表示范围区间
      $->{begin..end}
      例:
      spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=localhost-energy.t_order$->{0..1}
      表示:
      localhost-energy.t_order0,localhost_energy.t_order1
      
    • 2.$->{[unit1,unit2,unit_x]}:表示枚举值
      $->{[unit1,unit2,unit_x]}
      例:
      spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=localhost-energy.t_order$->{[0,1,3]}
      表示:
      localhost-energy.t_order0,localhost_energy.t_order1,localhost_energy.t_order3
      
    • 3.行表达式中如果出现连续多个$->{ expression }表达式,整个表达式最终的结果将会根据每个子表达式的结果进行笛卡尔组合
      例:spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=localhost-energy$->{0..1}.t_order$->{0..1}
      表示:
      localhost-energy0.t_order0,localhost_energy0.t_order1,localhost-energy1.t_order0,localhost_energy1.t_order1
      
      例:spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=$->{[localhost-energy,virtual-energy]}.t_order$->{0..1}
      表示:
      localhost-energy.t_order0,localhost_energy.t_order1,virtual-energy.t_order0,virtual-energy.t_order1
      
    • 4.非均匀数据节点需要单独配置每个数据节点的对应表
      例:spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=localhost-energy.t_order$->{0..1},virtual-energy.t_order$->{[1,3,4]}
      表示:
      localhost-energy.t_order0,localhost_energy.t_order1,virtual-energy.t_order1,virtual-energy.t_order3,virtual-energy.t_order4
      
    • 5.有前缀数据节点,可以将公共部分提取
      例:spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=localhost-energy.t_order_0$->{0..1},virtual-energy.t_order_0$->{[1,3,4]}
      表示:
      localhost-energy.t_order_00,localhost_energy.t_order_01,virtual-energy.t_order_01,virtual-energy.t_order_03,virtual-energy.t_order_04
      
2.垂直分库
1.application.properties
# 应用名称
spring.application.name=ShardingSphere
# 开发环境设置
spring.profiles.active=dev
# 内存模式
spring.shardingsphere.mode.type=Memory

# 配置真实数据源
spring.shardingsphere.datasource.names=localhost-energy,virtual-energy

# 配置第 1 个数据源
spring.shardingsphere.datasource.localhost-energy.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.localhost-energy.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.localhost-energy.jdbc-url=jdbc:mysql://localhost:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.localhost-energy.username=root
spring.shardingsphere.datasource.localhost-energy.password=root

# 配置第 2 个数据源
spring.shardingsphere.datasource.virtual-energy.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.virtual-energy.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.virtual-energy.jdbc-url=jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.virtual-energy.username=root
spring.shardingsphere.datasource.virtual-energy.password=root

# 标准分片表配置
# 由数据源名 + 表名组成,以小数点分隔。
# 多个表以逗号分隔,支持 inline 表达式。
# 缺省表示使用已知数据源与逻辑表名称生成数据节点,用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况
spring.shardingsphere.rules.sharding.tables.area_account.actual-data-nodes=localhost-energy.area_account
spring.shardingsphere.rules.sharding.tables.ny_energy_data.actual-data-nodes=virtual-energy.ny_energy_data

# 打印SQl
spring.shardingsphere.props.sql-show=true
2.application.yml
server:
 port: 8091
spring:
 profiles:
   active: test
 shardingsphere:
   mode:
     type: Memory
   datasource:
     names: localhost-energy,virtual-energy
     localhost-energy:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://localhost:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
     virtual-energy:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
   rules:
     sharding:
       tables:
         arar_account:
           actual-data-nodes: localhost-energy.area_account
         ny_energy_data:
           actual-data-nodes: virtual-energy.ny_energy_data
   props:
     sql-show: true
3.垂直分表
  • 1.垂直分表等同于按业务分为不同的表,即无需使用ShardingSphere
4.水平分库
  • 1.水平分片的id需要在业务层实现,不能依赖数据库的主键自增
  • 2.因为使用数据库本身的主键自增,不同的表会有各自独立的自增序列,拆分多张表的主键会重复
  • 3.需要在业务代码中生成主键,而非依赖主键自增
  • 4.水平分片的实体类对应未拆分的逻辑表,而真实数据节点则对应数据库中的真实表
    在这里插入图片描述
    在这里插入图片描述
  • 5.修改时无法修改分片键,否则会报错
  • 6.实体类id一般使用Long类型,且表id使用bigint类型,否则分布式id的值过大会报错
  • 7.表varchar需要设置字符类型字符排序类型,一般设置为utf8mb4utf8mb4_general_ci,否则根据该字段查询时会报错
1.application.properties
#------------------------基本配置
# 应用名称
spring.application.name=ShardingSphere
# 开发环境设置
spring.profiles.active=dev
# 内存模式
spring.shardingsphere.mode.type=Memory
# 打印SQl
spring.shardingsphere.props.sql-show=true


#------------------------数据源配置
# 配置真实数据源
spring.shardingsphere.datasource.names=energy0,energy1

# 配置第 1 个数据源
spring.shardingsphere.datasource.energy0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.energy0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.energy0.jdbc-url=jdbc:mysql://localhost:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.energy0.username=root
spring.shardingsphere.datasource.energy0.password=root

# 配置第 2 个数据源
spring.shardingsphere.datasource.energy1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.energy1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.energy1.jdbc-url=jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.energy1.username=root
spring.shardingsphere.datasource.energy1.password=root


#------------------------标准分片表配置(数据节点配置)
# 由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# 缺省表示使用已知数据源与逻辑表名称生成数据节点,用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=energy$->{0..1}.t_order0


#------------------------分库策略,缺省表示使用默认分库策略,以下的分片策略只能选其一
# 用于单分片键的标准分片场景
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=type
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_inline_type
       

#------------------------分片算法配置
# 行表达式分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_type.type=INLINE
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_type.props.algorithm-expression=energy$->{type % 2}

# 取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2
       
# 哈希取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2
2.application.yml
server:
 port: 8091
spring:
 profiles:
   active: test
 shardingsphere:
   mode:
     type: Memory
   datasource:
     names: energy0,energy1
     energy0:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://localhost:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
     energy1:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
   rules:
     sharding:
       tables:
         t_order:
           actual-data-nodes: energy$->{0..1}.t_order0
           database-strategy:
             standard:
               sharding-column: type
               sharding-algorithm-name: alg_inline_type
       sharding-algorithms:
         alg_inline_type:
           type: INLINE
           props:
             algorithm-expression: energy$->{type % 2}
         alg_mod:
           type: MOD
           props:
             sharding-count: 2
         alg_hash_mod:
           type: HASH_MOD
           props:
             sharding-count: 2
   props:
     sql-show: true
5.水平分表
  • 1.水平分片的id需要在业务层实现,不能依赖数据库的主键自增
  • 2.因为使用数据库本身的主键自增,不同的表会有各自独立的自增序列,拆分多张表的主键会重复
  • 3.需要在业务代码中生成主键,而非依赖主键自增
  • 4.水平分片的实体类对应未拆分的逻辑表,而真实数据节点则对应数据库中的真实表
  • 5.配置文件类似水平分库,修改对应的数据节点即可
1.application.properties
#------------------------基本配置
# 应用名称
spring.application.name=ShardingSphere
# 开发环境设置
spring.profiles.active=dev
# 内存模式
spring.shardingsphere.mode.type=Memory
# 打印SQl
spring.shardingsphere.props.sql-show=true


#------------------------数据源配置
# 配置真实数据源
spring.shardingsphere.datasource.names=energy0,energy1

# 配置第 1 个数据源
spring.shardingsphere.datasource.energy0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.energy0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.energy0.jdbc-url=jdbc:mysql://localhost:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.energy0.username=root
spring.shardingsphere.datasource.energy0.password=root

# 配置第 2 个数据源
spring.shardingsphere.datasource.energy1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.energy1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.energy1.jdbc-url=jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.energy1.username=root
spring.shardingsphere.datasource.energy1.password=root


#------------------------标准分片表配置(数据节点配置)
# 由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# 缺省表示使用已知数据源与逻辑表名称生成数据节点,用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=energy$->{0..1}.t_order$->{0..1}


#------------------------分库策略,缺省表示使用默认分库策略,以下的分片策略只能选其一
# 用于单分片键的标准分片场景
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=type
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_inline_type

#------------------------分表策略
# 用于单分片键的标准分片场景
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=code
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=alg_hash_mod

#------------------------分片算法配置
# 行表达式分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_type.type=INLINE
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_type.props.algorithm-expression=energy$->{type % 2}

# 取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2

# 哈希取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2
2.application.yml
server:
 port: 8091
spring:
 profiles:
   active: test
 shardingsphere:
   mode:
     type: Memory
   datasource:
     names: energy0,energy1
     energy0:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://localhost:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
     energy1:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
   rules:
     sharding:
       tables:
         t_order:
           actual-data-nodes: energy$->{0..1}.t_order$->{0..1}
           database-strategy:
             standard:
               sharding-column: type
               sharding-algorithm-name: alg_inline_type
           table-strategy:
             standard:
               sharding-column: code
               sharding-algorithm-name: alg_hash_mod
       sharding-algorithms:
         alg_inline_type:
           type: INLINE
           props:
             algorithm-expression: energy$->{type % 2}
         alg_mod:
           type: MOD
           props:
             sharding-count: 2
         alg_hash_mod:
           type: HASH_MOD
           props:
             sharding-count: 2
   props:
     sql-show: true

5.通过MybatisX快速生成

在这里插入图片描述

6.创建启动类

  • 同上

7.测试

1.垂直分库
   @Test
   public void insert(){
       NyEnergyData nyEnergyData = new NyEnergyData();
       nyEnergyData.setEnterpriseId(111L);
       nyEnergyData.setUseTime(new Date());
       nyEnergyData.setDateType(1);
       nyEnergyData.setAttributeId(1L);
       nyEnergyData.setFrequencyId(1L);
       nyEnergyData.setAttributeCode("A111");
       nyEnergyData.setDataCode("D111");
       nyEnergyData.setDataValue("2525");
       nyEnergyData.setRowId("test");
       nyEnergyDataMapper.insert(nyEnergyData);
       AreaAccount areaAccount = new AreaAccount();
       areaAccount.setCityName("测试");
       areaAccountMapper.insert(areaAccount);
   }
2023-03-03 19:22:01.235  INFO 36836 --- [main] ShardingSphere-SQL: 
Logic SQL: INSERT INTO ny_energy_data  (id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,row_id )  VALUES  ( ?,?,?,?,?,?,?,?,?,? )
2023-03-03 19:22:01.235  INFO 36836 --- [main] ShardingSphere-SQL: 
SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2023-03-03 19:22:01.235  INFO 36836 --- [main] ShardingSphere-SQL: 
Actual SQL: virtual-energy ::: INSERT INTO ny_energy_data  ( id,enterprise_id,use_time,date_type,attribute_id,frequency_id,attribute_code,data_code,data_value,row_id )  VALUES  (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ::: 
[1631615903340724225, 111, 2023-03-03 19:21:59.893, 1, 1, 1, A111, D111, 2525, test]
2023-03-03 19:22:04.859  INFO 36836 --- [main] ShardingSphere-SQL: 
Logic SQL: INSERT INTO area_account  ( city_name )  VALUES  ( ? )
2023-03-03 19:22:04.859  INFO 36836 --- [main] ShardingSphere-SQL: 
SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2023-03-03 19:22:04.859  INFO 36836 --- [main] ShardingSphere-SQL: 
Actual SQL: localhost-energy ::: INSERT INTO area_account  ( city_name )  VALUES  (?) ::: [测试]
  • 1.经测试,不同数据库的表的读写操作会自动路由到对应的数据库中
2.垂直分表
  • 无需测试
3.水平分库
	@Test
   public void testShardingSelect(){
       List<Order> orders = orderMapper.selectList(null);
       orders.forEach(order -> System.out.println(order));
   }

   @Test
   public void testShardingInsertAndUpdate(){
       Order order = new Order();
       order.setName("洛基亚");
       order.setCode("L444444");
       order.setNumber(3000L);
       order.setCreateTime(new Date());
       Order oldOrder = orderMapper.selectOne(new QueryWrapper<Order>().eq("name","洛基亚"));
       if(Objects.isNull(oldOrder)){
           order.setVersion(0);
           if(orderMapper.insert(order) > 0){
               System.out.println("添加成功!");
           }else {
               System.out.println("添加失败");
           }
       }else {
           Integer num = oldOrder.getVersion();
           order.setVersion(++num);
           order.setUpdateTime(new Date());
           if(orderMapper.update(order,new QueryWrapper<Order>().eq("name","洛基亚")) > 0){
               System.out.println("更新成功!");
           }else {
               System.out.println("更新失败");
           }
       }
   }
  • 1.实体类的id主键需要设置为分布式生成,且类型为Long,对应的表id类型应该为bigint,且varchar类型需按如下设置
    在这里插入图片描述
    在这里插入图片描述
  • 2.修改时无法修改分片键
    在这里插入图片描述
  • 3.插入时根据分库分片键自动将数据插入对应的库中,查询时自动根据分片键去指定的库中查询,然后ShardingSphere会自动将结果组合到一起
    在这里插入图片描述
4.水平分表
  • 1.测试内容同水平分库
  • 2.插入时根据分表分片键自动将数据插入到对应的表中,查询时将同一个库中的多个表的数据使用UNION ALL连接到一起,然后再将不同库的数据组装到一起
    在这里插入图片描述

8.分片算法

1.优缺点
  • 1.取模分片
    • 1.优点:数据存放比较均匀
    • 2.缺点:扩容需要大量数据迁移(例:两个片不够则需再加片,之前分好的数据需要迁移)
  • 2.范围分片(时间,id前缀,地区等)
    • 优点:扩容不需要迁移数据
    • 缺点:数据存放不均匀,容易产生数据倾斜(例:双11活动,可能11月分片很多,无法分担压力)
  • 3.业务场景分片

4.雪花算法

  • 1.传统数据库中,主键自动生成技术是基本需求(主键自增)
  • 2.数据分片后,不同数据节点生成全局唯一主键无法通过传统主键自增完成
  • 3.因为同一个逻辑表内的不同实际表之间的自增键由于无法互相感知而会产生重复主键
  • 4.可通过约束自增主键初始值和步长的方式避免碰撞,但需要引入额外的规则,使解决方案缺乏完整性和可扩展性
  • 5.通过第三方解决方案,如:UUIDSNOWFLAKE(雪花算法)

1.实现原理

  • 1.雪花算法生成64bit的长整型数据
  • 2.同一个进程中,首先通过时间位保证不重复,如果时间相同则通过序列位保证
  • 3.由于时间位是单调递增的,且各个服务器如果做了时间同步,那生成的主键在分布式环境可认为是总体有序的,保证了对索引字段插入的高效性
  • 4.雪花算法生成的主键,二进制表示形式包含4部分,从高位到低位分别表示为:1bit符号位41bit的时间戳位10bit工作进程位以及12bit的序列号位
    • 1.符号位(1bit)
      • 预留的符号位,恒为零(因为生成的是正数)
    • 2.时间戳位(41bit)
      • 41位的时间戳可以容纳的毫秒数是2的41次幂,一年所使用的毫秒数是365*24*60*60*100,通过计算可知结果约等于69.73年,Apache ShardingSphere的雪花算法时间纪元从2016年11月1日零点开始,可使用到2086年,可满足绝大部分系统的要求
    • 3.工作进程位(10bit)
      • 该标志在Java进程内是唯一的,如果是分布式应用部署应保证每个工作进程的id是不同的,该值默认为0,可通过属性设置
    • 4.序列号位(12bit)
      • 该序列用来在同一个毫秒内生成不同的id,如果在这个毫秒内生成的数量超过4096(2的12次幂),那么生成器会等待到下个毫秒继续生成
  • 5.雪花算法主键的详细结构图
    在这里插入图片描述
  • 6.雪花算法和UUID比较:雪花算法生成的主键唯一有序,而UUID生成的主键唯一无序,所以一般使用雪花算法作为主键生成策略

5.分布式序列配置

  • 1.使用ShardingSphere生成分布式主键id需要将Mybatis-Plus的主键自增策略设置为自增
    在这里插入图片描述
  • 2.因为Mybatis-Plus默认为雪花算法生成主键id,其优先级比ShardingSphere
    在这里插入图片描述

1.application.properties

#------------------------基本配置
# 应用名称
spring.application.name=ShardingSphere
# 开发环境设置
spring.profiles.active=dev
# 内存模式
spring.shardingsphere.mode.type=Memory
# 打印SQl
spring.shardingsphere.props.sql-show=true


#------------------------数据源配置
# 配置真实数据源
spring.shardingsphere.datasource.names=energy0,energy1

# 配置第 1 个数据源
spring.shardingsphere.datasource.energy0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.energy0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.energy0.jdbc-url=jdbc:mysql://localhost:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.energy0.username=root
spring.shardingsphere.datasource.energy0.password=root

# 配置第 2 个数据源
spring.shardingsphere.datasource.energy1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.energy1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.energy1.jdbc-url=jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
spring.shardingsphere.datasource.energy1.username=root
spring.shardingsphere.datasource.energy1.password=root


#------------------------标准分片表配置(数据节点配置)
# 由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# 缺省表示使用已知数据源与逻辑表名称生成数据节点,用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=energy$->{0..1}.t_order$->{0..1}


#------------------------分库策略,缺省表示使用默认分库策略,以下的分片策略只能选其一
# 用于单分片键的标准分片场景
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=type
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_inline_type

#------------------------分表策略
# 用于单分片键的标准分片场景
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=code
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=alg_hash_mod

#------------------------分片算法配置
# 行表达式分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_type.type=INLINE
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_type.props.algorithm-expression=energy$->{type % 2}

# 取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2

# 哈希取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2


#------------------------分布式序列策略配置
# 分布式序列列名称
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=id
# 分布式序列算法名称
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=alg_snowflake

#------------------------分布式序列算法配置
# 分布式序列算法类型
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.type=SNOWFLAKE
# 分布式序列算法属性配置(如果分布式序列作为分片键则需配置)
# spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.props.xxx=

2.application.yml

server:
 port: 8091
spring:
 profiles:
   active: test
 shardingsphere:
   mode:
     type: Memory
   datasource:
     names: energy0,energy1
     energy0:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://localhost:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
     energy1:
       type: com.zaxxer.hikari.HikariDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
   rules:
     sharding:
       tables:
         t_order:
           actual-data-nodes: energy$->{0..1}.t_order0
           database-strategy:
             standard:
               sharding-column: type
               sharding-algorithm-name: alg_inline_type
           key-generate-strategy:
             column: id
             key-generator-name: alg_snowflake
       sharding-algorithms:
         alg_inline_type:
           type: INLINE
           props:
             algorithm-expression: energy$->{type % 2}
         alg_mod:
           type: MOD
           props:
             sharding-count: 2
         alg_hash_mod:
           type: HASH_MOD
           props:
             sharding-count: 2
       key-generators:
         alg_snowflake:
           type: SNOWFLAKE
   props:
     sql-show: true

6.切换数据源

  • 1.ShardingSphere5.1.1默认使用com.zaxxer.hikari.HikariDataSource数据源
  • 2.如果想切换为durid数据源,则需要添加durid依赖即可

1.配置依赖

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.demp</groupId>
   <artifactId>ShardingSphere</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>ShardingSphere</name>
   <description>Demo project for ShardingSphere</description>

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

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

       <dependency>
           <groupId>org.apache.shardingsphere</groupId>
           <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
           <version>5.1.1</version>
       </dependency>

       <dependency>
           <groupId>com.alibaba</groupId>
           <artifactId>druid</artifactId>
           <version>1.2.9</version>
       </dependency>

       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <scope>runtime</scope>
       </dependency>

       <dependency>
           <groupId>com.baomidou</groupId>
           <artifactId>mybatis-plus-boot-starter</artifactId>
           <version>3.3.1</version>
       </dependency>

       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <optional>true</optional>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
           <exclusions>
               <exclusion>
                   <groupId>org.junit.vintage</groupId>
                   <artifactId>junit-vintage-engine</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
   </dependencies>

   <dependencyManagement>
       <dependencies>
           <dependency>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-dependencies</artifactId>
               <version>${spring-boot.version}</version>
               <type>pom</type>
               <scope>import</scope>
           </dependency>
       </dependencies>
   </dependencyManagement>

   <build>
       <plugins>
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
               <version>3.8.1</version>
               <configuration>
                   <source>1.8</source>
                   <target>1.8</target>
                   <encoding>UTF-8</encoding>
               </configuration>
           </plugin>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
               <version>2.3.7.RELEASE</version>
               <configuration>
                   <mainClass>com.atguigu.shargingjdbcdemo.ShargingJdbcDemoApplication</mainClass>
               </configuration>
               <executions>
                   <execution>
                       <id>repackage</id>
                       <goals>
                           <goal>repackage</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
       </plugins>
   </build>
</project>

2.配置文件

server:
 port: 8091
spring:
 profiles:
   active: test
 shardingsphere:
   mode:
     type: Memory
   datasource:
     names: energy0,energy1
     energy0:
       type: com.alibaba.druid.pool.DruidDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://localhost:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
     energy1:
       type: com.alibaba.druid.pool.DruidDataSource
       driver-class-name: com.mysql.cj.jdbc.Driver
       url: jdbc:mysql://169.254.73.100:3306/energy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&rewriteBatchedStatements=true
       username: root
       password: root
   rules:
     sharding:
       tables:
         t_order:
           actual-data-nodes: energy$->{0..1}.t_order0
           database-strategy:
             standard:
               sharding-column: type
               sharding-algorithm-name: alg_inline_type
           key-generate-strategy:
             column: id
             key-generator-name: alg_snowflake
       sharding-algorithms:
         alg_inline_type:
           type: INLINE
           props:
             algorithm-expression: energy$->{type % 2}
         alg_mod:
           type: MOD
           props:
             sharding-count: 2
         alg_hash_mod:
           type: HASH_MOD
           props:
             sharding-count: 2
       key-generators:
         alg_snowflake:
           type: SNOWFLAKE
   props:
     sql-show: true

3.ShardingSphere Proxy

1.简介

  • 1.ShardingSphere Proxy定位为透明化数据库代理器,即只是一个中间件并不提供程序代码,其提供了封装了数据库二进制协议的服务端版本,用于完成对异构语言(即非Java的项目)的支持

    • 1.目前提供MysqlPostgreSQL版本,可使用任何兼容MySQL/PostgreSQL协议的访问客户端(如(MySQL Command ClientMySQL WorkbenchNavicat等)操作数据
    • 2.对应用程序完全透明,可直接当做MySQL/PostgreSQL使用

    在这里插入图片描述

3.如何设置数据分片方案

  • 如何设计零迁移数据扩容分片方案
  • 问题核心:如何不迁移数据,实现集群动态扩缩容?同时又能保证数据分布相对均匀?
  • 关键点:整体按范围分片,保证扩容时老数据不需要迁移,范围内,按照取模分片,让每个范围内的数据分布大致均匀
    在这里插入图片描述

4.分库分表需要解决哪些问题

  • 主键唯一性
    • 单机,MySQL索引可以保证唯一性。
    • 分布式场景呢(每个数据库通过索引只能保证自己的唯一标识不会重复,无法简单的递增方式交给数据库自己处理,需要构建第三方的服务来保证分布式的主键唯一,还需要注意高并发的场景)
    • 保证数据唯一性最常用的是UUID,用UUID生成业务主键,UUID产生的是字符串主键,排序性能很低,MySQL的innodb引擎的采用的是B+树,需要对主键进行排序,然后排成一颗b+树,UUID的主键排序性能消耗很大,UUID也不是单调递增的趋势,单调递增的好处可以直接插入尾部,所以UUID需要插入中间,对B+树结构也产生影响
  • 分布式事务
    • 保证多个节点的数据一致性
  • SQL路由(in,大于,小于)
    • 每个分片都查
    • 根据分片策略去查一个分片
  • 结果归并
    • 每个节点只包括一部分结果
      在这里插入图片描述
  • 数据库是一个重状态的服务,从单机扩展到集群需要时刻考虑状态如何转移,阿里提出尽量不要分库分表

5.什么时候需要分库分表

在这里插入图片描述

6.分库分表与多数据源切换

  • 分库分表
  • 分库分表不光是管理多个数据源,他是对SQL的优化,改写,归并等一系列的解决方案,关注点是SQL语句
  • 多数据源切换
  • 如果只是需要简单的切换多个数据源,而对于SQL逻辑没有任何的限制,这时就不要选择分库分表了,直接选用多数据源切换的方案更简单
  • 以ShardingSphere为例,虽然他也支持用跟SQL无关的Hint策略提供路由功能,但是在SQL改写以及归并的过程中,依然对SQL有限制
    在这里插入图片描述
  • 两种典型的动态数据源切换方案
    在这里插入图片描述
  • 根据前端请求参数动态切换数据源
  • 在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 方式2动态数据源
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 总结
  • 分库分表是传统数据库在面临互联网三高压力时,最为轻量级的一种解决方案,但是分库分表并不是简单的将数据分散而已,包含了分布式唯一主键,分布式事务,分布式结果归并等一系列问题
  • 在决定使用分库分表之前,要仔细分析项目的业务场景,尽量将方案设计周全,一旦开始使用分库分表,临时改变方案必然要进行大量的数据迁移,对系统的影响会非常大

1.了解ShardingSphere

  • Apache ShardingSphere是一款开源分布式数据库生态项目,由JDBC(工具包,嵌入到Java应用中),Proxy(独立部署成一个服务)和Sidecar(规划中)3款产品构成
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 其中的$->{ }代表变量

3.标准分片之InIine策略

  • 根据单一分片键进行精确分片(不适合范围查询)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

4.标准分片之Standard策略

  • 根据单一分片键进行精确或者范围分片
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

5.标准分片之Complex策略

  • 根据多个分片键进行精确或者范围分片
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

6.标准分片之Hint策略

  • 使用与SQL无关的方式进行分片
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

总结:

  • ShardingSphere是目前分库分表领域影响力最大的一个框架,它提供了四种基础的分片策略,Inline,Standard,Complex,Hint.从这四种策略中可以看到任何一种数据分片策略都是针对特定的SQL语句设计的,没有万能的分片策略,只有合适的分片策略
  • 这四种分片策略也是我们去构建真实分片策略的基础,未来ShardingSphere提出的新的分片策略以及真实企业的复杂分片策略都可以通过这四种分片策略组合形成

新版本分片规则

在这里插入图片描述

ShardingSphere扩展接口

在这里插入图片描述

零迁移数据扩容方案

  • 实现效果:灵活规划下一个分片容量,老的数据不需要迁移
  • 关键点:将范围分片和取模分片的优缺点结合起来,综合考虑

基因法多分片查询

在这里插入图片描述
在这里插入图片描述

读写分离实现方案

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分库分表思想总结

navicate出现中文乱码,需要使用MySQL字符串后问题解决
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值