APP下载

sharding-jdbc初识 中小型专案分库分表的福音

消息来源:baojiabao.com 作者: 发布时间:2024-05-20

报价宝综合消息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应用于jdbc层,对业务层无感知,可以不影响原有逻辑的情况下平滑使用。当然,分散式分库、分表存在她的局限性,分库表最好是单表查询,不建议掺杂多表的join、union等操作。

使用

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

逻辑表

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

真实表

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

jar依赖

这里以springboot专案为例。专案中新增以下starter依赖。

org.apache.shardingsphere

sharding-jdbc-spring-boot-starter

4.0.0-RC1

规则配置

在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!

再来回顾下整个整合过程

首先依赖引入。定义分库分表的分片规则,配置档案表、分片列、分片表示式等修改。数据库建立逻辑表和真实表。按原有方式编写sql程式码逻辑。看上去很简单,但使用时一定要清楚sharding-jdbc的使用场景,过多的sql join切记不要使用,否则多库多表查询时,可能造成框架的笛卡尔集扫描,导致每个库、每张表都被查询,最终严重影响系统性能。

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

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

2020-02-01 03:00:00

相关文章