欢迎光临散文网 会员登陆 & 注册

ShardingSphere-JDBC:数据分片源码篇

2021-09-02 07:55 作者:做架构师不做框架师  | 我要投稿

前言

在上篇我们已经通过一个简单的demo(ShardingSphere-JDBC:数据分片实战篇)实现了数据分片,在本文我们会通过深入源码分析"ShardingSphere-JDBC"是如何实现改写sql语句的?

也就是说,我们只是写了“SELECT * FROM t_order WHERE order_id = ? AND user_id = ?”,他是如何做到数据改写,路由到“ds1库t_order1表”的。

下面我们会按照上篇实战的demo逐行去分析。

获取数据源

UML时序图

在这里主要就是初始化运行时上下文环境,包括:

  • 初始化数据源。

  • 初始化策略。

  • 初始化执行引擎。

  • 初始化SQL解析器引擎。

  • 初始化事务管理器。

建立连接

UML时序图

在这里的操作主要包括:

  • 获取数据源。

  • 获取运行时上下文环境。

  • 获取事务管理器。

获取预编译 SQL 语句

UML时序图

在这里的操作主要包括:

  • 获取数据库连接。

  • 获取sql语句。

  • 获取ParameterMetaData。

  • 获取PreparedQueryPrepareEngine。

  • 获取PreparedStatementExecutor。

  • 获取BatchPreparedStatementExecutor。

执行sql语句

UML时序图

在这里的操作主要包括:

  • 清除预编译执行器的缓存。

  • 获取执行上下文。

  • 初始预编译执行器的缓存。

  • 合并执行查询。

  • 获取结果集。

  • 释放资源。

在这里我们重点关注的是第2点也就是执行prepare()方法,它在这个方法中是如何改写sql语句的?

首先它会调BasePreparedEngine.prepare()方法,在这里调用executeRoute()方法生成RouteContext(),最终在DataNodeRouter.route()方法中生成RouteContext对象。

注意,在这个对象里有一个属性很重要,就是“routeResult”。在routeResult中有两个属性,分别是originalDataNodes和routeUnits,接下来我们会用到。

生成ExecutionContext,这个是返回值,我们先不管,重点是看一下executeRewrite()方法,从字面意思是就是重写执行语句。

在该方法中,我们只看最后一行也就是rewrite()方法,这个方法只有5行代码,我们看一下只是给结果循环赋值。

我们在看new SQLRouteRewriteEngine().rewrite(),在这里它会获取routeResult的routeUnits属性,进行循环遍历,在循环遍历中有一个很重要的方法“new RouteSQLBuilder(sqlRewriteContext, each)).toSQL()”,toSQL()方法,看方法名的意思是重写sql语句。

我们看一下该方法的源码,这里代码很简单,就是根据条件拼接执行的sql语句,看来我们离真相越来越近了,在这里我们要注意一下“getSQLTokenText()”这个方法,我们点进去看看。

在这里我们调用TableToken.toString()方法,在这里有一个很重要的变量“actualTableName”。这个就是我们表改写。

至此,我们通过对源码的分析终于明白了他是如何实现数据表和数据库的改写了。

他本质就是根据我们设置的分库分表策略对我们写的sql进行重写和对数据库的筛选。

写在最后

好兄弟可以点赞并关注我的公众号“javaAnswer”,全部都是干货。


ShardingSphere-JDBC:数据分片源码篇的评论 (共 条)

分享到微博请遵守国家法律