shardingjdbc原理解释&分片增强设计(附源码)

     1. 背景

     互联网时代数据日益增长,单表已满足不了数据存储,当前涌现很多nosql,newsql数据存储,但目前系统设计概念基于关系数据库,nosql,newsql不能很好适应,基于关系数据库的数据分片显然是目前比较好的解决方案

本文基于sharding-jdbc 3.1.0,针对sharding-jdbc使用上痛点和缺失在源码级别解决和增强,附有使用指南设计

    2. 核心概念

    2.1 逻辑表

     水平拆分的数据库/表的相同逻辑和数据结构表的总称。例:订单数据根据主键尾数拆分为10张表,分别是t_order_0到t_order_9,他们的逻辑表名为t_order。

    2.2 真实表

    在分片的数据库中真实存在的物理表。即上个示例中的t_order_0到t_order_9。

    2.3 绑定表

指分片规则一致的主表和子表。例如:t_order表和t_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。

    2.4 逻辑库/真实库

与逻辑表/真实表类似,同时真实库配置连接参数,也是连接数据源

    3. 架构图

sharding-spring my-sharding的spring boot starter,接管sharding-jdbc启动,构建库表资源模型,初始化自有的分片策略框架,按sharding-jdbc要求初始化库表列表,即data nodes;构建分片数据源

jdbc代理 sharding-jdbc自身实现一套jdbc代理,嵌入分库分表的逻辑,无缝地接入持久层

sql解释/sql路由/sql改写/sql执行/结果归并 sharding-jdbc分片的核心功能模块

apm埋点 手动埋探针,采集sql解释/sql执行执行性能

my-sharding  sharding-jdbc扩展和改造

3.1 shardsphere

下图展现shardingsphere整体模块

 sharding-jdbc/sharding-proxy sharding-sphere呈现的两个产品,sharding-jdbc轻量级分片组件,内部实现一套jdbc标准组件,嵌入分库分表逻辑;sharding-proxy 数据库代理,实现数据库的交互协议

sharding-core sql 改写,解释,执行等数据分片的核心功能,sharding-jdbc/sharding-prox代理壳不一样,共用分片的核心逻辑

sharding-orchetration 分片治理,包括注册中心,配置中心,支持zookeeper分布式配置及配置变更

sharding-transaction 分片事务模块,支持xa,v4.0支持base事务,集成seata

sharding-opentracing 原生支持opentracing 0.30.0,my-sharding重写代码,支持0.31.0,至此新的链路跟踪平台,如zipkin server 5.x

sharding-spring 包括分片的starter,事务starter,由于my-sharding自有的spring boot starter,只使用事务starter

*shardingsphere规划还有一款产品,sharding-sidecar,称为数据库网格,规划中,还没实现

3.2 my-sharding

service 资源服务,库表资源管理api,表的生成和扩充

resource 库表资源模型

strategy 分片策略/算法

function y=f(x), 投射函数,分片键值(x)投射到库/表(y)集合,包括预处理,如,取整,字符串截取,日期截取;投射,取模,=,表达式

springboot starter/springboot starter apm

3.2.1 原生sharding-jdbc问题                                                                                          

  • 原生提供的inline表达式的分片算法,不支持日期,字符等复杂分片算法, 需要自行扩展
  • sql不兼容,哪怕是肉眼看到是路由到一个库,主要是解释器问题
  • opentracing版本0.30,不兼容主流版本的链路服务,如zipkin 5.x

3.2.2 解决方案 

  1. 库表资源建模, 从而掌握库表控制权,分库分表实质库表资源分配,是算法框架的核心,也是在shardingsphere解释不了sql,绕过sharding-jdbc自行生成物理sql的关键
  2. 集合映射分片算法框架
  • sharding-jdbc自身只实现inline表达式的hash分片算法,不能满足实际需要,因此开发了基于集合分布分片算法框架,支持不同维度的分片算法
  • 数据分片抽象成数学概念,就是某个数值或者范围值(即)分片主键值)与特定集合(真实表名称)的映射 f(x)->y, x为分片键值,y真实表集合

    这里要求真实表命名:逻辑表名称{后缀},其中‘后缀‘是集合元素值

  • 库表资源集合分布类型:

      >整数集合,例如,userId取模,年龄范围

      >日期集合,年,月,周,日,时等

      >字符集合,如,“a~z”,“A~Z” 

      >离散点集合,没有顺序数值集合

      >并集合,不连续同类型的集合的并

示例:2个数据库,存放6个月数据,采用分片算法,按月分库,按日分表

考虑到数据分布不均匀,按经验,146月分到一个库,235月分到另一个库

库资源集合,采用离散点集合,[1,4,6], [2,3,5];

表资源集合,采用日集合并集,{[1.1~1.31]&[4.1~4.30]&[6.1~6.30]},{[2.1~1.28]&[3.1~3.31]&[5.1~5.31]}

3.2.3 库表资源模型

库表资源模型

 库表集合模型

库表资源看成连续的集合,分库分表就是根据sql分片键值,映射到具体库和表元素,已实现整形,字符,日期等集合类型和映射

  定位真实表时序

分片路由计算变成,数值定位到哪个集合里(使用并集的情况下)的哪个元素的计算

 1). 分片算法调用资源管理器,传入逻辑表名称查找逻辑表

2). 资源管理器找出逻辑表并返回

3). 分片算法调用逻辑表locate方法,传入分片键值

4). 逻辑表调用资源集合locate方法定位真实表 (集)

5). 数值预处理和值定位计算,预处理:  取模,日期截取;计算:  =,in;range

性能监控apm

apm 应用性能监控,发现性能瓶颈,持续改进

手动埋点,分别在sql解释,sql执行埋点,监控其性能

 apm监控台示例

  1. 执行概览

  开始(rootInvoke)à分析(parsesql)à执行(executesql),下面示例不带分片键条件的select sql,全域扫描,sql路由到所有的库/表执行

  2. 分析阶段

 执行时间,包括自定义标签,逻辑sql

 3. 执行阶段

实际执行sql,实际路由到哪个库,哪个表

代码库

mysharding修改了shardingsphere分片策略源码,为了不混淆原生,修改jar包名字,包结构没变

my-sharding-Java文档类资源-CSDN下载

测试包括,整形/日/月/字符的数据分片场景,例如,按店铺id取模分库+按月分表等,并接入opentracing,apm监

开发指南

分片设计

分库分表成败90%+在于分片设计,分片设计99%的关键在于表分析,分析表之间的关系,sql,选择分片键,

分片键的选择,总会有利于一些sql,而另一些sql因分片不能在单库执行,需要拆分,或使用搜索引擎

分片配置

分片配置使用xml,配置分绑定表,逻辑库,真实库,逻辑表,每部分可以拆开,避免文件过大,编辑阅读困难, 以后扩展到yml,继而支持nacos,zookeeper,apollo等常用的配置中心

示例:

  参考sharding-sphere/my-sharding/my-sharding-resouce-xml工程

创建分片库

分片框架没有提供api直接创建分片库,需手动创建

 创建分片表

  组件提供工具自动创建分片表,如下图:

框架提供工具类,  my-sharding-tools-gentable.jar, 生成分片表

命令行 java -jar my-sharding-tools-gentable.jar gentable [ddl]

其中,ddl是创建表(逻辑表)ddl

系统改造

数据分片后,系统需相应的改造,以适应分片要求

 分离分片/非分片表

分离数据源 

分片后,非分片使用原有数据源;分片表使用分片框架创建的代理数据源

分离服务和dao

服务和dao分离到不同的文件夹,方便扫描,事务切入

sql拆分

分片后,分片键选择,导致除了绑定表外,其他join需要跨库,需要拆分sql分段执行,合并结果,或者使用搜索引擎,宽表查询

手动计算和执行真实sql

sharding-sphere 有限度支持sql,例如,3.1.0 不支持 distinct

但有些情况,sql有分片健作为条件,肉眼可见sql路由到单库,s是可以执行的

例如,

select distinct

t1.partno, t1.uoi

from #{shardingTable}  t1

where t1.parent_id = #{parentId}

假设t1 以parentId分片,而parentId 是查询条件,sql最终路由到单库

my-sharding管理着库表资源,分片算法和数据源,可以轻松地手动计算出实际sql,

  1. ResourceCollection的locate方法,传入分片键值,获得真实库真实表
  2. 替换逻辑sql的逻辑表,活动实际sql
  3. 真实库获得真实数据源,执行实际sql

分布式事务

xa/base

版本3.x 只支持xa,有atomikos实现

版本4+,增加base支持,集成seata实现;xa增加多种实现

分布式事务3个场景:

  1. 非分表/分表的事务 不支持
  2. 多分片表 支持
    1. 广播表
    2. 其他

对于2.2应尽量避免,相比分片前本地事务,xa/base吞吐率/性能都会大幅下降;base最终一致,业务需要识别是否合适

对于2.1广播比表,例如,数据字典,xa是合适方案,时间容忍度高,需要严格保障一致性

搜索引擎

     数据分片后,一些数据跨库,需要拆分sql执行,也可以使用搜索引擎,完整的放到搜索引擎索引,数据查找在搜索引擎进行,同时数据变更使用数据同步,同步到搜索引擎

参考《搜索引擎onesearch设计与实现.docx》

  • 17
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中间件XL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值