sharding-jdbc初识,中小型项目分库分表的福音

原创不易,请多多支持!对Java技术感兴趣的童鞋请关注我,后面技术分享更精彩。 

介绍

mysql几乎成为现在后台项目开发的标配。虽然流行,但还是有弊端。单表超过5000w数据时,查询性能将急剧下降。一般业务发展到这个时候,分库分表将是绕不开的话题。但针对一些小的团队,自己设计分库分表逻辑,可能存在难度高、bug多的问题。使用mycat,又有些大材小用。文本将推荐一款小巧、便捷的分库分表组件 --- sharding-jdbc。希望在项目开发中对广大coder有所帮助。

sharding-jdbc最初是当当内部的一个架构组件,经过实际项目的身经百炼,不断抽象提取其通用性,开源出来的一套分库分表框架实现。现已贡献给Apache开源基金会,属于ShardingSphere中的一部分。

sharding-jdbc以jar包依赖的方式集成到项目中,在jdbc层实现sql解析、路由和归并等操作,对业务层透明。仅需简单配置,原有业务代码几乎无需改动即可使用。

架构

由于本文着重推荐sharding-jdbc,对ShardingSphere将不做过多介绍,有兴趣额的童鞋可以去以下官网了解。

https://shardingsphere.apache.org/document/current/cn/overview/

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。
sharding-jdbc初识,中小型项目分库分表的福音

上图中sharding-jdbc应用于jdbc层,对业务层无感知,可以不影响原有逻辑的情况下平滑使用。当然,分布式分库、分表存在她的局限性,分库表最好是单表查询,不建议掺杂多表的join、union等操作。

使用

为了便于演示,这里只以订单表的分表使用作为样例。开始前,请先了解以下两个概念。

逻辑表

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

真实表

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

jar依赖

这里以springboot项目为例。项目中新增以下starter依赖。

<dependency>
<groupid>org.apache.shardingsphere/<groupid>
<artifactid>sharding-jdbc-spring-boot-starter/<artifactid>
<version>4.0.0-RC1/<version>
/<dependency>

规则配置

在spring application.yml文件中添加以下配置

spring:
main:
# sharding-jdbc定义了重复的dataSource数据源bean,启动时必须添加以下值
allow-bean-definition-overriding: true
# sharding-jdbc 分库、分表配置
shardingsphere:
datasource:
names: ds0
ds0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/dctl_demo
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
sharding:
# default-database-strategy:
# inline:
# sharding-column: user_id
# algorithm-expression: ds$->{user_id % 2}
tables:
#分表的逻辑表表名
order:
#分表的物理表节点,数据源ds0下的order0...order9,共10张表
actual-data-nodes: ds0.order$->{0..9}
table-strategy:
inline:
#分片规则对应列,即以user_id值作为分片规则的列
sharding-column: user_id
#分片按user_id列和10取模运算,路由到对应的order0...9的表
algorithm-expression: order$->{user_id % 10}

由于本文仅涉及分表,不涉及分库。所以分库配置default-database-strategy被屏蔽。

有分库需求的对应着规则修改即可。

表结构

新建逻辑表,表结构如下

CREATE TABLE `order` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '订单id',
`user_id` bigint(20) unsigned NOT NULL COMMENT '用户id',
`product_id` bigint(20) unsigned NOT NULL COMMENT '产品id',
`price` decimal(8,2) DEFAULT '0.00' COMMENT '商品价格',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`update_by` varchar(255) DEFAULT NULL COMMENT '更新人',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

按上面逻辑表,新建订单对应的10张物理表。

sharding-jdbc初识,中小型项目分库分表的福音

测试服务

新增订单controller。

sharding-jdbc初识,中小型项目分库分表的福音

启动工程,模拟post请求,构建订单。

sharding-jdbc初识,中小型项目分库分表的福音

响应结果

sharding-jdbc初识,中小型项目分库分表的福音

数据库记录查看

由于分表规则以user_id来分片,并按10取模路由实际表。测试数据是user_id=9,取模后定位到order9这张表中。查看相应表,下图可见数据已经成功写入到相应表中。

sharding-jdbc初识,中小型项目分库分表的福音

总结

到此,整个集成已全部完成,是否感觉对项目业务的侵入性很小?简单、快捷,分库分表so easy!

再来回顾下整个集成过程

  1. 首先依赖引入。
  2. 定义分库分表的分片规则,配置文件表、分片列、分片表达式等修改。
  3. 数据库创建逻辑表和真实表。
  4. 按原有方式编写sql代码逻辑。

看上去很简单,但使用时一定要清楚sharding-jdbc的使用场景,过多的sql join切记不要使用,否则多库多表查询时,可能造成框架的笛卡尔集扫描,导致每个库、每张表都被查询,最终严重影响系统性能。

若业务需求避免不了多表查询,请把join的sql拆成多个,先查分表的值。用查到的值作为条件,再到另一个sql中查询。

最后,希望本文对有耐心看到最后的童鞋有所帮助。有相应问题和意见,欢迎指正。


分享到:


相關文章: