程序员开发实例大全宝库

网站首页 > 编程文章 正文

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

zazugpt 2024-09-08 11:23:56 编程文章 28 ℃ 0 评论
原创不易,请多多支持!对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应用于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张物理表。

测试服务

新增订单controller。

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

响应结果

数据库记录查看

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

总结

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

再来回顾下整个集成过程

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

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

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

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

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表