分库分表-Sharding-JDBC


1 概览

Sharding-JDBC是当当网研发的开源分布式数据库中间件。从 3.0 开始,Sharding-JDBC更名为 Sharding-Sphere,之后该项目进入Apache孵化器,4.0之后的版本为Apache版本。 ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、 Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。 它们均提供标准化的数据 分片、分布式事务和数据库治理功能,可适用于Java同构、异构语言、容器、云原生等各种多样化的应 用场景。 咱们目前只需关注Sharding-JDBC,它定位为轻量级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。

 2 功能介绍

Sharding-JDBC可以进行分库分表,同时又可以解决分库分表带来的问题,它的核心功能是:数据分片 和读写分离。

 3 数据分片

数据分片是Sharding-JDBC核心功能,它是指按照某个维度将存放在单一数据库中的数据分散存放至多 个数据库或表中,以达到提升性能瓶颈以及可用性的效果。 数据分片的有效手段是对关系型数据库进行 分库和分表。在使用Sharding-JDBC进行数据分片前,需要了解以下概念:

逻辑表

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

真实表

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

数据节点

数据分片的最小单元。由数据源名称和数据表组成,例: ds_0.t_order_0 。

分片键

用于分片的数据库字段,是将数据库(表)水平拆分的关键字段。例:将订单表中的订单主键的尾数取模 分片,则订单主键为分片字段。 SQL中如果无分片字段,将执行全路由,性能较差。 除了对单分片字 段的支持,ShardingSphere也支持根据多个字段进行分片。

自增主键生成策略

通过在客户端生成自增主键替换以数据库原生自增主键的方式,做到分布式全局主键无重复。

绑定表

 指分片规则一致的主表和子表。例如: 商品信息表 表和 商品描述 表,均按照 商品id 分片,则此两张表 互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积,关联查询效率将大大提升。以上图为 例,如果SQL为:

select p1.*,p2.商品描述 from 商品信息 p1 inner join 商品描述 p2 on p1.id=p2.商品
id;

在不配置绑定表关系时,那么最终执行的SQL应该为4条,它们呈现为笛卡尔积:

select p1.*,p2.商品描述 from 商品信息1 p1 inner join 商品描述1 p2 on p1.id=p2.商品
id
select p1.*,p2.商品描述 from 商品信息2 p1 inner join 商品描述2 p2 on p1.id=p2.商品
id
select p1.*,p2.商品描述 from 商品信息1 p1 inner join 商品描述2 p2 on p1.id=p2.商品
id
select p1.*,p2.商品描述 from 商品信息2 p1 inner join 商品描述1 p2 on p1.id=p2.商品
id

在配置绑定表关系后,最终执行的SQL应该为2条:

select p1.*,p2.商品描述 from 商品信息1 p1 inner join 商品描述1 p2 on p1.id=p2.商品
id
select p1.*,p2.商品描述 from 商品信息2 p1 inner join 商品描述2 p2 on p1.id=p2.商品
id

注意:绑定表之间的分片键要完全相同。

4 读写分离

面对日益增加的系统访问量以及高并发的情况,数据库的性能面临着巨大瓶颈。 数据库的“写”操作是比 较耗时的(例如:写10000条数据到oracle可能要3分钟),而数据库的“读”操作相对较快(例如:从oracle 读10000条数据可能只要5秒钟)。在高并发的情况下,写操作会严重拖累读操作,这是单纯分库分表无 法解决的。 我们可以将数据库拆分为主库和从库,主库只负责处理增删改操作,从库只负责处理查询操作,这就是 读写分离。它能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大的改善。

 我们还可以搞一主多从,这样就可以将查询请求均匀的分散到多个从库,能够进一步的提升系统的处理 能力。 使用多主多从的方式,不但能够提升系统的吞吐量,还能够提升系统的可用性,可以达到在任何 一个数据库宕机,甚至磁盘物理损坏的情况下仍然不影响系统的正常运行。

 读写分离的数据节点中的数据内容是一致的,所以在采用读写分离时,要注意解决主从数据同步的问 题。

Sharding-JDBC读写分离则是根据SQL语义的分析,将读操作和写操作分别路由至主库与从库。它提供 透明化读写分离,让使用方尽量像使用一个数据库一样进行读写分离操作。Sharding-JDBC不提供主从 数据库的数据同步功能,需要采用其他机制支持。