【分库分表】基于mysql+shardingSphere的分库分表技能

打印 上一主题 下一主题

主题 859|帖子 859|积分 2577

目录
1.什么是分库分表
2.分片方法
3.测试数据
4.shardingSphere
4.1.先容
4.2.sharding jdbc
4.3.sharding proxy
4.4.两者之间的对比
5.留个尾巴


1.什么是分库分表

分库分表是一种场景解决方案,它的出现是为了解决一些场景问题的,哪些场景喃?


  • 单表过大的话,读请求进来,查数据必要的时间会过长
  • 读请求过多,单节点IO压力太大,IO压力太大会造成什么?大概会造成IO壅闭,造成响应速率变慢。
分库分表是指的两种维度,一种维度是分库,另一种维度是分表。分的话有两种分法,一种是水中分,另一种是垂直分。
水中分是指将数据分为多段,一个服务器节点上存放一段,读写的时候走自己要的那一段地点服务器上。一段也叫一个分片(sharding)

垂直分是指将一个库或者一个表从一个整体拆成多个部门,差别服务器上存储一部门:

2.分片方法

其实总的来说分库都还好,垂直分库对应着服务拆成微服务做到资源隔离各玩儿各的,问题都还不大,而且一般不会出现水中分库,因为库里面数据多的也就某一些表,我们面对更多的是水中分表。水中分表首先要面对的就是如何分片?
分片方法有如下几种:


  • hash分片法
  • range分片法
hash分片法:
主键对服务器数目取余。

这种方式在扩容后数据必要重新散列一遍,重新散列一遍花时间吗?当然花时间,但是不散列又不可,为什么喃?举个例,原来id=12的数据散列到了0表,扩容后不迁移的话按照规则id=12的表会散列到4表,这就会导致id=12这条数据在查找的时候找不到:

当然hash算法可以用一致性hash算法来优化,但其数据迁移肯定是无法规避的,且一致性hash算法自己也存在无法规避的缺点。博主之前有一篇一致性hash算法的文章,可移步:
一致性hash算法_不停hash算法-CSDN博客
range分片法:
按照编号顺序均匀的分片,利益是扩容不用散列,但是新数据往往是使用频率更高的数据,会导致压力不均匀,而且现在一般唯一ID为了安全性都是无序的,比如接纳UUID做主键的时候,所以range分片法的场景实用也很有限。

3.测试数据

用一张订单表来做测试数据,根据主键来分库分表:
  
  1. create table order_(
  2. id varchar(100) primary key,
  3. productName VARCHAR(100),
  4. productId VARCHAR(100),
  5. createTime datetime,
  6. statue INT
  7. )ENGINE=INNODB;
复制代码
预备了两个库,db01和db02都有这张订单表:

依赖版本:
万万注意版本的对齐!
  
  1. <dependencies>
  2.        <dependency>
  3.            <groupId>org.springframework.boot</groupId>
  4.            <artifactId>spring-boot-starter-web</artifactId>
  5.        </dependency>
  6.        <dependency>
  7.            <groupId>org.springframework.boot</groupId>
  8.            <artifactId>spring-boot-starter-test</artifactId>
  9.        </dependency>
  10.        <dependency>
  11.            <groupId>org.springframework.boot</groupId>
  12.            <artifactId>spring-boot-starter-actuator</artifactId>
  13.        </dependency>
  14.        <!--prometheus -->
  15.        <dependency>
  16.            <groupId>io.micrometer</groupId>
  17.            <artifactId>micrometer-registry-prometheus</artifactId>
  18.        </dependency>
  19.        <!-- MySQL驱动 -->
  20.        <dependency>
  21.            <groupId>mysql</groupId>
  22.            <artifactId>mysql-connector-java</artifactId>
  23.            <version>8.0.29</version>
  24.        </dependency>
  25.        <!-- MyBatis Plus Starter -->
  26.        <dependency>
  27.            <groupId>com.baomidou</groupId>
  28.            <artifactId>mybatis-plus-boot-starter</artifactId>
  29.            <version>3.5.1</version>
  30.        </dependency>
  31.        <!--sharding-jdbc-->
  32.        <dependency>
  33.            <groupId>org.apache.shardingsphere</groupId>
  34.            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
  35.            <version>4.1.1</version>
  36.        </dependency>
  37.        <!-- Alibaba Druid 数据源 -->
  38.        <dependency>
  39.            <groupId>com.alibaba</groupId>
  40.            <artifactId>druid</artifactId>
  41.            <version>1.2.8</version>
  42.        </dependency>
  43.        <dependency>
  44.            <groupId>org.projectlombok</groupId>
  45.            <artifactId>lombok</artifactId>
  46.            <version>1.18.24</version>
  47.        </dependency>
  48.    </dependencies>
  49.    
  50. <dependencyManagement>
  51.        <dependencies>
  52.            <dependency>
  53.                <groupId>org.springframework.boot</groupId>
  54.                <artifactId>spring-boot-dependencies</artifactId>
  55.                <version>2.6.3</version>
  56.                <type>pom</type>
  57.                <scope>import</scope>
  58.            </dependency>
  59.        </dependencies>
  60.    </dependencyManagement>
复制代码
4.shardingSphere

4.1.先容

分片方法说起来容易,要自己去实现一个全过程的分片分表还是很繁琐的,必要手动实现多数据源,然后实现散列算法来控制读写请求映射到哪一台服务器,升级一点的功能还包罗要与服务器进行心跳通信,获取服务器的信息等等。所以说还是直接用"轮子"吧。
Apache ShardingSphere 是一个开源的分布式数据库中间件解决方案,它由阿里巴巴集团开源,现在是 Apache 软件基金会旗下的顶级项目。ShardingSphere 通过提供一组与数据库交互的标准化接口(如JDBC驱动或代理服务),对上层应用隐蔽了复杂的分布式数据库处置惩罚逻辑,为开发者提供了易用且功能强盛的分库分表、读写分离、数据治理、弹性伸缩等功能。
ShardingSphere分为三部门:Sharding-JDBC、Sharding-Proxy、Sharding-Sidecar。
4.2.sharding jdbc

其中Sharding-JDBC,其会托管JDBC,然后支持实现分库分表、读写分离。分库分表和读写分离都是通过配置实现的,配置好数据源,然后配置好分库规则即可。当然读写分离的前提是数据库已经配置成了读写分离的模式。以下是配置示例:
  
  1. spring:
  2.   application:
  3.    name: testDemo
  4.   shardingsphere:
  5.    datasource:
  6.      names: ds0,ds1
  7.      ds0:
  8.        driver-class-name: com.mysql.cj.jdbc.Driver
  9.        type: com.alibaba.druid.pool.DruidDataSource
  10.        url: jdbc:mysql://localhost:3306/db01?serverTimezone=UTC
  11.        username: root
  12.        password: admin
  13.      ds1:
  14.        driver-class-name: com.mysql.cj.jdbc.Driver
  15.        type: com.alibaba.druid.pool.DruidDataSource
  16.        url: jdbc:mysql://localhost:3306/db02?serverTimezone=UTC
  17.        username: root
  18.        password: admin
  19.    sharding:
  20.      default-database-strategy:
  21.        inline:
  22.          sharding-column: order_id
  23.          algorithm-expression: ds$->{order_id % 2}
  24.        tables:
  25.          t_order:
  26.            actual-data-nodes: ds$->{0..1}.t_order_$->{0..1}
  27.            table-strategy:
  28.              inline:
  29.                sharding-column: order_id
  30.                algorithm-expression: t_order_$->{order_id % 2}
  31.      #读写分离
  32.      master-slave-rules:
  33.        ms_ds:
  34.          master-data-source-name: ds0
  35.          slave-data-source-names: ds1
  36.          load-balance-algorithm-type: ROUND_ROBIN #负载均衡算法
  37.    props:
  38.      sql.show: true #是否打印sql
复制代码
上述YAML配置已经使用了inline表达式实现了基于order_id字段的分库和分表规则。当然还提供了接口,对于自界说分库、分表规则,可以通过实现ShardingSphere提供的接口来自界说算法类,并在配置中引用这些类。
  
  1. public class CustomDatabaseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
  2.    @Override
  3.    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Integer> shardingValue) {
  4.        // 根据order_id和其他可能的业务逻辑计算数据库名称
  5.        int orderId = shardingValue.getValue();
  6.        return "ds" + (orderId % 2); // 这里仅作为示例,实际请根据业务需求编写
  7.    }
  8. }
复制代码
  
  1. spring:
  2.   application:
  3.    name: testDemo
  4.   shardingsphere:
  5.    # ... 数据源配置 ...
  6.    sharding:
  7.      default-database-strategy:
  8.        precise:
  9.          sharding-column: order_id
  10.          algorithm-class-name: com.example.CustomDatabaseShardingAlgorithm
  11.      tables:
  12.        t_order:
  13.          actual-data-nodes: ds$->{0..1}.t_order_$->{0..1}
  14.          table-strategy:
  15.            precise:
  16.              sharding-column: order_id
  17.              # 同样可以为表级别分片指定自定义算法类
  18.              algorithm-class-name: com.example.CustomTableShardingAlgorithm
  19.      # ... 读写分离配置 ...
  20.    props:
  21.      sql.show: true
复制代码
同样的,假如必要自界说分表规则,也必要创建一个实现相应接口(如PreciseShardingAlgorithm)的类,并在table-strategy部门通过algorithm-class-name属性引用它。以上示例中的CustomTableShardingAlgorithm即是一个假设存在的自界说分表策略类。请确保实际应用中已正确创建并配置此类。
4.3.sharding proxy

sharding proxy是一个中间件,也能实现分库分表和读写分离。差别于sharding jdbc必要侵入代码中对JDBC进行一个托管,sharding proxy是无侵入式的,一个独立的组件。应用中的数据库连接设置为proxy的地点+proxy中的逻辑库名,将对数据库的利用全部打到proxy上来,由proxy来进行分库分表。
sharding proxy必要先下载,然后解压、配置。
配置示例:
配置sharding proxy的用户名和密码。

然后必要导入mysql的驱动:

配置分库分表以及读写分离:
给出一个配置文件,大家感受一下,该配置文件基于Apache ShardingSphere 5.x版本的语法编写。差别版本大概配置项存在差别哈。
  
  1. # config-sharding.yaml
  2. schemaName: testDemo  # 指定逻辑库名称
  3. rules:
  4.   - !SHARDING
  5.    dataSources:
  6.      ds0:
  7.        url: jdbc:mysql://localhost:3306/db01?serverTimezone=UTC
  8.        username: root
  9.        password: admin
  10.        connectionTimeoutMilliseconds: 30000
  11.        idleTimeoutMilliseconds: 60000
  12.        maxLifetimeMilliseconds: 1800000
  13.        type: com.alibaba.druid.pool.DruidDataSource
  14.      ds1:
  15.        url: jdbc:mysql://localhost:3306/db02?serverTimezone=UTC
  16.        username: root
  17.        password: admin
  18.        # 其他连接池属性...
  19.    shardingRule:
  20.      tables:
  21.        t_order:
  22.          actualDataNodes: ds$->{0..1}.t_order_$->{0..1}
  23.          databaseStrategy:
  24.            inline:
  25.              shardingColumn: order_id
  26.              algorithmExpression: ds$->{order_id % 2}
  27.          tableStrategy:
  28.            inline:
  29.              shardingColumn: order_id
  30.              algorithmExpression: t_order_$->{order_id % 2}
  31.      masterSlaveRules:
  32.        ms_ds:
  33.          masterDataSourceName: ds0
  34.          slaveDataSourceNames: [ds1]
  35.          loadBalanceAlgorithmType: ROUND_ROBIN
  36. props:
  37.   sql.show: true
复制代码
4.4.两者之间的对比

sharding jdbc是侵入了应用,托管了JDBC,对代码有侵入性。
sharding proxy是直接把数据库请求全部会合到自己身上,自己来做二次处置惩罚,其并没用侵入数据库。
但是proxy显着可以看到是中心化的,请求全部打到了proxy上,是会有性能瓶颈的。
5.留个尾巴

不管是水平拆还是垂直拆,分库分表后一定会存在两个核心问题:


  • 不好join,必要在步伐层面进行join
  • 分布式事件
sharding是如何解决第一个问题的喃?首先sharding会各个节点上进行全表扫描,用类似笛卡尔积的办法聚合成终极的结果。
至于第二个问题,留在后文,我们将深入探究一下sharding生态圈是如何实现分布式事件的。除此之外还有一些尾巴要留在后文继续睁开,包罗:


  • sharding jdbc是如何托管JDBC的
  • sharding proxy是否存在中心化架构带来的性能问题?有没有办法规避?

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

莫张周刘王

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表