分库分表-sharding-jdbc生产实践

学习思路

  1. 快速启动配置讲解
  2. 五种分片策略
  3. 四种分片算法
  4. 文末有git地址

一、快速启动配置讲解

1、引入jar包

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.0.0-RC2</version>
</dependency>

2、执行spring-cloud-example\sharding-sphere\script目录下sql

3、配置数据源、分片字段、规则等

本文基于mysql

spring:
  shardingsphere:
    datasource:
      names: ds0,ds1
      ds0:
        jdbc-url: jdbc:mysql://localhost:3306/user?userUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
        type: com.zaxxer.hikari.HikariDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        username: root
        password: root
      ds1:
        jdbc-url: jdbc:mysql://localhost:3306/user2019?userUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
        type: com.zaxxer.hikari.HikariDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        username: root
        password: root
        minIdle: 10
        ##其它属性自己加

    sharding:
      ## 设置默认数据源
      default-data-source-name: ds0
      ## 默认分库规则
      default-database-strategy:
        standard:
          precise-algorithm-class-name: com.murphy.shardingjdbc.sharding.PreciseAlgorithm
          shardingColumn: user_id
      tables:
        user:
          ##设置每张表策略,可以覆盖默认策略五规则@see org.apache.shardingsphere.core.yaml.config.sharding.YamlShardingStrategyConfiguration
          databaseStrategy:
            complex:
              shardingColumns: id
              ##复合分片
              algorithmClassName: com.murphy.shardingjdbc.sharding.ComplexAlgorithm
          ## 这段是sharding的表达式,用来确认分片的范围从数据源0-1
          actual-data-nodes: ds$->{0..1}.user
        user_message:
          actual-data-nodes: ds$->{0..1}.user_message


logging:
  level:
    com.murphy.shardingjdbc.mapper: debug

mybatis:
  configuration:
    map-underscore-to-camel-case: true

解释:

  1. names:你分了多少个库就写多少个别名用逗号分隔,注意要和下面的数据源配置保持一致
  2. ds0,ds1,dsn跟平时配置数据源一样
  3. 设置默认的数据源,默认分片规则,分片字段(比如我们用user_id)
  4. 表配置,每个表可单独设置分片规则(比如:我们上面默认按user_id分片,但在user表这个字段的字段名是id,这个时候我们可以为user表单独设置规则)(如配置中的user表)
  5. 如果表使用默认规则只需要配置库对应的表即可(如配置中的user_message表)
  6. 如果表无分片规则,如配置表这样的全局表:无需配置任何规则,只需要在默认数据库有表即可,其它库不需要(匹配不到规则走默认库)(如:config_info表)

4、编写分片规则算法

我们在配置里看到两个分片算法:接下来我们着重看系统内部提供的四种分片算法

com.murphy.shardingjdbc.sharding.PreciseAlgorithm

com.murphy.shardingjdbc.sharding.ComplexAlgorithm

二、五种分片策略讲解

就是我们配置文件里的default-database-strategy.standard和databaseStrategy.complex

我们这里配置的是databaseStrategy:数据源分片策略

当然还有表分片策略,跟数据源配置大同小异,我们这里以数据源为主:tableStrategy

分片策略:分片键+分片算法(分片键:将数据库水平拆分的关键字段;分片算法:把分片键的值按照一定的算法分配到不同的数据源)

主要类:org.apache.shardingsphere.core.yaml.config.sharding.YamlShardingStrategyConfiguration

public class YamlShardingStrategyConfiguration implements YamlConfiguration {
    
    private YamlStandardShardingStrategyConfiguration standard;
    
    private YamlComplexShardingStrategyConfiguration complex;
    
    private YamlHintShardingStrategyConfiguration hint;
    
    private YamlInlineShardingStrategyConfiguration inline;
    
    private YamlNoneShardingStrategyConfiguration none;
}

1、standard(标准分片策略):处理类:org.apache.shardingsphere.core.strategy.route.standard.StandardShardingStrategy

提供对SQL语句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。

StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。

PreciseShardingAlgorithm是必选的,用于处理=和IN的分片。

RangeShardingAlgorithm是可选的,用于处理BETWEEN AND, >, <, >=, <=分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND将按照全库路由处理

2、complex(符合分片策略):处理类:org.apache.shardingsphere.core.strategy.route.complex.ComplexShardingStrategy

提供对SQL语句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。

ComplexShardingStrategy支持多分片键,可根据业务自定义算法实现,提供ComplexKeysShardingAlgorithm分片算法

3、hint(hint表达式分片策略):处理类:org.apache.shardingsphere.core.strategy.route.hint.HintShardingStrategy

通过hint表达式,而非SQL解析做分片,对应算法:HintShardingAlgorithm

4、inline(行表达式分片策略):处理类:org.apache.shardingsphere.core.strategy.route.inline.InlineShardingStrategy

使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代码开发,如: t_user_$->{u_id % 8} 表示t_user表根据u_id模8,而分成8张表,表名称为t_user_0t_user_7

5、none(不分片策略)处理类:org.apache.shardingsphere.core.strategy.route.none.NoneShardingStrategy

查询所有的分片,谨慎使用(配置了分片表,单sql中没有分片键)

三、四种分片算法

分片策略里已经将策略提供的算法进行了对应,可看第三部分

主要在sharding-core-api包下的org.apache.shardingsphere.api.sharding.standard目录下

1、PreciseShardingAlgorithm(精确切分算法):

             用于处理使用单一键作为分片键的=与IN进行分片的场景(项目中的user_id分片,项目中最常用的)

2、RangeShardingAlgorithm(范围切分算法):

            用于处理使用单一键作为分片键的BETWEEN AND、>、<、>=、<=进行分片的场景(这个用于无规律的范围,一般不用)

3、HintShardingAlgorithm(无分片键算法):

             用于处理使用Hint行分片的场景

4、ComplexKeysShardingAlgorithm(复杂键切分算法):

             用于处理使用多键作为分片键进行分片的场景,包含多个分片键的逻辑较复杂,需要应用开发者自行处理其中的复杂度

 

面对复杂分片算法,一般都是初期没设计好,后期分片的时候要用多个字段用业务逻辑补,要根据不同的坑不同设计

四、问题   

1、如果按用户id来分库,那么按手机号查询该怎么处理

  1. 可在数据库和分布式缓存同时维护一套用户id和手机号的映射关系,缓存可设置过期时间防止僵尸用户
  2. 在数据库主库维护一套映射关系,关系表可按手机号取模进行分表

2、如果用户id分片,id是自增的该怎么处理

  1. 可以按用户id区间递增分片,不用洗数据,如db1[1-1000W];db2[1000W-2000W],但存在访问热度问题
  2. 如果用户id用日期生成(雪花算法)可按日期分片,但存在数据分布不均、访问热度问题

 

涉及代码git地址:https://gitee.com/carpentor/spring-cloud-example

公众号主要记录各种源码、面试题、微服务技术栈,帮忙关注一波,非常感谢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章