大家好,我是一安,今天介绍一下 Sharding-JDBC 实现分库分表的详细配置。

分库分表带来的问题

从单一表、单一库切分成多库、多表对于性能的提升是必然的,但是同时也带来了一些问题:

  • 分布式事务问题:

    由于垂直分库、水平分库,将数据分摊在不同库中,甚至不同的服务器上,势必带来了分布式事务的问题。对于单库单表的事务很好控制,分布式事务的控制却是非常头疼,但是好在现在已经有成熟的解决方案,这个后续再介绍。


  • 跨节点关联 join 问题

    在切分之前关联查询非常简单,直接 SQL JOIN 便能解决,但是切分之后数据分摊在不同的节点上,此时 JOIN 就比较麻烦了,因此切分之后尽量避免 JOIN,解决这一问题的有些方法:

  1. 全局表

这种很好理解,对于一些全局需要关联的表可以在每个数据节点上都存储一份,一般是一些数据字典表(全局表在 Sharding-JDBC 称之为广播表)

  1. 字段冗余

这是一种典型的反范式设计,为了避免关联 JOIN,可以将一些冗余字段保存,比如订单表保存 userId 时,可以将 userName 也一并保存,这样就避免了和 User 表的关联 JOIN 了(字段冗余这种方案存在数据一致性问题)

  1. 数据组装

这种还是比较好理解的,直接不使用 JOIN 关联,分两次查询,从第一次的结果集中找出关联数据的唯一标识,然后再次去查询,最后对得到的数据进行组装(需要进行手动组装,数据很大的情况对 CPU、内存有一定的要求)

  1. 绑定表

对于相互关联的数据节点,通过分片规则将其切分到同一个库中,这样就可以直接使用 SQL 的 JOIN 进行关联查询(Sharding-JDBC 中称之为绑定表,比如订单表和用户表的绑定)


  • 跨节点分页、排序、函数问题

    对于跨数据节点进行分页、排序或者一些聚合函数,筛选出来的仅仅是针对当前节点,比如排序,仅仅能够保证在单一数据节点上是有序,并不能保证在所有节点上都是有序的,需要将各个节点的数据的进行汇总重新手动排序。

Sharding-JDBC 正是 按照上述流程进行分页、排序、聚合


  • 全局主键避重问题

    单库单表一般都是使用的自增主键,但是在切分之后每个自增主键将无法使用,因为这样会导致数据主键重复,因此必须重新设计主键

  1. UUID

UUID 应该是大家最为熟悉的一种方案,优点非常明显本地生成,性能高,缺点也很明显,太长了存储耗空间,查询也非常耗性能,另外 UUID 的无序性将会导致 InnoDB 下的数据位置变动

  1. Snowflake

Twitter 开源的由 64 位整数组成分布式 ID,性能较高,并且在单机上递增

  1. UidGenerator

UidGenerator 是百度开源的分布式 ID 生成器,其基于雪花算法实现。

具体参考:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

  1. Leaf

Leaf 是美团开源的分布式 ID 生成器,能保证全局唯一,趋势递增,但需要依赖关系数据库、Zookeeper 等中间件。

具体参考:https://tech.meituan.com/2017/04/21/mt-leaf.html


  • 数据迁移、扩容问题

    当业务高速发展,面临性能和存储的瓶颈时,才会考虑分片设计,此时就不可避免的需要考虑历史数据迁移的问题。一般做法是先读出历史数据,然后按指定的分片规则再将数据写入到各个分片节点中。此外还需要根据当前的数据量和 QPS,以及业务发展的速度,进行容量规划,推算出大概需要多少分片。
    如果采用数值范围分片,只需要添加节点就可以进行扩容了,不需要对分片数据迁移。如果采用的是数值取模分片,则考虑后期的扩容问题就相对比较麻烦。

分库分表虽然提升了性能,但是在切分过程中一定要考虑上述总结的 5 种问题


Sharding-JDBC 介绍

官网:https://shardingsphere.apache.org

Sharding-JDBC 是当当网研发的开源分布式数据库中间件,从 3.0 开始 Sharding-JDBC 被包含在 Sharding-Sphere 中,之后该项目进入进入 Apache 孵化器,4.0 版本之后的版本为 Apache 版本。

ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈,由 Sharding-JDBC、Sharding-Proxy、Sharding-Sidecar(规划中)组成。

目前我们只需要关注 Sharding-JDBC,后面的两种组件后文介绍。

Sharding-JDBC 的定位是一款轻量级 JAVA 框架,基于 JDBC 实现分库分表,通过 Sharding-JDBC 可以透明的访问已经经过分库、分表的数据源。

Sharding-JDBC 的特性如下:

  1. 适用于任何基于 Java 的 ORM 框架,如:Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC。
  2. 基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP 等。
  3. 支持任意实现 JDBC 规范的数据库。目前支持 MySQL,Oracle,SQLServer 和 PostgreSQL。

Sharding-JDBC 中的一些概念

在介绍 Sharding-JDBC 实战之前需要了解其中的一些概念,如下:

  1. 逻辑表

在对表进行分片后,一张表分成了 n 个表,比如订单表 t_order 分成如下三张表:t_order_1,t_order_2,t_order_3。此时订单表的逻辑表就是 t_order,Sharding-JDBC 在进行分片规则配置时针对的就是这张逻辑表。

  1. 真实表

上述 t_ordr_1,t_order_2,t_order_3 称之为 真实表。

  1. 数据节点

数据分片的最小单元,由数据源名称和表名称组成,比如:ds1.t_order_1。

  1. 分片键

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

  1. 分片算法

通过分片算法将数据分片,支持通过 = 、 BETWEEN 和 IN 分片。

分片算法需要应用方开发者自行实现,可实现的灵活度非常高。包括:精确分片算法 、范围分片算法 ,复合分片算法 等。例如:where order_id = ? 将采用精确分片算法,where order_id in (?,?,?)将采用精确分片算法,where order_id BETWEEN ? and ? 将采用范围分片算法,复合分片算法用于分片键有多个复杂情况。

  1. 分片策略

包含分片键和分片算法,由于分片算法的独立性,将其独立抽离。真正可用于分片操作的是分片键 + 分片算法,也 就是分片策略。

内置的分片策略大致可分为尾数取模、哈希、范围、标签、时间等。由用户方配置的分片策略则更加灵活,常用的使用行表达式配置分片策略,它采用 Groovy 表达式表示,如: tuser$->{u_id % 8} 表示 t_user 表根据 u_id 模 8,而分成 8 张表,表名称为 t_user_0 到 t_user_7 。

  • 标准分片策略

标准分片策略适用于单分片键,此策略支持 PreciseShardingAlgorithm 和 RangeShardingAlgorithm 两个分片算法。

其中 PreciseShardingAlgorithm 是必选的,用于处理 = 和 IN 的分片。RangeShardingAlgorithm 是可选的,用于处理 BETWEEN AND, >, <,>=,<= 条件分片,如果不配置 RangeShardingAlgorithm,SQL 中的条件等将按照全库路由处理。

  • 复合分片策略

复合分片策略,同样支持对 SQL 语句中的 =,>, <, >=, <=,IN 和 BETWEEN AND 的分片操作。不同的是它支持多分片键,具体分配片细节完全由应用开发者实现。

  • 行表达式分片策略

行表达式分片策略,支持对 SQL 语句中的 = 和 IN 的分片操作,但只支持单分片键。这种策略通常用于简单的分片,不需要自定义分片算法,可以直接在配置文件中接着写规则。

torder$->{t_order_id % 4} 代表 t_order 对其字段 t_order_id 取模,拆分成 4 张表,而表名分别是 t_order_0 到 t_order_3。

  • Hint 分片策略

Hint 分片策略,对应上边的 Hint 分片算法,通过指定分片健而非从 SQL 中提取分片健的方式进行分片的策略。

  1. 分布式主键生成策略

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

                                                                                                             文章来源于码猿技术专栏,作者不才陈某

最后说一句(别白嫖,求关注)

如果这篇文章对你有所帮助,或者有所启发的话,帮忙点赞、在看、转发、收藏,你的支持就是我坚持下去的最大动力!下篇进入 Sharding-JDBC 实战



本篇文章来源于微信公众号: 一安未来



微信扫描下方的二维码阅读本文

此作者没有提供个人介绍
最后更新于 2023-07-13