分库分表中间件 Sharding-JDBC Sharding-Sphere(Sharding-JDBC Sharding-Proxy Sharding-Sidecar(TBD))
http://shardingsphere.io/document/current/cn/overview/
https://github.com/sharding-sphere/sharding-sphere
版本 3.0.0
特点:
定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
适用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer和PostgreSQL。
基本路径:
-
数据分片
-
SQL概念: 逻辑表 真实表 数据节点 逻辑索引
-
分片: 分片键 分片算法 分片策略(精确、范围、复合多键、行内表达式、hint)
-
内核剖析:数据分片主要流程, 核心由SQL解析 => 执行器优化 => SQL路由 => SQL改写 => SQL执行 => 结果归并的流程组成
SQL解析
分为词法解析和语法解析。 先通过词法解析器将SQL拆分为一个个不可再分的单词。再使用语法解析器对SQL进行理解,并最终提炼出解析上下文。 解析上下文包括表、选择项、排序项、分组项、聚合函数、分页信息、查询条件以及可能需要修改的占位符的标记。执行器优化
合并和优化分片条件,如OR等。SQL路由
根据解析上下文匹配用户配置的分片策略,并生成路由路径。目前支持分片路由和广播路由。SQL改写
将SQL改写为在真实数据库中可以正确执行的语句。SQL改写分为正确性改写和优化改写。SQL执行
通过多线程执行器异步执行。结果归并
将多个执行结果集归并以便于通过统一的JDBC接口输出。结果归并包括流式归并、内存归并和使用装饰者模式的追加归并这几种方式。 -
SQL支持: 并不是所有的原生SQL都可以支持,有些DML需要改写 参考 http://shardingsphere.io/document/current/cn/features/sharding/usage-standard/sql/
-
-
读写分离
- 概念: 主库 从库 主从同步 负载均衡
-
数据治理
- 配置中心: 提供统一的配置存储
- 编排治理: 提供服务治理 动态上下线从库 熔断处理 (还未开发完成)
- 支持的注册中心: ETCD ZK SPI
-
应用监控 配合SkyWalking进行监控
-
分布式事务 (还在开发中)
数据分片
SQL:逻辑表 真实表 数据节点 绑定表 逻辑索引
分片:分片键 分片算法(=、BETWEEN和IN 精确分片、范围分片、复合分片、Hint分片) 分片策略(5种) SQL Hint
分库配置等
内核:
http://shardingsphere.io/document/current/cn/features/sharding/principle/rewrite/
改写引擎:
标识符改写
补列 (使用AVG要注意)
分页修正 (分页查询时加了order条件的 要注意limit的改写)
批量拆分 (批量插入时会根据分片键重新改写sql成带路由的sql)
源码:
分表自动配置启动类 SpringBootShardingRuleConfigurationProperties extends YamlShardingRuleConfiguration
YamlShardingRuleConfiguration是分表规则配置类
AbstractBaseShardingAlgorithm
坑:
- 框架在获取PreciseShardingAlgorithm时 是通过反射获取的 所以注册到spring容器没卵用
- 配合MyBatis的批量插入 会多次计算分表策略
Druid连接池的wall防火墙
wall会对sql语句进行分词解析,默认不允许在一个sql中使用多个dml语句
例如,使用MyBatis进行批量更新语句的拼接时,wall会抛出异常信息,‘sql injection violation, multi-statement not allow’
源码研究
解析
采用 Druid 的作为基础解析器的 Sharding-JDBC 解析流程为:(Lexer -> Parser -> AST -> Vistor) -> SharidingContext,其中括号内是 Duird 框架的流程,无法修改。
New Parser 的解析流程简化为:Lexer -> Parser -> SharidingContext。因此在性能以及实现复杂度上都有所突破。