设为首页 加入收藏

TOP

理论+实战,详解Sharding Sphere-jdbc(一)
2023-07-25 21:40:19 】 浏览:47
Tags:理论 实战 详解 Sharding Sphere-jdbc
摘要:Apache ShardingSphere 是一款分布式的数据库生态系统,它包含两大产品:ShardingSphere-Proxy和ShardingSphere-JDBC。

本文分享自华为云社区《看完这一篇,ShardingSphere-jdbc 实战再也不怕了》,作者:勇哥java实战分享 。

1 ShardingSphere 生态

Apache ShardingSphere 是一款分布式的数据库生态系统,它包含两大产品:

  • ShardingSphere-Proxy
  • ShardingSphere-JDBC

▍一、ShardingSphere-Proxy

ShardingSphere-Proxy 被定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。

代理层介于应用程序与数据库间,每次请求都需要做一次转发,请求会存在额外的时延。

这种方式对于应用非常友好,应用基本零改动,和语言无关,可以通过连接共享减少连接数消耗。

▍二、ShardingSphere-JDBC

ShardingSphere-JDBC 是 ShardingSphere 的第一个产品,也是 ShardingSphere 的前身, 我们经常简称之为:sharding-jdbc 。

它定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。

当我们在 Proxy 和 JDBC 两种模式选择时,可以参考下表对照:

越来越多的公司都在生产环境使用了 sharding-jdbc ,最核心的原因就是:简单(原理简单,易于实现,方便运维)。

2 基本原理

在后端开发中,JDBC 编程是最基本的操作。不管 ORM 框架是 Mybatis 还是 Hibernate ,亦或是 spring-jpa ,他们的底层实现是 JDBC 的模型。

sharding-jdbc 的本质上就是实现 JDBC 的核心接口。

虽然我们理解了 sharding-jdbc 的本质,但是真正实现起来还有非常多的细节,下图展示了 Prxoy 和 JDBC 两种模式的核心流程。

1.SQL 解析

分为词法解析和语法解析。 先通过词法解析器将 SQL 拆分为一个个不可再分的单词。再使用语法解析器对 SQL 进行理解,并最终提炼出解析上下文。

解析上下文包括表、选择项、排序项、分组项、聚合函数、分页信息、查询条件以及可能需要修改的占位符的标记。

2.执行器优化

合并和优化分片条件,如 OR 等。

3.SQL 路由

根据解析上下文匹配用户配置的分片策略,并生成路由路径。目前支持分片路由和广播路由。

4.SQL 改写

将 SQL 改写为在真实数据库中可以正确执行的语句。SQL 改写分为正确性改写和优化改写。

5.SQL 执行

通过多线程执行器异步执行。

6.结果归并

将多个执行结果集归并以便于通过统一的 JDBC 接口输出。结果归并包括流式归并、内存归并和使用装饰者模式的追加归并这几种方式。

本文的重点在于实战层面, sharding-jdbc 的实现原理细节我们会在后续的文章一一给大家呈现 。

3 实战案例

笔者曾经为武汉一家 O2O 公司订单服务做过分库分表架构设计 ,当企业用户创建一条采购订单 , 会生成如下记录:

  • 订单基础表t_ent_order :单条记录
  • 订单详情表t_ent_order_detail :单条记录
  • 订单明细表t_ent_order_item:N 条记录

订单数据采用了如下的分库分表策略:

  • 订单基础表按照 ent_id (企业用户编号) 分库 ,订单详情表保持一致;
  • 订单明细表按照 ent_id (企业用户编号) 分库,同时也要按照 ent_id (企业编号) 分表。

首先创建 4 个库,分别是:ds_0、ds_1、ds_2、ds_3 。

这四个分库,每个分库都包含 订单基础表 , 订单详情表 ,订单明细表 。但是因为明细表需要分表,所以包含多张表。

然后 springboot 项目中配置依赖 :

 <dependency>
 <groupId>org.apache.shardingsphere</groupId>
 <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
 <version>4.1.1</version>
 </dependency>

配置文件中配置如下:

  • 配置数据源,上面配置数据源是: ds0、ds1、ds2、ds3 ;
  • 配置打印日志,也就是:sql.show ,在测试环境建议打开 ,便于调试;
  • 配置哪些表需要分库分表 ,在 shardingsphere.datasource.sharding.tables 节点下面配置:

上图中我们看到配置分片规则包含如下两点:

1)真实节点

对于我们的应用来讲,我们查询的逻辑表是:t_ent_order_item 。

它们在数据库中的真实形态是:t_ent_order_item_0 到 t_ent_order_item_7。

真实数据节点是指数据分片的最小单元,由数据源名称和数据表组成。

订单明细表的真实节点是:ds$->{0..3}.t_ent_order_item_$->{0..7} 。

2)分库分表算法

配置分库策略和分表策略 , 每种策略都需要配置分片字段( sharding-columns )和分片算法

4 基因法 & 自定义复合分片算法

分片算法和阿里开源的数据库中间件 cobar 路由算法非常类似的。

假设现在需要将订单表平均拆分到4个分库 shard0 ,shard1 ,shard2 ,shard3 。

首先将 [0-1023] 平均分为4个区段:[0-255],[256-511],[512-767],[768-1023],然后对字符串(或子串,由用户自定义)做 hash, hash 结果对 1024 取模,最终得出的结果 slot 落入哪个区段,便路由到哪个分库。

看起来分片算法很简单,但我们需要按照订单 ID 查询订单信息时依然需要路由四个分片,效率不高,那么如何优化呢 ?

答案是:基因法 & 自定义复合分片算法。

基因法是指在订单 ID 中携带企业用户编号信息,我们可以在创建订单 order_id 时使用雪花算法,然后将 slot 的值保存在 10位工作机器 ID 里。

通过订单 order_id 可以反查出 slot , 就可以定位该用户的订单数据存储在哪个分片里。

 Integer getWorkerId(Long orderId) {
  Long workerId = (orderId >> 12) & 0x03ff;
 return workerId.intValue();
 }

下图展示了订单 ID 使用雪花算法的生成过程,生成的编号会携带企业用户 ID 信息。

解决了分布式 ID 问题,接下来的一个问题:sharding-jdbc 可否支持按照订单 ID ,企业用户 ID

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇RocketMQ 5.0 多语言客户端的设计.. 下一篇Apache HttpClient 5 笔记: SSL, ..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目