当前位置: 首页 > news >正文

ShardingJDBC实战指南

文章目录

  • 分库分表,能不分就不分
    • 为什么要分库分表
    • 分库分表的优势
    • 分库分表的挑战
    • 分库分表类型
    • ShardingJDBC常见数据分片策略
  • 第一个分库分表的案例
    • 建表语句
    • pom依赖
    • yml配置文件

分库分表,能不分就不分

为什么要分库分表

数据库是一个应用中最为核心的价值,之前我们学习过很多对sql的调忧,但是互联网应用越来越大,数据库会频繁的成为整个应用的性能瓶颈,而传统的SQL调优也无法处理海量数据。

  1. 单库承载极限
    • 当单表数据量 > 2000万行(如航空订单表),查询延迟呈指数级上升
    • 示例:某航司订单表年增2000万条,全表扫描耗时从 0.1s → 12s+
  2. 资源竞争风暴
    • 高并发场景(如机票秒杀)下:
      • CPU利用率 > 90% 导致线程阻塞
      • 磁盘IOPS峰值超物理限制

分库分表的优势

分库分表是一种数据库架构优化技术,通过将数据分散到多个数据库或表中,以应对高并发、大数据量场景,提升系统性能和扩展性。

分库分表优点:

  • 提高系统性能:分库分表可以将大型数据库分成多个小型数据库,每个小型数据库只需要处理部分数据,因此可以提高数据库的并发处理能力和查询性能
  • 提高系统可用性:分库分表可以将数据复制到多个数据库中,以提高数据的可用性和可靠性。如果一个数据库崩溃了,其他他数据库可以接管其工作,以保持系统的正常运行。
  • 提高系统可扩展性:分库分表可以使系统更容易扩展。当数据量增加时,只需要增加更多的数据库和表,而不是替换整个数据库,因此系统的可扩展性更高。
  • 提高系统灵活性:分库分表可以根据数据的使用情况,对不同同的数据库和表进行不同的优化。例如,可以将经常使用的数据存储在性能更好的数据库中,或者将特定类型的数据存储在特定的表中以提高系统的灵活性。

应用场景:

数据量过大: 单表数据量超过千万,查询性能下降。

高并发: 单库无法承受大量读写请求。

扩展性需求: 支持水平扩展,动态添加数据库或表。

分库分表的挑战

可能你会说,分库分表嘛,也不是很难,一个库存不下,那就把数据拆分到多个库,一张表数据太多了,就把同一张表的数据拆分到多张。至于怎么做,也不难啊,要操作多个数据库,那么建立多个jdbc连接就行了。要写到多张表,修改下sql语句就行了。

如果你也这么觉得,那么就大错特错了,分库分表也并不是字面意义上的将数据分到多个库或者多个表这么简单,他需要的是一系列的分布式解决方案

常见问题:

  • 主键避重问题:在分库分表环境中,由于表中数据同时存在不同数据库中,某个分区数据库生成的ID就无法保证全局唯一。因此需要单独设计全局主键以避免跨库主键重复问题。
  • 分布式事务问题:原本单机数据库有很好的事务机制能够帮我们保证数据一致性,但是分库分表后,由于数据分布在不同库甚至不同服务器,不可避免会带来分布式事务问间题。
  • 跨库查询归并问题 :跨节点进行查询时,每个分散的数据库中只能查出一部分的数据,这时要对整体结果进行归并时,就会变得非常复杂,比如常见的分页limit、排序order by等操作。
  • 数据迁移问题:当数据库集群需要进行扩缩容时,集群中的数据也需要随着服务进行迁移。如何在不影响业务稳定性的情况下进行数据居迁移也是数据库集群化后需要考虑的问题。
  • SQL路由问题:数据被拆分到多个分放的数据库服务当中,每个数据库服务只能保存一部分的数据。这时,在执行SQL语句检索数据时,如问快速定位到目标数据所在的数据库服务,并将sql语句转到对应的数据库服务中执行,也是提升检索效率必须要考虑的问题。

分库分表类型

分片类型描述优点缺点
垂直分库按业务模块拆分数据库(如用户库、订单库)业务清晰,维护简单跨库事务复杂
水平分库按分片键(如用户 ID)将数据分散到多个数据库支持高并发和大数据量分片算法设计复杂
垂直分表按字段拆分表(如用户信息表、用户扩展表)减少单表大小,优化查询增加开发复杂性
水平分表按分片键将单表数据分散到多个表单库内优化性能表结构重复,维护成本高

ShardingJDBC常见数据分片策略

分布式主键生成方案:SNOWFLAKE / UUID / 主键初始值+步长

分片策略 = 分片键 + 分片算法

分片键:拆分表的字段,比如user表根据id进行拆分,则id就是分片键

分片算法:将数据拆分到不同真实表的算法

精确分片算法:PreciseShardingAlgorithm,使用一个分片键,处理in、=查询,配合StandardShardingStrategy策略范围分片算法:RangeShardingAlgorithm,使用一个分片键,处理between and、>、>=、<、<=查询,,配合StandardShardingStrategy策略复合分片算法:ComplexKeysShardingAlgorithm,使用多个分片键,配合ComplexShardingStrategy策略hint分片算法:HintShardingAlgorithm,强制路由分片,配合HintShardingAlgorithm策略

分片策略:

标准分片策略:精确分片算法(必选,处理in、=)、范围分片算法(可选,处理范围查询),如不设置RangeShardingAlgorithm,处理范围查询时使用全库表路由复合分片策略:使用ComplexKeysShardingAlgorithm处理多分片键Hint分片策略:强制路由分片,使用Hint 指定分片值行表达式分片策略:用Grooy表达式,直接在配置文件中进行分片配置,支持单分片对=、in进行处理不分片策略:不对数据库、表进行分片处理

第一个分库分表的案例

要求:将100条数据插入到以下2个库ds0、ds1,共四张表sys_user0、sys_user1中

建表语句

CREATE DATABASE ds0;
USE ds0;
DROP TABLE IF EXISTS `sys_user0`;
CREATE TABLE `sys_user0` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',`create_user` varchar(100) NOT NULL COMMENT '创建人编码',`update_user` varchar(100) NOT NULL COMMENT '修改人编码',`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记(1 删除 0未删除)',`pos_code` varchar(50) DEFAULT NULL COMMENT '职位编码',`disable_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '启用标记(1 禁用 0启用)',`avatar` varchar(100) DEFAULT NULL COMMENT '头像地址',`email` varchar(50) DEFAULT NULL COMMENT '邮箱',`password` varchar(100) DEFAULT NULL COMMENT '密码',`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',`dept_code` varchar(50) DEFAULT NULL COMMENT '部门编码',`user_phone` varchar(15) DEFAULT NULL COMMENT '手机号',`tenant` varchar(15) DEFAULT NULL COMMENT '租户',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='系统用户表';
DROP TABLE IF EXISTS `sys_user1`;
CREATE TABLE `sys_user1` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',`create_user` varchar(100) NOT NULL COMMENT '创建人编码',`update_user` varchar(100) NOT NULL COMMENT '修改人编码',`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记(1 删除 0未删除)',`pos_code` varchar(50) DEFAULT NULL COMMENT '职位编码',`disable_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '启用标记(1 禁用 0启用)',`avatar` varchar(100) DEFAULT NULL COMMENT '头像地址',`email` varchar(50) DEFAULT NULL COMMENT '邮箱',`password` varchar(100) DEFAULT NULL COMMENT '密码',`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',`dept_code` varchar(50) DEFAULT NULL COMMENT '部门编码',`user_phone` varchar(15) DEFAULT NULL COMMENT '手机号',`tenant` varchar(15) DEFAULT NULL COMMENT '租户',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='系统用户表';CREATE DATABASE ds1;
USE ds1;
DROP TABLE IF EXISTS `sys_user0`;
CREATE TABLE `sys_user0` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',`create_user` varchar(100) NOT NULL COMMENT '创建人编码',`update_user` varchar(100) NOT NULL COMMENT '修改人编码',`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记(1 删除 0未删除)',`pos_code` varchar(50) DEFAULT NULL COMMENT '职位编码',`disable_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '启用标记(1 禁用 0启用)',`avatar` varchar(100) DEFAULT NULL COMMENT '头像地址',`email` varchar(50) DEFAULT NULL COMMENT '邮箱',`password` varchar(100) DEFAULT NULL COMMENT '密码',`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',`dept_code` varchar(50) DEFAULT NULL COMMENT '部门编码',`user_phone` varchar(15) DEFAULT NULL COMMENT '手机号',`tenant` varchar(15) DEFAULT NULL COMMENT '租户',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='系统用户表';
DROP TABLE IF EXISTS `sys_user1`;
CREATE TABLE `sys_user1` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',`create_user` varchar(100) NOT NULL COMMENT '创建人编码',`update_user` varchar(100) NOT NULL COMMENT '修改人编码',`delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记(1 删除 0未删除)',`pos_code` varchar(50) DEFAULT NULL COMMENT '职位编码',`disable_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '启用标记(1 禁用 0启用)',`avatar` varchar(100) DEFAULT NULL COMMENT '头像地址',`email` varchar(50) DEFAULT NULL COMMENT '邮箱',`password` varchar(100) DEFAULT NULL COMMENT '密码',`user_name` varchar(50) DEFAULT NULL COMMENT '用户名',`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',`dept_code` varchar(50) DEFAULT NULL COMMENT '部门编码',`user_phone` varchar(15) DEFAULT NULL COMMENT '手机号',`tenant` varchar(15) DEFAULT NULL COMMENT '租户',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='系统用户表';

pom依赖

    <dependencies><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.1.1</version></dependency></dependencies>

yml配置文件

# 分库分表【数据分布在ds0.sys_user0、ds0.sys_user1、ds1.sys_user0、ds1.sys_user1】
spring:shardingsphere:datasource:names: ds0,ds1ds0:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverjdbc-url: jdbc:mysql://127.0.0.1:3306/ds0?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=falseusername: rootpassword: xxds1:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverjdbc-url: jdbc:mysql://127.0.0.1:3306/ds1?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=falseusername: rootpassword: xxsharding:# 默认数据源default-data-source-name: ds0# 分库分表规则tables:sys_user:# 实际数据节点actual-data-nodes: ds$->{0..1}.sys_user$->{0..1}# 分库策略 - 使用最简单的hash算法database-strategy:inline:sharding-column: idalgorithm-expression: ds$->{id.hashCode().abs() % 2}# 分表策略 - 使用最简单的hash算法table-strategy:inline:sharding-column: idalgorithm-expression: sys_user$->{(id.hashCode().abs() >> 1) % 2}# 主键生成策略key-generator:column: idtype: SNOWFLAKEprops:sql:show: true# 允许内联策略进行范围查询allow:range:query:with:inline:sharding: true

文章转载自:

http://xzndLIfn.mpfLb.cn
http://Wp0HfQVk.mpfLb.cn
http://aAe3yIRT.mpfLb.cn
http://Vv9gqPdg.mpfLb.cn
http://QuJSlwBN.mpfLb.cn
http://o3BeauSK.mpfLb.cn
http://3nXrb0Ui.mpfLb.cn
http://4asXG1jg.mpfLb.cn
http://fBU8Tbwy.mpfLb.cn
http://Dm0ELnXB.mpfLb.cn
http://Dont45dd.mpfLb.cn
http://idkuZnS1.mpfLb.cn
http://RQj7grXI.mpfLb.cn
http://554lGaEa.mpfLb.cn
http://J6W1W7x1.mpfLb.cn
http://YwiRZJv0.mpfLb.cn
http://HGJ1WDw7.mpfLb.cn
http://rJNNb849.mpfLb.cn
http://Tb4G1LjV.mpfLb.cn
http://7PCci4sI.mpfLb.cn
http://yMVYHGfg.mpfLb.cn
http://fgOH9wuY.mpfLb.cn
http://9EibumB0.mpfLb.cn
http://xlU1VdFB.mpfLb.cn
http://4v0uA5U2.mpfLb.cn
http://bR44YGFf.mpfLb.cn
http://fAw6Cjm1.mpfLb.cn
http://R0432Gcy.mpfLb.cn
http://sa73Rtx2.mpfLb.cn
http://ZkfGuvEY.mpfLb.cn
http://www.dtcms.com/a/376418.html

相关文章:

  • 数据库--MySQL数据管理
  • Java全栈学习笔记33
  • 网络学习笔记
  • GitHub每日最火火火项目(9.10)
  • 基于stm32的环境监测系统/智能家居/空气质量监测系统
  • 基于PyQt5和阿里云TTS的语音合成应用开发实战[附源码】
  • Linux的V4L2视频框架学习笔记
  • Android studio安装教程——超详细(含安装包安装教程)
  • 如何将大型音频文件从 iPhone 发送到不同的设备
  • 使用阿里云容器镜像服务 ACR
  • ffmpeg内存模型
  • Android面试指南(八)
  • 不止是进度条:深入PiXSingleGUI的TpSlideProgressBar组件架构设计​
  • Flutter 视频播放器——flick_video_player 介绍与使用
  • 【Java】Hibernate管理Session
  • 【ARMv7】系统复位上电后的程序执行过程
  • Ubuntu引导修复
  • PetaLinux_User_udev
  • 《链表的优雅封装:C++ list 模拟实现与迭代器之美》
  • 基于Redis设计一个高可用的缓存
  • 看涨看跌期权平价公式原理及其拓展
  • Django 基础入门:命令、结构与核心配置全解析
  • 中断系统介绍
  • 算法题 Day5---String类(2)
  • 关于Linux系统调试和性能优化技巧有哪些?
  • 大数据电商流量分析项目实战:Hadoop初认识+ HA环境搭建(二)
  • 软考中级习题与解答——第四章_软件工程(2)
  • AutoTrack-IR-DR200底盘仿真详解:为教育领域打造的高效机器人学习实验平台
  • 介绍 Python Elasticsearch Client 的 ES|QL 查询构建器
  • LeetCode 234. 回文链表