战狂粗人张

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

一.概念

sharding-jdbc是当当网开源的一款客户端代理中间价。sharding-jdbc包含分库分片和读写分离功能。

对应用的代码没有侵入型,几乎没有任何改动,兼容主流orm框架,主流数据库连接池。目前属于apache的孵化项目shardingSphere,发展迅猛。sharding-jdbc实现读写分离不能实现主从库数据同步。

Sharding-JDBC 采用在 JDBC 层扩展分库分表,支持读写分离,是一个以 jar 形式提供服务的轻量级组件,其核心思路是小而美地完成最核心的事情,

基于 JDBC 层进行分片的好处是轻量、简单、兼容性好以及无需额外的运维工作。缺点是无法跨语言,目前仅支持 Java。

 

二.Sharding-jdbc架构图及原理

sharding-jdbc都有哪些包?

sharding-jdbc-config-parent    配置相关源码
sharding-jdbc-core      核心源码
sharding-jdbc-doc       文档
sharding-jdbc-example:针对各个模块的测试用例代码;
sharding-jdbc-plugin:目前只有KeyGenerator的三种实现;
sharding-jdbc-transaction-parent:事务相关源码;
 

 原理:

1.分片规则配置;

2.JDBC规范重写;

3.SQL解析——SQL路由——SQL改写——SQL执行——结果归并。

因此由于主库和从库同步延迟导致的数据不一致,并不是Sharding-JDBC 的处理范畴。

Mycat原理:

是基于 Proxy,它复写了 MySQL 协议,将 Mycat Server 伪装成一个 MySQL 数据库,而 Sharding-JDBC 是基于 JDBC 的扩展,是以 jar 包的形式提供轻量级服务的。

使用Mycat时不需要改代码,而使用Sharding-Jdbc时需要修改代码。

Sharding-JDBC:不支持子语句,不支持UNION 和 UNION ALL,不支持批量插入,不支持DISTINCT聚合。支持自定义sharding路由。

sharding-jdbc作为一个组件集成在应用内,而mycat则作为一个独立的应用需要单独部署。

 

三.Sharding-jdbc与mycat 相似性以及区别

从设计理念上看确实有一定的相似性。主要流程都是SQL 解析 -> SQL 路由 -> SQL 改写 -> SQL 执行 -> 结果归并。

但架构设计上是不同的。Mycat 是基于 Proxy,它复写了 MySQL 协议,将 Mycat Server 伪装成一个 MySQL 数据库,

而 Sharding-JDBC 是基于 JDBC 的扩展,是以 jar 包的形式提供轻量级服务的。

Mycat作为一个真正的中间件:

(1)基于Mycat实现Mysql读写分离;

(2)Mycat实现数据库切分;

(3)全局表,ER表,分片机制分析;

(4)路由规则得分析;

数据库同步工具:Canal和Binlog。

 

四.Sharding-jdbc支持读写分离

Sharding-JDBC 从 1.3.0 开始支持读写分离。其功能包括:

(1)根据配置区分写库和多个读库,目前暂时只有轮训策略选取读库,可以配合分库分表使用。

(2)通过 Hint 强制指定某次查询走写库。

(3)如果在同一线程且同一数据库连接中有发现 DML 语句,则该 DML 之后的查询都从写库查询,DML 之前的 DQL 语句不受影响,仍然查询读库。其目的是保持同一用户线程的数据一致性。

但限于 Sharding-JDBC 本身设计的考虑,数据库层面的主从切换以及主从数据同步,Sharding-JDBC并不负责。

Sharding-JDBC 定位仍然是轻量级的增强版数据库驱动。因此由于主库和从库同步延迟导致的数据不一致,并不是Sharding-JDBC 的处理范畴。

sharding-jdbc 3.0版本:更名为sharding-sphere

Sharding-Sphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar这3款相互独立的产品组成。

(1)Sharding-JDBC

Sharding-JDBC是Sharding-Sphere的第一个产品,也是Sharding-Sphere的前身。

它定位为轻量级Java框架,在Java的JDBC层提供分库分表、读写分离、数据库治理、柔性事务等服务。

它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

 

(2)Sharding-Proxy

Sharding-Proxy是Sharding-Sphere的第二个产品。

它定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。

Sharding-Proxy屏蔽了底层的分库分表,您可以像使用一个简单的数据库一样来操作分库分表的数据。

目前提供MySQL版本,它可以使用任何兼容MySQL协议的访问客户端(如:MySQL Command Client, MySQLWorkbench等)来访问Sharding-Proxy,进而进行DDL/DML等操作来变更数据,对DBA更加友好。

 

目前分库分表的中间件有两种思想,分别是:

(1)类似 Sharding-JDBC 及 TDDL 的增强版 JDBC 驱动思想;

(2)类似 Mycat 增加中间层,然后在中间层进行分库分表思想;

JDBC 驱动版的优点:

(1)轻量,范围更加容易界定,只是 JDBC 增强,不包括 HA、事务以及数据库元数据管理;

(2)开发的工作量较小,无需关注 nio,各个数据库协议等;

(3)运维无需改动,无需关注中间件本身的 HA;

(4)性能高,JDBC 直连数据库,无需二次转发;

(5)可支持各种基于 JDBC 协议的数据库,如:MySQL,Oralce,SQLServer;

Proxy 版的优点:

(1)可以负责更多的内容,将数据迁移,分布式事务等纳入 Proxy 的范畴;

(2)更有效的管理数据库的连接;

(3)整合大数据思路,将 OLTP 和 OLAP 分离处理;

因此两种方式互相可以互补,建议使用 Java 的团队,且仅 OLTP 的互联网前端操作。有可能会使用多种数据库的情况,可以选择 JDBC层的中间件;

如果需要 OLAP 和 OLTP 混合,加以重量级的操作,如数据迁移,分布式事务等,可以考虑 Proxy 层的中间件。


五.Sharding-JDBC 应用场景

1、适合场景

对于关系型数据库数据量很大的情况,需要进行水平拆库和拆表(即分库和分表),这种场景很适合使用 Sharding-JDBC。

举例说明:

假设有一亿数据的用户库,放在 MySQL 数据库里查询性能会比较低,而采用水平拆库,将其分为 10 个库,根据用户的 ID 模10,

这样数据就能比较平均的分在 10 个库中,每个库只有 1000w 记录,查询性能会大大提升。分片策略类型非常多,大致分为 Hash +Mod、Range、Tag 等。

Sharding-JDBC 还提供了读写分离的能力,用于减轻写库的压力。

此外,Sharding-JDBC 可以用在 JPA 场景中,如 JPA、Hibernate、Mybatis,Spring JDBC Template 等任何 Java 的 ORM 框架。

Java 的 ORM 框架也都是采用 JDBC 与数据库交互。这也是我们选择在 JDBC 层,而非选择一个 ORM 框架进行开发的原因。

我们希望 Sharding-JDBC 可以尽量的兼容所有的 Java 数据库访问层,并且无缝的接入业务应用。

 

2、不合适的场景主要是两方面:

(1)不适合 OLAP 的场景。虽然 Sharding-JDBC 也能做聚合分组查询,但大量的 OLAP 场景,仍然会比较慢,而且复杂的SQL(如子查询等)目前还没有支持。

         这种查询不太适合大数据和高并发的互联网 online 数据库,建议使用合理的 OLTP 查询。

(2)不适合事务强一致的要求。目前 Sharding-JDBC 的事务支持两种,一种是弱 XA,另一种是柔性事务(BASE)。

因为 XA的两阶段或三阶段提交其性能较低,因此互联网公司基本不会采用。而无论是弱 XA还是柔性事务,都无法保证事务在任意时间段完全保证一致,

其中柔性事务能保证数据的最终一致性,但达到最终一致性的时间仍然不可控。因此对于对跨库事务强一致要求很高的场景,需要从设计方面去考虑数据库schema 的合理性。

对于 JTA 事务,目前 Shariding-JDBC 没有实现 JTA 的标准。而且由于在互联网场景下使用 JTA 比较少见,因此暂时不支持 JTA 事务。

 

3、场景

垂直切分:比如订单相关若干表放在订单库,用户相关的表放在用户库,账务明细相关的表放在账务库等。这样就将数据分担到了不同的库上,达到专库专用的效果。

水平切分:

与垂直切分对比,水平切分不是将库表根据业务类型进行分类存储,而是将其按照数据表中某个字段或某几个字段的某种规则切分存储至多个DB中,

在每个库每个表中所包含的只是其中的一部分数据,所有库表加起来的才是全量的业务数据。

这种对数据的切分方式,基本可以保证经过水平切分后的单库单表存储的容量不会太大,从而保证了对单表的增/删/改/查的SQL执行效率和处理能力。

其中,数据的分片规则也是需要重点考虑的,因为它会使得数据分片在多个库表中是否均匀分布存储。

对于,“流水”/“明细”一类的业务数据,通常的业务需求是准实时或者说相对滞后,这些数据是按小时、按日和按月汇总加工处理后生成最终业务需求的数据(比如用户账单、报表和话单)。

此外,由于这一类型的业务数据量普遍较大,比如清算系统的清分明细、云管平台的资源计量明细、订单系统的订单流水和云计算主机资源上报的性能数据等,

如果只是使用单库单表存储的普通方案,那么在单表数据量达到千万级别以上的时候,单库的IO读写能力将持续降低,会成为业务系统整体吞吐量和性能的瓶颈。

对于以上这种“流水”/“明细”类的业务数据,还是推荐使用水平切分的方案从根本上来解决业务上遇到的单表数据过大的问题。

由于该类型的业务数据基本不会涉及跨库的Join连表SQL查询、只需保证分库的本地事务。

MySQL的分区表比较适合用于解决业务数据具有较强时间序列特点,且数据量偏大的场景。

但是,如果SQL的查询条件并非基于时间维度的,那么执行起来的效率并不会有所改观,

同时对于处理单表千万级别以上数据量时,MySQL的分区表方案还是会显得有些“力不从心”。

选择ShardingJdbc组件后,就需要使用该组件来解决实际的问题。这一节主要根据之前提到的“流水”/“明细”一类的业务数据,

前面已经提到了“流水”/“明细”类的业务数据,一般是准实时或者说相对滞后,需要按小时、按日和按月汇总处理后生成最终的业务数据(如账单、报表和话单等)。

我们对“流水”/“明细型”业务数据处理过程中,一般都会涉及数据落库(Insert SQL)、数据分组汇总和分组查询(Select+sum(xxx)+Group By SQL)

以及删除数据表(Delete SQL)等业务处理操作。这里有必要对这几种类型的SQL进行一定的说明:

 

(1)数据落库(Insert SQL):

流水/明细类的数据一般都需要先DB持久化处理;以云计算平台中10W台虚拟机同时产生性能明细数据上报,

如果是单库单表,则这个数据库会进行每小时会有10W次的写请求;如果使用100个分表(分10个库,每库10个表)则每个表平均承受1000次写请求,

每个库平均分担1W次的请求压力,这样子就可以将原来单库单表的写请求压力成倍的减少;

一般业务研发人员使用ShardingJdbc组件,设置合理的数据分片路由规则,即可使得流水/明细类的数据基本均匀落在预先设置的分库分表中。

 

(2)数据分组汇总查询(Select+sum(xxx)+Group By SQL):

由于(a)中持久化至分库分表的业务数据为若干段时间的业务数据,根据业务需求还需要按日,按周或者按月进行累加汇总,

因此有必要对各个分表中的数据执行Select+sum(xxx)+Group By的分组汇总SQL;

ShardingJdbc组件可以完成SQL的解析、改写、路由和结果归并,对于“Select+sum(xxx)+Group By SQL”的语句,

可以遍历设置的多个分库分表,对每个分库分表执行SQL后进行一个结果归并再返回给业务调用方。

 

(3)删除数据表(Delete SQL):

一般业务系统对会通过定时任务来生成明细数据加工处理后的业务数据(比如用户账单、清偿明细、云资源按日按月的话单)。

一旦生成这些有效业务数据后,原来落库的明细也就没有什么业务价值,可以通过任务定期删除或者迁移至历史库的方式来使得分库分表的数据水位量级维持在一定量,

因此就需要涉及对原来存储在分库分表的明细数据进行删除;

ShardingJdbc组件可以根据“Delete SQL”语句中的筛选条件进行规则路由来定位某个分库和分表,否则会删除所有分库中的分表数据。

将这些“加工”后的业务数据批量插入至共享库share_db中,其他定时任务再从共享库中读取并生成最终形式的业务数据(比如,按月的账单、话单或者性能计量值)。

SQL路由的问题。关于主键的生成,每个机器专门有一个id生成器。专门管理。合并查询。

 

4、性能测试报告如下:

(1)使用Sharding-JDBC,性能是大家最关心的问题。在数据量一致的情况下,使用Sharding-JDBC和原生JDBC的性能测试报告如下:

查询操作:Sharding-JDBC的TPS为JDBC的TPS的99.8%。

插入操作:Sharding-JDBC的TPS为JDBC的TPS的90.2%。

更新操作:Sharding-JDBC的TPS为JDBC的TPS的93.1%。

可以看到,Sharding-JDBC在查询中的性能损失非常低,插入和更新略高。

 

(2)将单表的数据拆分为二,放入两个表中,使用Sharding-JDBC和原生JDBC的性能测试报告如下:

查询操作:TPS双库比单库可以增加大约94%的性能。

插入操作:TPS双库比单库可以增加大约60%的性能。

更新操作:TPS双库比单库可以增加大约89%的性能。

结果表明,Sharding-JDBC可有效利用水平扩展大幅度提升性能。

 

posted on 2020-05-25 16:00  战狂粗人张  阅读(1177)  评论(0编辑  收藏  举报