乐趣区

关于数据库:ShardingSphere-4x-数据分片内核剖析之执行引擎

ShardingSphere 采纳一套自动化的执行引擎,负责将路由和改写实现之后的实在 SQL 平安且高效发送到底层数据源执行。
它不是简略地将 SQL 通过 JDBC 间接发送至数据源执行;也并非间接将执行申请放入线程池去并发执行。它更关注均衡数据源连贯创立以及内存占用所产生的耗费,以及最大限度地正当利用并发等问题。
执行引擎的指标是自动化的均衡资源管制与执行效率。

连贯模式

从资源管制的角度看,业务方拜访数据库的连贯数量该当有所限度。
它可能无效地避免某一业务操作过多的占用资源,从而将数据库连贯的资源耗尽,以致于影响其余业务的失常拜访。
特地是在一个数据库实例中存在较多分表的状况下,一条不蕴含分片键的逻辑 SQL 将产生落在同库不同表的大量实在 SQL,如果每条实在 SQL 都占用一个独立的连贯,那么一次查问无疑将会占用过多的资源。

从执行效率的角度看,为每个分片查问维持一个独立的数据库连贯,能够更加无效的利用多线程来晋升执行效率。
为每个数据库连贯开启独立的线程,能够将 I / O 所产生的耗费并行处理。为每个分片维持一个独立的数据库连贯,还可能防止过早的将查问后果数据加载至内存。
独立的数据库连贯,可能持有查问后果集游标位置的援用,在须要获取相应数据时挪动游标即可。

以后果集游标下移进行后果归并的形式,称之为流式归并,它无需将后果数据全数加载至内存,能够无效的节俭内存资源,进而缩小垃圾回收的频次。
当无奈保障每个分片查问持有一个独立数据库连贯时,则须要在复用该数据库连贯获取下一张分表的查问后果集之前,将以后的查问后果集全数加载至内存。
因而,即便能够采纳流式归并,在此场景下也将进化为内存归并。

一方面是对数据库连贯资源的管制爱护,一方面是采纳更优的归并模式达到对中间件内存资源的节俭,如何解决好两者之间的关系,是 ShardingSphere 执行引擎须要解决的问题。
具体来说,如果一条 SQL 在通过 ShardingSphere 的分片后,须要操作某数据库实例下的 200 张表。
那么,是抉择创立 200 个连贯并行执行,还是抉择创立一个连贯串行执行呢?效率与资源管制又应该如何抉择呢?

针对上述场景,ShardingSphere 提供了一种解决思路。
它提出了连贯模式(Connection Mode)的概念,将其划分为内存限度模式(MEMORY_STRICTLY)和连贯限度模式(CONNECTION_STRICTLY)这两种类型。

内存限度模式

应用此模式的前提是,ShardingSphere 对一次操作所消耗的数据库连贯数量不做限度。
如果理论执行的 SQL 须要对某数据库实例中的 200 张表做操作,则对每张表创立一个新的数据库连贯,并通过多线程的形式并发解决,以达成执行效率最大化。
并且在 SQL 满足条件状况下,优先选择流式归并,以防止出现内存溢出或防止频繁垃圾回收状况。

连贯限度模式

应用此模式的前提是,ShardingSphere 严格控制对一次操作所消耗的数据库连贯数量。
如果理论执行的 SQL 须要对某数据库实例中的 200 张表做操作,那么只会创立惟一的数据库连贯,并对其 200 张表串行解决。
如果一次操作中的分片散落在不同的数据库,依然采纳多线程解决对不同库的操作,但每个库的每次操作依然只创立一个惟一的数据库连贯。
这样即能够避免对一次申请对数据库连贯占用过多所带来的问题。该模式始终抉择内存归并。

内存限度模式实用于 OLAP 操作,能够通过放宽对数据库连贯的限度晋升零碎吞吐量;
连贯限度模式实用于 OLTP 操作,OLTP 通常带有分片键,会路由到繁多的分片,因而严格控制数据库连贯,以保障在线零碎数据库资源可能被更多的利用所应用,是理智的抉择。

自动化执行引擎

ShardingSphere 最后将应用何种模式的决定权交由用户配置,让开发者根据本人业务的理论场景需要抉择应用内存限度模式或连贯限度模式。

这种解决方案将两难的抉择的决定权交由用户,使得用户必须要理解这两种模式的利弊,并根据业务场景需要进行抉择。
这无疑减少了用户对 ShardingSphere 的学习和应用的老本,并非最优计划。

这种一分为二的解决计划,将两种模式的切换交由动态的初始化配置,是不足灵便应答能力的。在理论的应用场景中,面对不同 SQL 以及占位符参数,每次的路由后果是不同的。
这就意味着某些操作可能须要应用内存归并,而某些操作则可能抉择流式归并更优,具体采纳哪种形式不应该由用户在 ShardingSphere 启动之前配置好,而是应该依据 SQL 和占位符参数的场景,来动静的决定连贯模式。

为了升高用户的应用老本以及连贯模式动态化这两个问题,ShardingSphere 提炼出自动化执行引擎的思路,在其外部消化了连贯模式概念。
用户无需理解所谓的内存限度模式和连贯限度模式是什么,而是交由执行引擎依据以后场景主动抉择最优的执行计划。

自动化执行引擎将连贯模式的抉择粒度细化至每一次 SQL 的操作。
针对每次 SQL 申请,自动化执行引擎都将依据其路由后果,进行实时的演算和衡量,并自主地采纳失当的连贯模式执行,以达到资源管制和效率的最优均衡。
针对自动化的执行引擎,用户只需配置 maxConnectionSizePerQuery 即可,该参数示意一次查问时每个数据库所容许应用的最大连接数。

执行引擎分为筹备和执行两个阶段。

筹备阶段

顾名思义,此阶段用于筹备执行的数据。它分为后果集分组和执行单元创立两个步骤。

后果集分组是实现内化连贯模式概念的要害。执行引擎依据 maxConnectionSizePerQuery 配置项,联合以后路由后果,抉择失当的连贯模式。
具体步骤如下:

  1. 将 SQL 的路由后果依照数据源的名称进行分组。
  2. 通过下图的公式,能够取得每个数据库实例在 maxConnectionSizePerQuery 的容许范畴内,每个连贯须要执行的 SQL 路由后果组,并计算出本次申请的最优连贯模式。

在 maxConnectionSizePerQuery 容许的范畴内,当一个连贯须要执行的申请数量大于 1 时,意味着以后的数据库连贯无奈持有相应的数据后果集,则必须采纳内存归并;
反之,当一个连贯须要执行的申请数量等于 1 时,意味着以后的数据库连贯能够持有相应的数据后果集,则能够采纳流式归并。

每一次的连贯模式的抉择,是针对每一个物理数据库的。也就是说,在同一次查问中,如果路由至一个以上的数据库,每个数据库的连贯模式不肯定一样,它们可能是混合存在的状态。

通过上一步骤取得的路由分组后果创立执行的单元。
当数据源应用数据库连接池等管制数据库连贯数量的技术时,在获取数据库连贯时,如果不妥善处理并发,则有肯定几率产生死锁。
在多个申请互相期待对方开释数据库连贯资源时,将会产生饥饿期待,造成穿插的死锁问题。

举例说明,假如一次查问须要在某一数据源上获取两个数据库连贯,并路由至同一个数据库的两个分表查问。
则有可能呈现查问 A 已获取到该数据源的 1 个数据库连贯,并期待获取另一个数据库连贯;而查问 B 也曾经在该数据源上获取到的一个数据库连贯,并同样期待另一个数据库连贯的获取。
如果数据库连接池的容许最大连接数是 2,那么这 2 个查问申请将永恒的期待上来。下图描述了死锁的状况。

ShardingSphere 为了防止死锁的呈现,在获取数据库连贯时进行了同步解决。
它在创立执行单元时,以原子性的形式一次性获取本次 SQL 申请所需的全副数据库连贯,杜绝了每次查问申请获取到局部资源的可能。
因为对数据库的操作十分频繁,每次获取数据库连贯时时都进行锁定,会升高 ShardingSphere 的并发。因而,ShardingSphere 在这里进行了 2 点优化:

  1. 防止锁定一次性只须要获取 1 个数据库连贯的操作。因为每次仅须要获取 1 个连贯,则不会产生两个申请互相期待的场景,无需锁定。

对于大部分 OLTP 的操作,都是应用分片键路由至惟一的数据节点,这会使得零碎变为齐全无锁的状态,进一步晋升了并发效率。
除了路由至单分片的状况,读写拆散也在此领域之内。

  1. 仅针对内存限度模式时才进行资源锁定。在应用连贯限度模式时,所有的查问后果集将在装载至内存之后开释掉数据库连贯资源,因而不会产生死锁期待的问题。

执行阶段

该阶段用于真正的执行 SQL,它分为分组执行和归并后果集生成两个步骤。

分组执行将筹备执行阶段生成的执行单元分组下发至底层并发执行引擎,并针对执行过程中的每个关键步骤发送事件。
如:执行开始事件、执行胜利事件以及执行失败事件。执行引擎仅关注事件的发送,它并不关怀事件的订阅者。
ShardingSphere 的其余模块,如:分布式事务、调用链路追踪等,会订阅感兴趣的事件,并进行相应的解决。

ShardingSphere 通过在执行筹备阶段的获取的连贯模式,生成内存归并后果集或流式归并后果集,并将其传递至后果归并引擎,以进行下一步的工作。

执行引擎的整体构造划分如下图所示。

退出移动版