暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Sharding JDBC

Alleria Windrunner 2020-12-12
257
本篇开始我们来讨论一下MySql数据库的数据分片组件Sharding JDBC。

什么是Sharding JDBC

Apache ShardingSphere(Incubator) 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(规划中)这3款相互独立,却又能够混合部署配合使用的产品组成。


Sharding JDBC架构

Sharding JDBC的整体架构示意图如下:


Sharding JDBC核心概念

关于Sharding JDBC相关的主要概念有以下这些:

  • 逻辑表
  • 真实表
  • 数据节点
  • 绑定表
  • 广播表



逻辑表是指水平拆分的数据库(表)的相同逻辑和数据结构表的总称。真实表则是指在分片的数据库中真实存在的物理表。数据节点指数据分片的最小单元。由数据源名称和数据表组成。绑定表则指指分片规则一致的主表和子表。例如: t_order 表和 t_order_item 表,均按照 order_id 分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提 升。最后广播表指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致。适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表。


分片算法

ShardingJDBC包含分片键和分片算法。分片键是用于分片的数据库字段,是将数据库(表)水平拆分的关键字段。常用的分片算法包括:

  • 精确分片算法
  • 范围分片算法
  • 复合分片算法
  • Hint分片算法

首先来说精确分片算法(PreciseShardingAlgorithm)用于处理使用单一键作为分片键的(=、in)进行分片的场景,需要配合StandardShardingStrategy使用,代码示例如下:

    public class DemoTableShardingAlgorithm implements
    PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> collection,
    PreciseShardingValue<Long> preciseShardingValue) {
    for (String each : collection) { if(each.endsWith(Long.parseLong(preciseShardingValue.getValue().toString()) %2+"")) {
    return each;
    }
    }
    throw new IllegalArgumentException();
    }
    }

    而范围分片算法(RangeShardingAlgorithm)用于处理使用单一键作为分片键的(BETWEEN、AND)进行分片的场景,需要配合StandardShardingStrategy使用,代码示例如下:

      public class MyRangeShardingAlgorithm implements RangeShardingAlgorithm<Long> {
      @Override
      public Collection<String> doSharding(Collection<String> collection,
      RangeShardingValue<Long> rangeShardingValue) {
      log.info("Range collection:" + JSON.toJSONString(collection) +
      ",rangeShardingValue:" + JSON.toJSONString(rangeShardingValue));
      Collection<String> collect = new ArrayList<>();
      Range<Long> valueRange = rangeShardingValue.getValueRange();
      for (Long i = valueRange.lowerEndpoint(); i <=
      valueRange.upperEndpoint(); i++) {
      for (String each : collection) {
      if (each.endsWith(i % collection.size() + "")) {
      collect.add(each);
      } }
      }
      return collect;
      }
      }

      另外复合分片算法(ComplexKeysShardingAlgorithm)用于处理使用多键作为分片键进行分片的场景,包含多个分片键的逻辑较复杂,需要应用开发者自行处理其中的复杂度,需要配合 ComplexShardingStrategy使用,代码示例如下:

        public class MyComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm
        {
        @Override
        public Collection<String> doSharding(Collection<String> collection,
        Collection<ShardingValue> shardingValues) {
        log.info("collection:" + JSON.toJSONString(collection) +
        ",shardingValues:" + JSON.toJSONString(shardingValues));
        Collection<Long> orderIdValues = getShardingValue(shardingValues,
        "order_id");
        Collection<Long> userIdValues = getShardingValue(shardingValues,
        "user_id");
        List<String> shardingSuffix = new ArrayList<>();
        /**例如:根据user_id + order_id 双分片键来进行分表*/
        //Set<List<Integer>> valueResult = Sets.cartesianProduct(userIdValues,
        orderIdValues);
        for (Long userIdVal : userIdValues) {
        for (Long orderIdVal : orderIdValues) {
        String suffix = userIdVal % 2 + "_" + orderIdVal % 2;
        collection.forEach(x -> {
        if (x.endsWith(suffix)) {
        shardingSuffix.add(x);
        } });
        return shardingSuffix;
        }
        private Collection<Long> getShardingValue(Collection<ShardingValue>
        shardingValues, final String key) {
        Collection<Long> valueSet = new ArrayList<>();
        Iterator<ShardingValue> iterator = shardingValues.iterator();
        while (iterator.hasNext()) {
        ShardingValue next = iterator.next();
        if (next instanceof ListShardingValue) {
        } }
        } }
        return valueSet;
        }
        }

        最后Hint分片算法(HintShardingAlgorithm)用于处理使用Hint行分片的场景,需要配合 HintShardingStrategy使用。


        分片策略

        常用的分片策略包括:

        • 标准分片策略
        • 复合分片策略
        • 行表达式分片策略
        • Hint分片策略




        首先标准分片策略(StandardShardingStrategy)提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和 RangeShardingAlgorithm两个分片算法。PreciseShardingAlgorithm是必选的,用于处理=和IN的分片。RangeShardingAlgorithm是可选的,用于处理BETWEEN AND分片,如果不配置 RangeShardingAlgorithm,SQL中的BETWEEN、AND将按照全库路由处理。

        而复合分片策略(ComplexShardingStrategy)提供对SQL语句中的=,IN和BETWEEN、AND的分片操作支持。ComplexShardingStrategy支持多分片键,由于多分片键之间的关系复杂,因此并未进行过多的封装,而是直接将分片键值组合以及分片操作符透传至分片算法,完全由应用开发者实现,提供最大的灵活度。

        行表达式分片策略(InlineShardingStrategy)使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代 码开发。

        行表达式的使用非常直观,只需要在配置中使用 ${ expression } 或 $->{ expression } 标识行表达式即可。目前支持数据节点和分片算法这两个部分的配置,行表达式的内容使用的是Groovy的语法,Groovy能够支持的所有操作,行表达式均能够支持。

        Hint分片策略(HintShardingStrategy)通过Hint而非SQL解析的方式分片的策略。对于分片字段非SQL决定,而由其他外置条件决定的场景,可使用SQL Hint灵活的注入分片字段。


        Sharding JDBC对数据库的支持

        Sharding JDBC不仅仅局限于对MySql的支持,其支持的数据库有很多:

        • MySQL
        • ORACLE
        • SQL Server
        • PostgreSQL
        • mongoDB

        Sharding JDBC的使用

        对于Sharding JDBC的使用也很简单,我们直接在工程中引入jar包,调用API即可:

          <dependency>
          <groupId>org.apache.shardingsphere</groupId>
          <artifactId>sharding-jdbc-core</artifactId>
          <version>3.0.0</version>
          </dependency>

          好了,关于Sharding JDBC的基础概念本篇就介绍到这里。

          文章转载自Alleria Windrunner,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

          评论