我是如何探索Sharding-JDBC源码的?sharding源码学习从0到1
一、本文主旨
本系列源于对sharding多表路由情况下,性能问题的跟踪、解析,借这次机会,进行一次sharding源码的全面学习和总结。
本篇尝试总结从0到1探索源码的过程,从主体脉络上理清sharding执行流程。
二、一条sql 引起的反思
@Override
<select id="list" resultMap="baseResultMap">
SELECT * FROM user where id in (397768528364568576, 397768518222741505, 397768536589598720)
</select>
当我们使用sharding-jdbc、执行这样一条sql时,user称为虚拟表名,并不真实存在。那么,sharding执行时,内部具体都做了哪些事情呢?
//分表配置
spring.shardingsphere.sharding.tables.user.actual-data-nodes=ds$->{0..1}.user_$->{0..2}
spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id % 3}
spring.shardingsphere.sharding.tables.user.key-generator.column=id
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE
//分库配置
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{id % 2}
spring.shardingsphere.props.sql.show=true
我的实际配置如上:2个库,3张表
三、 寻找Sharding-JDBC 主脉络
1.从sharding源码包结构寻找线索
核心原则:抓主放次,抓大放小
本篇目的:理清sharding主脉络,掌握主要执行过程。
浏览源码包后,对几个主要模块功能定位有了解、筛选出了关键入口类。便于进一步代码跟踪验证。
1)shrding-jdbc-core 对jdbc重写
sharding-jdbc基于适配器模式、实现了jdbc规范,我们可以简单认为,它是一种支持分片的数据库驱动(类似,事实并不是)。
ShardingPreparedStatement#execute
2)sharding-core-parse 对sql解析
sql 解析过程分为词法解析和语法解析。
SQLParsingEngine#parse
3)sharding-core-rewrite 对sql重写
面向逻辑库与逻辑表书写的SQL,不能够直接在真实的数据库执行,SQL改写用于将逻辑SQL改写为在真实数据库中可以正确执行的SQL。
SQLRewriteEngine#rewrite
4)sharding-core-route 对sql路由
根据上下文匹配数据库和表的分片策略,生成路由路径。 对于携带分片键的SQL,根据分片键进行分片路由,不携带分片键的SQL则采用广播路由。
ShardingRouterFactory#newInstance
5)sharding-core-optimize 对sql优化
优化包只是根据上下文和参数对sharding数据模型做了处理,便于后续处理。
OptimizeEngineFactory#newInstance //只是对内部数据模型的优化,不重点关注
6)sharding-core-execute 执行sql
负责将路由和改写完成之后的真实SQL发送到底层数据源执行
SQLExecuteCallback#execute
7)sharding-core-merge 结果归并
将从各个数据节点获取的多个结果集,组合为一个返回给请求客户端。
MergeEngineFactory#newInstance
2.debug关键节点验证执行流
对之前选出来的各个子模块的入口类,断点调试,验证执行流程。
1)ShardingRouterFactory
很显然,我们没有指定强制路由,因次走new ParsingSQLRouter逻辑。
我们在ParsingSQLRouter#parse和ParsingSQLRouter#route方法打上断点、大胆放行。
2)ShardingPreparedStatement#execute
看到这个很高兴、这是sharding对JDBC规范的实现,是我们的老朋友。
@Override
public boolean execute() throws SQLException {
try {
clearPrevious();
//执行sql路由
shard();
initPreparedStatementExecutor();
//调用preparedStatementExecutor执行sql