潍坊市论坛

首页 » 分类 » 定义 » What数据量巨大还不分库分表Shar
TUhjnbcbe - 2021/8/27 16:41:00

点击上方蓝色“小哈学Java”,选择“设为星标”

回复“资源”获取独家整理的学习资料!

来源:juejin.im/post/

核心概念数据分片读写分离执行流程项目实战

最近项目中不少表的数据量越来越大,并且导致了一些数据库的性能问题。因此想借助一些分库分表的中间件,实现自动化分库分表实现。调研下来,发现Sharding-JDBC目前成熟度最高并且应用最广的Java分库分表的客户端组件。

本文主要介绍一些Sharding-JDBC核心概念以及生产环境下的实战指南,旨在帮助组内成员快速了解Sharding-JDBC并且能够快速将其使用起来。

核心概念

在使用Sharding-JDBC之前,一定是先理解清楚下面几个核心概念。

逻辑表

水平拆分的数据库(表)的相同逻辑和数据结构表的总称。例:订单数据根据主键尾数拆分为10张表,分别是t_order_0到t_order_9,他们的逻辑表名为t_order。

真实表

在分片的数据库中真实存在的物理表。即上个示例中的t_order_0到t_order_9。

数据节点

数据分片的最小单元。由数据源名称和数据表组成,例:ds_0.t_order_0。

绑定表

指分片规则一致的主表和子表。例如:t_order表和t_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。

举例说明,如果SQL为:

SELECTi.*FROMt_orderoJOINt_order_itemiONo.order_id=i.order_idWHEREo.order_idin(10,11);

假设t_order和t_order_item对应的真实表各有2个,那么真实表就有t_order_0、t_order_1、t_order_item_0、t_order_item_1。

在不配置绑定表关系时,假设分片键order_id将数值10路由至第0片,将数值11路由至第1片,那么路由后的SQL应该为4条,它们呈现为笛卡尔积:

SELECTi.*FROMt_order_0oJOINt_order_item_0iONo.order_id=i.order_idWHEREo.order_idin(10,11);SELECTi.*FROMt_order_0oJOINt_order_item_1iONo.order_id=i.order_idWHEREo.order_idin(10,11);SELECTi.*FROMt_order_1oJOINt_order_item_0iONo.order_id=i.order_idWHEREo.order_idin(10,11);SELECTi.*FROMt_order_1oJOINt_order_item_1iONo.order_id=i.order_idWHEREo.order_idin(10,11);

在配置绑定表关系后,路由的SQL应该为2条:

SELECTi.*FROMt_order_0oJOINt_order_item_0iONo.order_id=i.order_idWHEREo.order_idin(10,11);SELECTi.*FROMt_order_1oJOINt_order_item_1iONo.order_id=i.order_idWHEREo.order_idin(10,11);广播表

指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致。适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如:字典表。

数据分片分片键

用于分片的数据库字段,是将数据库(表)水平拆分的关键字段。例:将订单表中的订单主键的尾数取模分片,则订单主键为分片字段。SQL中如果无分片字段,将执行全路由,性能较差。除了对单分片字段的支持,Sharding-JDBC也支持根据多个字段进行分片。

分片算法

通过分片算法将数据分片,支持通过=、=、=、、、BETWEEN和IN分片。分片算法需要应用方开发者自行实现,可实现的灵活度非常高。

目前提供4种分片算法。由于分片算法和业务实现紧密相关,因此并未提供内置分片算法,而是通过分片策略将各种场景提炼出来,提供更高层级的抽象,并提供接口让应用开发者自行实现分片算法。

精确分片算法

对应PreciseShardingAlgorithm,用于处理使用单一键作为分片键的=与IN进行分片的场景。需要配合StandardShardingStrategy使用。

范围分片算法

对应RangeShardingAlgorithm,用于处理使用单一键作为分片键的BETWEENAND、、、=、=进行分片的场景。需要配合StandardShardingStrategy使用。

复合分片算法

对应ComplexKeysShardingAlgorithm,用于处理使用多键作为分片键进行分片的场景,包含多个分片键的逻辑较复杂,需要应用开发者自行处理其中的复杂度。需要配合ComplexShardingStrategy使用。

Hint分片算法

对应HintShardingAlgorithm,用于处理通过Hint指定分片值而非从SQL中提取分片值的场景。需要配合HintShardingStrategy使用。

分片策略

包含分片键和分片算法,由于分片算法的独立性,将其独立抽离。真正可用于分片操作的是分片键+分片算法,也就是分片策略。目前提供5种分片策略。

标准分片策略

对应StandardShardingStrategy。提供对SQL语句中的=,,,=,=,IN和BETWEENAND的分片操作支持。StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。

PreciseShardingAlgorithm是必选的,用于处理=和IN的分片。RangeShardingAlgorithm是可选的,用于处理BETWEENAND,,,=,=分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEENAND将按照全库路由处理。

复合分片策略

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

行表达式分片策略

对应InlineShardingStrategy。使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代码开发,如:t_user_$-{u_id%8}表示t_user表根据u_id模8,而分成8张表,表名称为t_user_0到t_user_7。可以认为是精确分片算法的简易实现

Hint分片策略

对应HintShardingStrategy。通过Hint指定分片值而非从SQL中提取分片值的方式进行分片的策略。

分布式主键

用于在分布式环境下,生成全局唯一的id。Sharding-JDBC提供了内置的分布式主键生成器,例如UUID、SNOWFLAKE。还抽离出分布式主键生成器的接口,方便用户自行实现自定义的自增主键生成器。为了保证数据库性能,主键id还必须趋势递增,避免造成频繁的数据页面分裂。

读写分离

提供一主多从的读写分离配置,可独立使用,也可配合分库分表使用。

同一线程且同一数据库连接内,如有写入操作,以后的读操作均从主库读取,用于保证数据一致性基于Hint的强制主库路由。主从模型中,事务中读写均用主库。执行流程

Sharding-JDBC的原理总结起来很简单:核心由SQL解析=执行器优化=SQL路由=SQL改写=SQL执行=结果归并的流程组成。

项目实战

spring-boot项目实战

引入依赖

dependencygroupIdorg.apache.shardingsphere/groupIdartifactIdsharding-jdbc-spring-boot-starter/artifactIdversion4.0.1/version/dependency数据源配置

如果使用sharding-jdbc-spring-boot-starter,并且数据源以及数据分片都使用shardingsphere进行配置,对应的数据源会自动创建并注入到spring容器中。

spring.shardingsphere.datasource.names=ds0,ds1spring.shardingsphere.datasource.ds0.type=org.apache.

1
查看完整版本: What数据量巨大还不分库分表Shar