金点分享|数据库系列之GoldenDB数据库分片和重分布

2022-03-15 00:00:00 数据 节点 分片 分布 切分
数据分片是分布式数据库横向扩展的基础,本文主要整理了GoldenDB的数据库分片技术以及数据重分布实现的过程,加深对分片和重分布技术的理解。

1、数据分片规则

数据的切分(sharding)根据切分规则的类型,可以分为垂直切分和水平切分两种模式:
  • 垂直切分是按照不同的表切分到不同的数据库中,适用于业务系统之间耦合度低、业务逻辑清晰的系统
  • 水平切分是根据表中数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库上,对应用来说更为复杂
数据分片是将数据库横向扩展到多个物理节点的分布式技术,具有以下特性:
  • 无限扩展:数据分片水平切分扩展到多个物理节点,理论上支持无限扩展
  • 性能提升:数据分片以后单个数据节点上上的数据集变小,数据库查询的压力变小、查询更快,性能更好;同时水平切分以后查询可以并发执行,提升了系统的吞吐量
  • 高可用:部分分片节点宕机只会影响该部分分片的服务,不会影响整个系统的可用性
在GoldenDB中支持的分片规则和使用场景如下:

1.1 Hash分片
1.1.1 普通hash算法


Hash分片的算法就是对分片键的值进行hash(取模)计算,将计算后的key值映射到不同的服务器上,这样的好处是能将海量的数据均匀的打散在不同的数据节点上。但是普通的hash算法在节点扩容时候,需要对所有的数据进行重新打散,存在大量的数据搬迁。

1.1.2 一致性hash算法
一致性Hash算法早是解决分布式cache提出的,它将整个hash值空间组织成一个虚拟的圆环,根据节点名称的Hash值将服务器节点放置在这个Hash环上,然后根据数据的Key值计算得到其Hash值,接着在Hash环上顺时针查找距离这个Key值的Hash值近的服务器节点,完成Key到服务器的映射查找。
如下图所示,当增加新的节点的时候,只有在圆上增加服务器的逆时针的台服务器上的主键会受到影响。这种算法解决了普通余数Hash算法伸缩性差的问题,可以保证在上线、下线服务器的情况下尽量有多的请求命中原来路由到的服务器。

  • GoldenDB中的hash算法
GoldenDB中使用的是一致性hash算法,它可以尽可能减少节点数变化引起的数据迁移。
  1. 对分片键计算hash值,该hash值会落到0~N的封闭圆环中
  2. 按照分片数量M将hash值均分为M段(M<<N),确定每个分段的值范围
  3. 将落入同一个分段的hash值划分在同一个分片上
  4. 当增加数据节点时候,会使用到hash流式重分布策略,将其它分片的hash值搬动到新增的节点,使得数据均匀分布

    • Hash分片的语法如下:
    Create table t1(a int,b int) distributed by hash(a)(g1,g2,g3);
    1.2 Range分片
    Range分片是按照数据范围分片,常用于按照时间分区或者ID分区来切分,比如按照不同日月的数据分散到不同的库中。Range分片优点在于集群扩容时候只需要添加节点即可,不需要对分片数据进行迁移;同时对于范围查找时,可以通过分片数据快速查询,有效避免跨分片的查询问题。Range分片也有很明显的问题就是出现冷热数据,以及热点数据集中在单个数据节点上出现性能瓶颈。

    • GoldenDB中range分区示例:
    Create table t1(a bigint,b char(6)) distributed by range(a)
    (g1 values less than (1000),g2 values less than (2000),g3 values less than maxvalues);
    1.3 List分片
    List分片是根据不同的枚举值将数据分布在不同的分片上,比如分片键为银行法人,将不同的法人部署在单独的分片上。List分片适合分片键数据较少且固定的场景,但是不同枚举值的数据分布可能出现不均衡的问题。
    • GoldenDB中List分片示例:
    Create table t1(a varchar(4),b char(6)) distributed by list(a)
    (g1 values in(CN),g2 values in (HK));
    1.4 复制表
    复制表是在数据节点保留全量的数据副本,有多节点复制表和单节点复制表,通常用于表的数据读多写少变化不大的场景,比如参数表。复制表的好处是将公共访问表存放在本地数据节点,可以减少跨节点的表数据访问和分布式事务开销,提升SQL的性能。
    • GoldenDB中复制表示例:
    Create table t1(a varchar(4),b char(6)) distributed by duplicate(g1,g2,g3);
    1.5 多级分片
    多级分片是通过多维属性对数据分片进行控制,通常是通过多个字段进行多层次分片,比如通过法人字段进行一级分片,再按照客户类型字段进行二级分片。
    • GoldenDB中多级分片示例:
    Create table t1(a int,b int,c int) distributed by
    case c when 1 then case when b<100 then subdistributed by hash(a) (g1);
    else subdistributed by hash(a) (g2);
    end case;
    when 2 then subdistributed by hash(a) (g3);
    else subdistributed by hash(a) (g4);
    end case;
    1.6 GoldenDB中分区


    当表在横向切分后,单节点的表数据依然很大,可以考虑进行纵向分区,将节点上的分片数据进一步进行切分。这样做的好处是比如一些流水表按照时间进行分区,历史档需要定期清理的时候直接drop历史分区即可;同时业务访问表数据的时候可以减少读取的表数据量,快速定位数据提升性能。

    • GoldenDB中分片+分区示例:
    Create table t1(a int,b int,c int) partition by range (c)
    (partition p1 values less than (20210101), partition p2 values less than (20210201),
    partition p3 values less than (20210301), partition p4 values less than (20210401))
    distributed by hash (a) (g1,g2);

    2、分片路由

    2.1 表分片DDL过程
    整个过程如下:
    1、计算节点将DDL语句下推到每个数据节点分别执行
    2、所有数据节点执行成功后,计算节点通知MDS Server更新元数据信息,并持久化保存到RDB中,算节点本地内存和数据节点中会保存一份全量的表结构信息。
    3、应用访问时会优先从本地读取DDL信息
    2.2 表分片的插入过程
    GoldenDB中分片表的插入过程如下:
    1. 算节点接收到SQL信息后,从MDS获取表的分片信息并解析SQL
    2. 算节点根据分片规则将SQL语句下发到不同的DB分片节点
    3. DB分片节点执行insert语句,并返回执行结果给计算节点算节点

      根据路由规则可以看到,相同的表名在不同的DB数据节点执行的是不同的SQL语句。
      2.3 表分片的查询过程
      GoldenDB中分片表的查询过程如下:
      1. 算节点接收到SQL信息后,从MDS获取表的分片信息并解析SQL
      2. 算节点根据分片规则将查询语句下发到不同的DB分片节点
      3. DB分片节点执行SQL查询语句,并返回结果集给计算节点算节点进行汇总,再返回给客户端

      注:对于不带分片键的查询,会将DB数据节点的查询结果汇总到计算节点,当数据量很大时会出现计算节点OOM情况。

      3、在线重分布

      3.1 数据重分布策略


      GoldenDB支持动态的数据重分布,将数据高效均匀的分布在数据节点上,可实现在线重分布,对业务影响小。重分布过程通过在OMM管理界面以管理任务的形式运行,执行、暂停、继续取消以及异常情况下的重试等,全程可视化控制。同时,数据重分布根据不同的场景有不同的策略,常见的有:增量迭代式数据重分布、HASH策略流式重分布以及RANGE策略重分布优化。

      3.1.1 增量迭代式数据重分布
      增量迭代式数据重分布是一种通用策略,适合所有的数据重分布场景,比如:
      • 分片策略的变更,由hash变为range,复制表变为分片表等
      • 表分片键的变更,由A列调整为B列
      • 分片策略不变,数据节点横向扩容的场景
      增量迭代式数据重分布过程如下图所示:

      实现数据重分布策略的基本策略是针对重分布的表,建立一个与原表字段结构相同但是分发策略为新的分发策略的新表,然后将重分布的数据节点上数据导出并导入到新表,后将新表和旧表的表名切换,总的过程如下:
      1. 按照扩容后的分发策略创建临时表
      2. 导出需要重分布的数据节点的数据,并导入到临时表
      3. 通过binlog数据追平导数期间增量更新的数据到临时表
      4. 将当前表锁住(此时应用不能更新表),并通过binlog追平增量更新数据
      5. 数据校验完毕后,将临时表和新表切换表名,解锁并对外提供服务
      6. 删除旧表的数据
      数据重分布过程中需要注意:
      • 锁表和切换表名的过程中,影响应用的写操作
      • 重分布过程中临时表需要额外的存储空间,重分布操作前需要保证存储空间充足
      3.1.2 Hash策略流式重分布
      Hash策略流式重分布是对通用重分布策略的优化,适用于分片键信息不变,仅进行Hash分片策略横向扩容的场景。
      • 系统中默认包含2048*128个HASH桶,新增数据节点的过程中会并行的从现有的每个分片节点迁移部分数据到新增分片上,确保所有分片数据平均
      • 整个数据迁移的过程是在现有分片数据上动态操作,对磁盘空间没有额外的要求
      • 同步更新MDS和DB节点中表的分片信息

        Hash策略流式重分布还有几个细节问题尚待明确:
        • 分片数据从现有分片移动到新增分片的方法,直接导出再load进去?
        • 数据移动的过程中,应用访问到的数据的节点信息和移动后的数据信息不一致该如何处理?
        • 现有分片数据移动到新增分片的算法,即哪些数据会搬到新的分片节点
        • Hash桶数量是有限的,是否会出现Hash值重复的情况?
        3.2 重分布任务

        3.2.1 创建重分布任务
        重分布任务通过OMM管理平台创建,主要分为三步:
        1. 解析重分布任务:MDS对重分布任务进行检查,解析出新的重分布策略,并根据表的老旧分发规则解析出本次重分布涉及哪些分片
        2. 分解重分布步骤并保存重分布任务:MDS会把重分布任务分解为执行步骤,并保存到元数据RDB中
        3. 创建临时表:MDS向各DB分片发起创建临时表的请求,临时表的命名规则为原表名_时间戳
        重分布上述三个步骤其中一个失败,整个重分布任务即为失败。同时需要注意的是一张表同时只能有两个重分布任务并行执行,并且重分布的表必须有主键,因为在增量同步过程中读取binlog解析增量更新的数据,再根据主键更新到临时表中。
        3.2.2 线下阶段(全量部分)
        数据重分布线下阶段分为全量部分和增量部分,只有完成全量部分后才能进行增量部分操作。全量部分是对整个表进行全量的备份和全量恢复到临时表中,主要包括四个步骤:
        1. 全量备份:使用mysqldump进行全量数据备份
        2. 全量恢复:全量恢复是将备份文件根据新的分发策略切分为多个文件传输到其它DB数据节点,并恢复到临时表中
        3. 全量校验:进行全量数据校验,如果数据出现不一致,需重头发起重分布任务
        4. 创建索引:数据校验完成后会通过计算节点为临时表创建索引
        在数据重分布过程中,MDS会有一个定时器定时检测上述步骤的执行情况,并同步更新保存到RDB中。如果某一步执行失败,会重试该步骤,如果出现数据不一致MDS会重头开始执行任务。重做之前会清理垃圾数据,包括导出的数据文件、拆分的数据文件以及表中已经导入的数据等。

        3.2.3 线下阶段(增量部分)
        数据重分布线下阶段的增量部分是对全量恢复数据期间的binlog解析回放的过程,通过多次追加binlog直到已经基本追平增量数据为止。

        3.2.4 线上阶段
        数据重分布线上阶段是对表写禁止,同时完成全部增量的binlog数据追加,并切换临时表和原表的表名。主要分为以下步骤:
        1. 表写禁止,此时业务只能查询,不能增删改操作
        2. 追加全部的binlog数据
        3. 增量校验数据的一致性,如果不一致则需要重新开始重分布任务
        4. 数据校验完成后切换表名
        5. 恢复表的写访问,对外提供服务
        6. 清理旧表的数据

          至此,GoldenDB分片和数据重分布过程到此结束,其实在线数据重分布的过程和DB2的在线重组过程在实现机制上非常相似。

          来源 https://mp.weixin.qq.com/s/cscotOgBALKxza4AYo2-Gg

相关文章