在《DistSQL:像数据库一样使用 Apache ShardingSphere》和《SCTL 涅槃重生:投入 RAL 的怀抱》中,已经为大家介绍了 DistSQL 的设计初衷和语法体系,并通过实战操作展示了 DistSQL 创建分布式数据库表的强大能力,展现了 Apache ShardingSphere 在新形态下的交互体验。
为了让大家对 DistSQL 有更深入的了解,同时能根据需要定制自己的 DistSQL 语法,本篇将为大家解析 DistSQL 的设计开发流程,同时通过实际的场景案例,带领大家实现一个全新的 DistSQL 语法,完成从需求到设计、开发和测试的完整过程。
兰城翔
SphereEx 中间件研发工程师,Apache ShardingSphere contributor,目前专注于 DistSQL 的设计和研发。
何为 DistSQL
DistSQL(Distributed SQL)是 Apache ShardingSphere 特有的操作语言,它与标准 SQL 的使用方式完全一致,用于提供增量功能的 SQL 级别操作能力,以此达到对资源和规则的管理的目的。关于 DistSQL 更多信息参考《DistSQL:像数据库一样使用 Apache ShardingSphere》。
DistSQL 的意义
DistSQL 设计的目的是打破中间件和数据库之间的界限,让开发者像使用数据库一样使用 Apache ShardingSphere。因此 DistSQL 的设计会尽可能契合已有的数据库语法,进而降低学习成本;此外 DistSQL 的作用是对资源和规则进行 SQL 级别的管理,完全替代配置文件也是其优点之一。
开发 DistSQL
准备
* 在开发之前需要对以下工具有所了解
1. ANTRL4 作为解析工具是开发 DistSQL 的基础,关于 ANTLR 4 的使用可以参考 【ANTRL4简明教程】:https://wizardforcel.gitbooks.io/antlr4-short-course/content/
2. 在 IntelliJ IDEA 开发时还需要使用到插件 ANTLR v4, (https://plugins.jetbrains.com/plugin/7358-antlr-v4)作用是对 ANTRL4 定义的语法规则进行测试,使用方式如下:
a. 在对应的规则上选择 Test Rule
b. 在 ANTLR preview 中输入需要校验的语句
在了解语法和插件的基础之上,还需要对 DistSQL 执行流程有一定认识。但 DistSQL 完整的执行流程较为繁琐,而 ShardingSphere 的良好的架构使得开发者不用关注整个流程也能完成 DistSQL 功能的开发。
开发 DistSQL 需要关注的核心流程如下,此处以分片功能为例,不同的功能对应的 Visitor 不同:
实战
在了解 DistSQL 执行流程之后,接下来将实战演示如何开发一条自己的 DistSQL。
在《DistSQL:像数据库一样使用 Apache ShardingSphere》一文中实战演示了使用 DistSQL 创建分片规则,同时使用 show sharding table rules 对分片规则进行了展示。
现在,让我们提出一个新的需求:通过 DistSQL 快速查询各个分片表的分片数量。设计语法如下:
show sharding tables count [from schema] ;
-
环境准备
-
MySQL 服务,包含用于分片的数据库和表
-
Zookeeper 服务,作为注册中心
-
ShardingSphere-Proxy 5.0.0
-
实战演示
1. 创建语法定义
在 src/main/antlr4/imports/sharding/RQLStatement.g4 文件中添加如下的语法定义,添加完成后可以使用 ANTLR v4 对语法定义进行测试。
在添加语法定义时需要考虑该语法中的关键字是否已经定义,此处的 COUNT 为未定义的关键字,需要在 src/main/antlr4/imports/sharding/Keyword.g4 中定义。 在语法定义之后还需将其添加到 ShardingDistSQLStatement.g4 文件中,该文件可以理解为解析的路由。
在完成以上步骤之后,对 shardingsphere-sharding-distsql-parser 进行编译生成语法对应的上下文对象。
2. 完成对语法定义的解析
在处理语法之前还需要在 shardingsphere-distsql-statement 添加一个与该语法定义对应的 DistSQLStatement 对象用于保存语句中的变量属性,例如当前语法定义中的 schemaName 需要保存至 DistSQLStatement 对象中。
在 ShardingSphere 中使用的是 ANTLR 的 Visitor 模式,因此对语法定义的处理需要在 ShardingDistSQLStatementVisitor 中重写 visitShowShardingTableCount 方法,该方法的目的为创建 ShowShardingTablesCountStatement 对象,并将语法中的变量属性保存到 DistSQLStatement 对象中。
shardingsphere-distsql-statement 存在 shardingsphere-sharding-distsql-parser 依赖关系,因此需要对 shardingsphere-distsql-statement 进行编译。
3. 数据处理以及结果返回
数据的处理主要由 Handler 或者 Executor 中的 execute 方法处理,结果主要由 getRowData 方法返回,但是对应不同类型的语法定义在侧重点上可能有所差异。其中结果返回的语法定义使用 DistSQLResultSet 作为结果存储的对象,会在 execute 方法中对结果数据进行组装。
本示例便是这种处理方式,以下为该示例对应的 DistSQLResultSet。
在 ShardingTablesCountResultSet 中 init 方法负责数据的获取与组装,getRowData 方法负责对行数据的返回。此外不难发现该类中还有 getType 方法,该方法属于 TypedSPI 接口,所以 ShardingTablesCountResultSet 还需要在当前模块的 src/main/resources/META-INF/services 目录下增加 org.apache.shardingsphere.infra.distsql.query.DistSQLResultSet 文件来完成 SPI 的注入才能使用,路径与内容如下:
至此该语法定义的功能开发已基本完成。
4. 单元测试以及解析测试
在完成基本的功能开发之后为了保证其持续的可用性需要对新增的类或者方法添加测试用例,对新增的语法添加解析测试,以下为 ShardingTablesCountResultSet 的单元测试。
除了单元测试以外还需要在 shardingsphere-parser-test 中添加对语法定义的解析测试,将输入的 DistSQL 解析成 DistSQLStatement 然后与预期的 TestCase 对象进行比较, 步骤如下。
a. 在
src/main/resources/sql/supported/rql/show.xml 中添加测试的 SQL;
b. 在 src/main/resources/case/rql/show.xml 添加测试的 case;
c. 添加 TestCase 对象用于保存 case 中定义的预期结果;
d. 使用 SQLParserTestCases 类将 TestCase 进行加载;
e. 添加对应的 Assert 对象 ,并将其加入到 ShowRulesStatementAssert 判断中;
f. 执行 DistSQLParserParameterizedTest 中的测试方法,至此测试告一段落。 最后可以在命令行工具中去执行开发完成的 DistSQL 检验功能。
结语
DistSQL 作为 5.0.0 版本发布的新特性之一,将会在此版本基础上持续发力,也希望更多的社区伙伴加入,构造更加完善的语法体系,提供更强大的功能,真正打破中间件与数据库之间的界限。
最后,DistSQL SIG 近日已成立,致力于 DistSQL 特性持续优化,拓展新的使用场景以及宣传答疑,欢迎大家点击这里链接关注,了解 DistSQL 以及 ShardingSphere 项目最新进展。
欢迎添加社区经理微信(ss_assistant_1)进入交流群,与众多 ShardingSphere 爱好者一同交流进步