ShardingSphere 学习

7 篇文章 0 订阅

ShardingSphere 学习中遇到的一些概念及总结

先来了解下什么是 ShardingSphere:ShardingSphere 是以分片为核心、其他功能为辅助的中间件。但 Apache ShardingSphere 的定位并不仅仅是用于分片的数据库中间层,它其实是一个可插拔平台。无论分片、读写分离、分布式事务、高可用治理、SQL审计、数据脱敏、数据扩容等功能,都将以 SPI 的形式加入到 ShardingSphere 平台中,ShardingSphere 最终只是一个空白的可以跑的数据库协议+高性能 IO 的骨架。ShardingSphere 的目标不是数据库,而是站在数据库之上的数据库管理层。数据库和 ShardingSphere 的关系,就像 Docker 和 Kubernetes 的关系类似。ShardingSphere 不去负责最终的最底层存储,而是通过更上一层的管理,将数据库管理起来。至于终端存储是什么类型的数据库,ShardingSphere 并不关注。(作者:张亮 链接:https://www.zhihu.com/question/352256403/answer/878733845来源:知乎)

  1. 熔断:阻断 Apache ShardingSphere 和数据库的连接。当某个 ShardingSphere 节点超过负载后,停止该节点对数据库的访问,使数据库能够保持足够的资源为其他节点服务。

  2. 限流:面对超负荷的请求开启限流,以保护部分请求可以得到高质量的响应。

  3. 数据分片

    背景:传统的方式将数据集中存储至单一节点,在性能、可用性和运维成本这三个方面已经难于满足海量数据的场景。

    从性能方面来说:由于关系型数据库大多采用 B+ 树类型的索引,在数据量超过阀值的情况下,索引深度的增加也将使得磁盘访问的 IO 次数增加,进而导致查询性能的下降;同时,高并发访问请求也使得集中式数据库成为系统的最大瓶颈。(传统数据库存储方式不行)

    从可用性的方面来说:服务化的无状态性,能够达到较小成本的随意扩容,这必然导致系统最后的压力都落在了数据库之上。而单一的数据节点,或者简单的主从架构,已经越来越难以承担。数据库的可用性,已成为数据库的关键。

    从运维成本方面考虑:当一个数据库实例中的数据达到阀值以上,对于 DBA 的运维压力就会增大。数据备份和恢复的时间成本都会随着数据量的增大而愈发不可控制。一般来讲,单一数据库实例的数据的阀值在 1 TB 之内,是比较合理的范围。

    在传统的关系型数据库无法满足互联网场景需要的情况下,将数据存储至原生支持分布式的 NoSQL 的尝试越来越多。但 NoSQL 对 SQL 的不兼容性以及生态圈的不完善,使得它们在与关系型数据库的博弈中始终无法完成致命一击,而关系型数据库的地位依然不可撼动。(非关系型数据库也不行)

    数据分片:按照某个维度将存放在单一数据库中的数据分散地存放至多个数据库或表中以达到提升性能瓶颈以及可用性的效果。数据分片的有效手段是对关系型数据库进行分库和分表。分库和分表均可以有效的避免由数据量超过可承受的阀值而产生查询瓶颈。除此之外,分库还可以用于有效的分散对数据库单点的访问量分表虽然无法缓解数据库压力,但能够提供尽量将分布式事务转换为本地事务的可能,一旦涉及到跨库的更新操作,分布式事务往往会使问题变得复杂。但使用多主多从的分片方式,可以有效的避免数据单点,从而提升数据架构的可用性。

    • 通过分库和分表进行数据的拆分来使得各个表的数据量保持在阀值以下,以及对流量进行疏导应对高访问量,是应对高并发和海量数据系统的有效手段。数据分片的拆分方法又分为垂直分片和水平分片。
      • 垂直分片:按照业务拆分的方式称为垂直分片,又称为纵向拆分,它的核心理念是专库专用。在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库中,从而将压力分散至不同的数据库。下图是示例:

      • 垂直分片往往需要对架构和设计进行调整。通常来讲,是来不及应对互联网业务需求快速变化的;而且,它也并无法真正解决单点瓶颈问题。垂直拆分可以缓解数据量和访问带来的问题,但无法根治如果垂直拆分后,表中的数据依然超过单点节点所能承载的阀值,则需要水平分片来进一步处理。

      • 在这里插入图片描述

      • 水平分片:又称为横向拆分。相对于垂直分片,它不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段)根据某种规则将数据分散至多个库或表中,每个分片仅包含数据的一部分。例如:根据主键分片,偶数主键的记录放入 0 库(或表),奇数主键的记录放入 1 库(或表),如下图:

      • 水平分片从理论上突破了单机数据处理的瓶颈,并且扩展相对自由,是数据分片的标准解决方案。

      • 在这里插入图片描述

  4. 挑战:虽然数据分片解决了性能、可用性以及单点备份恢复等问题,但分布式的架构在获得了收益的同时,也引入了新的问题。

    1. 面对如此散乱的分片之后的数据,应用开发工程师和数据库管理员对数据库的操作变的异常繁重就是其中的重要挑战之一。他们需要知道数据从哪个具体的数据库的子表中获得
    2. 另一个挑战是:能够正确的运行在单点数据库中的 SQL,在分片之后的数据库中并不一定能正确运行。如:分表导致表名称的修改,或者分页等操作的不正确处理。
    3. 跨库事务也是分布式的数据库集群要面对的棘手问题。采用合理分表,可以在降低单表数据量的情况下,尽量采用本地事务,善于使用同库不同表可有效避免分布式事务带来的麻烦。在不能避免跨事务的场景,有些业务仍然需要保持事务的一致性。而基于 XA 的分布式事务由于在并发度高的场景中性能无法满足要求,并未被互联网巨头大规模使用,他们大多采用最终一致性的柔性事务代替强一致事务。
  5. Sharding Sphere 就是尽量透明化分库分表带来的影响,让使用方尽量像使用一个数据库一样,使用水平分片之后的数据库集群。

  6. 表:透明化数据分片的关键概念。

    1. 逻辑表:相同结构的水平拆分数据库(表)的逻辑名称,是 SQL 中的逻辑标识。例如:订单数据根据主键尾数拆分为 10 张表,分别是 t_order_0 ~ t_order_9 ,他们的逻辑表名为 t_order。
    2. 真实表:在水平拆库的数据库中真实存在的物理表,即 t_order_0 ~ t_order_9 。
    3. 绑定表:指分片规则一致的表。使用绑定关系进行多表关联查询时,必须使用分片键进行关联,否则会出现笛卡尔积关联,影响效率。
  7. 数据节点:数据分片的最小单元,由数据源名称和真实表组成。如:ds_0.t_order_0。逻辑表与真实表的映射关系,可分为均匀分布和自定义分布两种形式。

    1. 均匀分布:指数据表在每个数据源内呈现均匀分布的态势。如:db0.t_order_0,db0.t_order_1,db1.t_order_0,db1.t_order_1
    2. 自定义分布:指数据表呈现有特定规则的分布,如:db0.t_order0,db0.t_order1, db1.t_order2, db1.t_order3
  8. 分片

    1. 分片键:用于将数据库(表)水平拆分的数据库字段。例如:将订单表中的订单主键的尾数取模分片,则订单主键为分片字段。SQL 中如无分片字段,将执行全路由,性能较差。除了对单片分片字段的支持,ShardingSphere 也支持多个字段的分片。
    2. 分片算法:用于将数据分片的算法,支持 =,>=,<=,<,>,between,IN进行分片,分片算法支持开发着自定义,也支持内置的分片算法语法糖。
  9. 分布式事务(XA)

    1. 背景:数据库事务需要满足 ACID (原子性、一致性、隔离性、持久性)四个特性。
    2. 本地事务:在单一数据节点中,事务仅限于对单一数据库资源的访问控制,称之为本地事务。几乎所有的成熟的关系型数据库都提供了对本地事务的原生支持。但是基于微服务的分布式应用环境下,越来越多的应用场景要求对多个服务的访问以及其相对应的多个数据库资源能纳入到同一个事务中分布式事务应用而生。
    3. 关系型数据库虽然对本地事务提供了完美的 ACID 原生支持,但是在分布式的场景下,他却成为系统性能的桎梏(gu)。如何让数据库在分布式场景下满足 ACID 的特性或寻找响应的替代方案,是分布式事务的重点工作。
    4. 两阶段提交(XA):最早的分布式事务模型是由 X/Open 提出的,简称 XA 协议。基于 XA 协议实现的分布式事务对业务入侵很小。它最大的优点就是对使用方透明,用户可以像使用本地事务一样使用基于 XA 基于协议的分布式事务。也能严格保障事务的 ACID。
    5. 柔性事务:如果将实现了 ACID 的事务要素的事务称为刚性事务的话,那么基于 BASE 事务要素的事务则称为柔性事务。BASE 是基本可用、柔性状态和最终一致性这三个要素的缩写。
  10. 读写分离:

    面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。对于同一时刻有大量并发读操作和较少写操作的类型的应用系统来说,将数据库拆分为主库和从库,主库负责处理事件的增删改操作,从库负责处理查询操作,能够有效避免由数据更新导致的行锁,使性能得到较大提升。

    通过一主多从的配置方式,可以将查询请求的压力分散到多个数据副本。使用多主多从的方式,不但能够提升系统的吞吐量,还能提高系统的可用性,即使其中一个宕机,也不影响系统正常运行。

    与将数据根据分片键打散至各个数据节点的水平分片不同,读写分离则是根据 SQL 语义的分析,将读操作和写操作分别路由至主库和从库

    读写分离的数据节点中的数据内容是一致的,而水平分片的每个数据节点的数据内容却并不相同。将水平分片和读写分离结合使用,能更有效提升系统性能。

    ​ 1. 挑战:读写分离虽然可以提升系统的吞吐量和可用性,但也带来了数据不一致的问题。这包括多个主库之间、主库与从库之间。并且,读写分离也带来了与数据分片同样的问题,使得开发运维困难。下图展示了将数据分片和读写分离联合使用时,数据库集群和应用程序之间的拓扑关系。

在这里插入图片描述

在进行分库分表的实践操作中,还是遇到了很多问题,果然那句话很经典:talk is cheap,let is code。

使用数据库中间件最重要的地方就是配置文件,像其他地方的使用几乎没有区别,所以如何编写配置文件以及不出错是很重要的。下面贴出一份没有出错的分库分表的配置文件:

spring:
  # ShardingSphere 配置项
  shardingsphere:
    datasource:
      # 所有数据源的名字
      names: ds-orders-0, ds-orders-1
      # 订单 orders 数据源配置 00
      ds-orders-0:
        type: com.zaxxer.hikari.HikariDataSource # 使用 Hikari 数据库连接池
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/guitest?useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password:
      # 订单 orders 数据源配置 01
      ds-orders-1:
        type: com.zaxxer.hikari.HikariDataSource # 使用 Hikari 数据库连接池
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/guitest_1?useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password:
    # 分片规则
    sharding:
      tables:
        # orders 表配置
        orders:
#          actualDataNodes: ds-orders-$->{0..1}.orders_$->{0..4} # 映射到 ds-orders 数据源的 orders 表
#          actualDataNodes: ds-orders-0.orders_0, ds-orders-0.orders_2, ds-orders-0.orders_4, ds-orders-0.orders_6, ds-orders-1.orders_1, ds-orders-1.orders_3, ds-orders-1.orders_5, ds-orders-1.orders_7
          actualDataNodes: ds-orders-0.orders_$->{[0,2,4,6]}, ds-orders-1.orders_$->{[1,3,5,7]} # 映射到 ds-orders-0 和 ds-orders-1 数据源的 orders 表们
          key-generator: # 主键生成策略
            column: id
            type: SNOWFLAKE
          database-strategy:
            inline:
              algorithm-expression: ds-orders-$->{user_id % 2}
              sharding-column: user_id
          table-strategy:
            inline:
              algorithm-expression: orders_$->{user_id % 8}
              sharding-column: user_id
        # order_config 表配置
        order_config:
          actualDataNodes: ds-orders-0.order_config # 仅映射到 ds-orders-0 数据源的 order_config 表
    # 拓展属性配置
    props:
      sql:
        show: true # 打印 SQL

# mybatis 配置内容
mybatis:
  config-location: classpath:mybatis-config.xml # 配置 MyBatis 配置文件路径
  mapper-locations: classpath:mapper/*.xml # 配置 Mapper XML 地址
  type-aliases-package: com.gui.shardingdatasource01.dataobject # 配置数据库实体包路径

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值