Apache ShardingSphere笔记

Apache ShardingSphere

为什么分库分表?

一般的机器(4核16G),单库的mysql并发(QPS+TPS)超过了2K,系统基本就完蛋了。最好是并发量控制在1K左右。这里就引出了一个问题,为什么要分库分表?

分库分表的目的:解决高并发,和数据量大的问题
  1. 高并发的情况下,会造成IO读写频繁,自然就会造成读写缓慢,甚至是宕机,一般单库不要超过2K并发(根据机器配置变化)
  2. 数据量大的问题。主要由于底层索引实现导致,mysql的索引实现为B+tree,数据量过大,会导致索引树十分庞大,造成查询缓慢,第二,innodb的最大存储限制为64TB。

要解决上面的问题,最常见的做法就是分库分表。
分库分表的目的,是将一个表拆成N个表,就是让每个表的数据量控制在一定范围内,保证SQL的性能。一个表的数据量不建议超过500W。

ShardingSphere是什么?

产品官网:
https://shardingsphere.apache.org/index_zh.html

Apache ShardingSphere 是一款开源分布式数据库生态项目,由 JDBC、Proxy 和 Sidecar(规划中) 3 款产品组成。其核心采用可插拔架构,通过组件扩展功能。对上以数据库协议及 SQL 方式提供诸多增强功能,包括数据分片、访问路由、数据安全等;对下原生支持 MySQL、PostgreSQL、SQL Server、Oracle 等多种数据存储引擎。Apache ShardingSphere 项目理念,是提供数据库增强计算服务平台,进而围绕其上构建生态。充分利用现有数据库的计算与存储能力,通过插件化方式增强其核心能力,为企业解决在数字化转型中面临的诸多使用难点,为加速数字化应用赋能。

ShardingSphere 已于2020年4月16日成为 Apache 软件基金会的顶级项目。

在这里插入图片描述

在这里插入图片描述

ShardingJDBC

ShardingJDBC是用来做客户端分库分表的产品。

在这里插入图片描述

ShardingJDBC的核心功能是数据分片和读写分离,通过ShardingJDBC,应用可以透明的使用JDBC访问已经分库分表、读写分离的多个数据源,而不用关心数据源的数量以及数据如何分布。

核心概念

  • 逻辑表:水平拆分的数据库的相同逻辑和数据结构的表的总称。
  • 真实表:在分片数据库中真实存在的物理表。
  • 数据节点:数据分片的最小单元。由数据源名称和数据表组成。
  • 绑定表:分片规则一致的主表和子表。
  • 广播表:也叫公共表,指素有的分片数据源中都存在的表,表结构和表中数据在每个数据库中都完全一致。例如字典表。
  • 分片键:用于分片的数据库字段,是将数据库(数据表)进行水平拆分的关键字段。SQL中若没有分片字段,将会执行全路由,性能会很差。
  • 分片算法:通过分片算法将数据进行分片,支持IN、=、BETWEEN等分片,分片算法需要由应用开发者自行实现,可实现的灵活度极高。
  • 分片策略:真正用于进行分片操作的是分片键+分片算法,这也就是分片策略。在ShardingJDBC中一般采用基于Groovy表达式的inline分片策略,通过一个包含分片键的算法表达式来制定分片策略,如t_user_$->{u_id%8}标识根据u_id模8,分成8张表,表名称为t_user_0到t_user_7。

配置文件实例

# 分库-分表配置
spring:
  shardingsphere:
    datasource:
      # 配置两个数据源,命名为m1和m2
      names: m1,m2
      # m1数据源配置
      m1:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://127.0.0.1:3306/shardingtest01?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false
        username: root
        password: root
      # m2数据源配置
      m2:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://127.0.0.1:3306/shardingtest02?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false
        username: root
        password: root
    sharding:
      tables:
        # 指定逻辑表
        course:
          # 真实数据节点,Groovy表达式 m1、m2库的course_1和course_2表
          actualDataNodes: m$->{1..2}.course_$->{1..2}
          # 指定表的主键生成策略
          keyGenerator:
            column: c_id
            # 雪花算法
            type: SNOWFLAKE
            #雪花算法的一个可选参数
            props:
              worker:
                id: 1
          # 分库策略
          databaseStrategy:
            inline:
              # 选定计算的字段
              shardingColumn: c_id
              # 根据计算的字段算出对应的表名。
              algorithmExpression: m$->{c_id%2+1}
          # 分表策略
          tableStrategy:
            inline:
              # 选定计算的字段
              shardingColumn: c_id
              # 根据计算的字段算出对应的表名。
              algorithmExpression: course_$->{c_id%2+1}

    # 打印sql
    props:
      sql:
        show: true

ShardingJDBC的分片算法

整个分库分表的核心就是在于配置的分片算法。

上述配置文件的databaseStrategy和tableStrategy配置中,我们可以看出,我们采用的都是inline的分片算法即提供一个分片键和一个分片表达式来制定分片算法。这种方式配置简单,功能灵活,是分库分表最佳的配置方式,并且对于绝大多数的分库分片场景来说,都已经非常好用了。但是,如果针对一些更为复杂的分片策略,例如多分片键、按范围分片等场景,inline分片算法就有点力不从心了。

ShardingSphere目前提供了一共五种分片策略:

  • NoneShardingStrategy: 不分片。这种严格来说不算是一种分片策略了。只是ShardingSphere也提供了这么一个配置。
  • InlineShardingStrategy: 最常用的分片方式
    • 配置参数:
      • inline.shardingColumn 分片键;
      • inline.algorithmExpression 分片表达式
    • 实现方式: 按照分片表达式来进行分片。
  • StandardShardingStrategy: 只支持单分片键的标准分片策略。
    • 配置参数:
      • standard.sharding-column 分片键;
      • standard.precise-algorithm-class-name 精确分片算法类名;
      • standard.range-algorithm-class-name 范围分片算法类名;
    • 实现方式:
      • shardingColumn 指定分片键。
      • preciseAlgorithmClassName 指向一个实现了io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm接口的java类名,提供按照 = 或者 IN 逻辑的精确分片
      • rangeAlgorithmClassName 指向一个实现了io.shardingsphere.api.algorithm.sharding.standard.RangeShardingAlgorithm接口的java类名,提供按照Between 条件进行的范围分片。
    • 说明:其中精确分片算法是必须提供的,而范围分片算法则是可选的。
  • ComplexShardingStrategy: 支持多分片键的复杂分片策略。
    • 配置参数:
      • complex.sharding-columns 分片键(多个);
      • complex.algorithm-class-name 分片算法实现类;
    • 实现方式:
      • shardingColumn指定多个分片列。
      • algorithmClassName指向一个实现了org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm接口的java类名。提供按照多个分片列进行综合分片的算法。
  • HintShardingStrategy: 不需要分片键的强制分片策略。这个分片策略,简单来理解就是说,他的分片键不再跟SQL语句相关联,而是用程序另行指定。对于一些复杂的情况,
    例如:
    select count(*) from (select userid from t_user where userid in (1,3,5,7,9)) 这样的SQL语句,就没法通过SQL语句来指定一个分片键。这个时候就可以通过程序,给他另行执行一个分片键,例如在按userid奇偶分片的策略下,可以指定1作为分片键,然后自行指定他的分片策略。
    • 配置参数:

      • hint.algorithm-class-name 分片算法实现类;
    • 实现方式:

      • algorithmClassName指向一个实现了org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm接口的java类名。
      • 在这个算法类中,同样是需要分片键的。而分片键的指定是通过HintManager.addDatabaseShardingValue方法(分库)和HintManager.addTableShardingValue(分表)来指定。使用时要注意,这个分片键是线程隔离的,只在当前线程有效,所以通常建议使用之后立即关闭,或者用try资源方式打开。
    • 注意:Hint分片策略并没有完全按照SQL解析树来构建分片策略,是绕开了SQL解析的,所有对某些比较复杂的语句,Hint分片策略性能有可能会比较好(情况太多了,无法一一分析)。但是,Hint强制路由在使用时有非常多的限制:

      -- 不支持UNION 
      SELECT * FROM t_order1 UNION SELECT * FROM t_order2 INSERT INTO tbl_name (col1, col2,) SELECT col1, col2,FROM tbl_name WHERE col3 = ? 
      -- 不支持多层子查询 
      SELECT COUNT(*) FROM (SELECT * FROM t_order o WHERE o.id IN (SELECT id FROM t_order WHERE status = ?)) 
      -- 不支持函数计算。ShardingSphere只能通过SQL字面提取用于分片的值 
      SELECT * FROM t_order WHERE to_date(create_time, 'yyyy-mm-dd') = '2019-01-01';
      

      从这里也能看出,即便有了ShardingSphere框架,分库分表后对于SQL语句的支持依然是非常脆弱的。


ShardingProxy

ShardingProxy是用来做服务端分库分表的产品。

在这里插入图片描述


ShardingSidecar

ShardingSidecar是针对service mesh定位的一个分库分表插件,目
前在规划中

ShardingJDBC与ShardingProxy的区别

在这里插入图片描述
ShardingJDBC只是客户端的一个工具包,可以理解为一个特殊的JDBC驱动包,所有分库分表逻辑均由业务方自己控制,所以他的功能相对灵活,支持的数据库也非常多,但是对业务侵入大,需要业务方自己定制所有的分库分表逻辑。
而ShardingProxy是一个独立部署的服务,对业务方无侵入,业务方可以像用一个普通的MySQL服务一样进行数据交互,基本上感觉不到后端分库分表逻辑的存在,但是这也意味着功能会比较固定,能够支持的数据库也比较少。这两者各有优劣。

ShardingSphere的SQL使用限制

参见官方文档:
https://shardingsphere.apache.org/document/current/cn/features/sharding/use-norms/sql/

文档中详细说明了许多支持、实验中和暂未支持的SQL类型。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张矜持

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值