首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >简单易懂的 MyBatis 分库分表方案

简单易懂的 MyBatis 分库分表方案

作者头像
科技新语
发布于 2025-01-23 10:25:11
发布于 2025-01-23 10:25:11
1580
举报

数据库分库分表除了使用中间件来代理请求分发之外,另外一种常见的方法就是在客户端层面来分库分表

—— 通过适当地包装客户端代码使得分库分表的数据库访问操作代码编写起来也很方便。本文的分库分表方案基于 MyBatis 框架,但是又不同于市面上常用的方案,它们一般都是通过编写复杂的 MyBatis 插件来重写 SQL 语句,这样的插件代码会巨复杂无比,可能最终只有插件的原作者自己可以完全吃透相关代码,给项目的维护性带来一定问题。

本文的方案非常简单易懂,而且也不失使用上的便捷性

。它的设计哲学来源于 Python —— Explicit is better than Implicit,也就是显式优于隐式,它不会将分库分表的过程隐藏起来。

很多分库分表的设计在实现上会尽量将分库分表的逻辑隐藏起来,其实这是毫无必要的。使用者必须知道背后确实进行了分库分表,否则他怎么会无法进行全局的索引查找?他怎么会无法随意进行多表的 join 操作。如果你真的将它当成单表来用,到上线时必然会出大问题。

项目名称叫:shardino,项目地址:https://github.com/pyloque/shardino

接下来我们来看看在本文的方案之下,数据库操作代码的形式是怎样的

帖子表一共分出来 64 个表,不同的记录会各自分发到其中一个表,可以是按 hash 分发,也可以按照日期分发,分发逻辑由用户代码自己来决定。在不同的环境中可以将分表数量设置为不同的值,比如在单元测试下分表设为 4 个,而线上可能需要设置为 64 个。

帖子表又会被分配到多个库,这里就直接取模分配。假设有 4 个帖子库,帖子表总共分出来 64 个表,分别是 post_0、post_1、post_2 一直到 post_63。那么 post_0、post_4、post_8 等分配到 0 号库,post_1、post_5、post_9 等分配到 1 号库,post_2、post_6、post_10 等分配到 2 号库,post_3、post_5、post_11 等分配到 4 号库。

从配置文件中构建 MySQLGroupStore 数据库组对象,这个对象是我们执行 MySQL 操作的入口,通过它可以找到具体的物理的 MySQL 主从数据源。

配置文件 application.properties 如下

这里的数据库组是由多个对等的 Master-Slaves 对构成,每个 Master-Slaves 是由一个主库和多个不同权重的从库构成,Master-Slaves 对的数量就是分库的数量。

mysqlgroup 还有一个特殊的配置选项 slaveEnabled 来控制是否需要从库,从而关闭读写分离,默认是关闭的,这样就不会去构建从库实例相关对象。

post_k 这张表后缀 k 我们称之为 partition number,也就是后续代码中到处在用的 partition 变量,表明当前的记录被分配到对应物理数据表的序号。我们需要根据记录的内容计算出 partition number,再根据 partition number 决定出这条记录所在的物理表属于那个物理数据库,然后对这个物理数据库进行相应的读写操作。

在本例中,帖子表按照 userId 字段 hash 出 64 张表,平均分配到 2 对物理库中,每个物理库包含一个主库和2个从库。

有了 MySQLGroupStore 实例,我们就可以尽情操纵所有数据库了。

从上面的代码中可以看出所有的读写、创建、删除表操作的第一步都是计算出 partition number,然后根据它来选出目标主从库再进一步对目标的数据表进行操作。这里我默认开启了autocommit,所以不需要显式来 session.commit() 了。

在对数据表的操作过程中,又需要将具体的 partition number 传递过去,如此 MyBatis 才能知道具体操作的是哪个分表。

在每一条数据库操作中都必须带上 partition 参数,你可能会觉得这有点繁琐。但是这也很直观,它明确地告诉我们目前正在操作的是哪一个具体的分表。

在 MyBatis 的注解 Mapper 类中,如果方法含有多个参数,需要使用 @Param 注解进行名称标注,这样才可以在 SQL 语句中直接使用相应的注解名称。否则你得使用默认的变量占位符名称 param0、param1 来表示,这就很不直观。

我们将分表的 hash 算法写在实体类 Post 中,这里使用 CRC32 算法进行 hash。

代码中的 partitionFor 方法的参数 num 就是一共要分多少表。如果是按日期来分表,这个参数可能就不需要,直接返回日期的整数就行比如 20190304。

还有最后一个问题是多个带权重的从库是如何做到概率分配的。这里就要使用到 spring-jdbc 自带的 AbstractRoutingDataSource —— 带路由功能的数据源。它可以包含多个子数据源,然后根据一定的策略算法动态挑选出一个数据源来,这里就是使用权重随机。

但是有个问题,我这里只需要这一个类,但是需要引入整个 spring-boot-jdbc-starter 包,有点拖泥带水的感觉。我研究了一下 AbstractRoutingDataSource 类的代码,发现它的实现非常简单,如果就仿照它自己实现了一个简单版的,这样就不需要引入整个包代码了。

还需进一步深入理解其实现代码的可以将 shardino 代码仓库拉到本地跑一跑

里面有单元测试可以运行起来,运行之前需要确保本机安装了 docker 环境

这条指令会启动2对主从库,各1主两从。

在本例中虽然用到了 springboot ,其实也只是用了它方便的依赖注入和单元测试功能,shardino 完全可以脱离 springboot 而独立存在。

shardino 并不是一个完美的开源库,它只是一份实现代码的样板,如果读者使用的是其它数据库或者 MySQL 的其它版本,那就需要自己微调一下代码来适配了。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
一种简单易懂的 MyBatis 分库分表方案
数据库分库分表除了使用中间件来代理请求分发之外,另外一种常见的方法就是在客户端层面来分库分表 —— 通过适当地包装客户端代码使得分库分表的数据库访问操作代码编写起来也很方便。本文的分库分表方案基于 MyBatis 框架,但是又不同于市面上常用的方案,它们一般都是通过编写复杂的 MyBatis 插件来重写 SQL 语句,这样的插件代码会巨复杂无比,可能最终只有插件的原作者自己可以完全吃透相关代码,给项目的维护性带来一定问题。本文的方案非常简单易懂,而且也不失使用上的便捷性。它的设计哲学来源于 Python —— Explicit is better than Implicit,也就是显式优于隐式,它不会将分库分表的过程隐藏起来。
老钱
2019/03/18
2.1K0
一种简单易懂的 MyBatis 分库分表方案
数据库分库分表策略的具体实现方案
:http://blog.csdn.net/xlgen157387/article/details/51331244
Java后端技术
2018/08/09
1.4K0
数据库分库分表策略的具体实现方案
MySQL 分库分表方案
前言 公司最近在搞服务分离,数据切分方面的东西,因为单张包裹表的数据量实在是太大,并且还在以每天60W的量增长。之前了解过数据库的分库分表,读过几篇博文,但就只知道个模糊概念, 而且现在回想起来什么都是模模糊糊的。
每周聚焦
2025/01/23
4130
MySQL 分库分表方案
你分库分表的姿势对么?——详谈水平分库分表
提起分库分表,对于大部分服务器开发来说,其实并不是一个新鲜的名词。随着业务的发展,我们表中的数据量会变的越来越大,字段也可能随着业务复杂度的升高而逐渐增多,我们为了解决单表的查询性能问题,一般会进行分表操作。
2020labs小助手
2021/10/25
3.3K0
你分库分表的姿势对么?——详谈水平分库分表
分库分表初探
面试官:这边有个数据库-单表1千万数据,未来1年还会增长多500万,性能比较慢,说下你的优化思路
Joseph_青椒
2023/08/02
6330
分库分表初探
大厂原来都这么对MySQL分库分表!
传统的将数据集中存储至单一数据节点的解决方案,在容量、性能、可用性和运维成本这三方面难满足海量数据场景。在单库单表数据量超过一定容量水位的情况下,索引树层级增加,磁盘I/O也很可能出现压力,会导致很多问题。
JavaEdge
2022/11/30
4.4K0
大厂原来都这么对MySQL分库分表!
ShardingJdbc分库分表浅谈
在传统的中小公司里面,尤其是以企业内部的办公系统、REP系统,或者体量不是很大的互联网公司里面,搭建一套单库和单表足以应对生产的业务数据量了。而在一些互联网大公司里面,单表每天有上100w的数据业务增量时,就要考虑分库分表的策略了。否则,无论是数据的存储、访问、更新等操作,单库和单表都会影响系统和数据库的性能。
程序大视界
2022/12/19
1.7K0
ShardingJdbc分库分表浅谈
MySQL - 分库分表
主从模式对于写少读多的场景确实非常大的优势,但是总会写操作达到瓶颈的时候,导致性能提不上去。
Vincent-yuan
2021/10/09
6.4K0
MySQL - 分库分表
分库分表路由组件构建方案V1
获取多个数据源我们肯定需要在yaml或者properties中进行配置。所以首先需要获取到配置信息; 定义配置文件中的库和表:
xbhog
2022/10/31
4100
一文快速入门分库分表(必修课)
之前有不少刚入坑 Java 的粉丝留言,想系统的学习一下分库分表相关技术,可我一直没下定决心搞,眼下赶上公司项目在使用 sharding-jdbc 对现有 MySQL 架构做分库分表的改造,所以借此机会出一系分库分表落地实践的文章,也算是自己对架构学习的一个总结。
程序员小富
2020/09/25
5480
一文快速入门分库分表(必修课)
springboot实战之mysql分库分表
把存于一个库的数据分散到多个库中,把存于一个表的数据分散到多个表中。如果说读写分离是为了分散数据库读写操作压力,分库分表就是为了分散存储压力
lyb-geek
2019/10/28
7K0
分库分表专题
分库分表本质上就是为了解决由于库表数据量过大而导致数据库性能降低的问题; 核心操作:
ma布
2024/10/21
2390
分库分表专题
分库分表的常见问题和示例
网上分库分表的资料很多,这里主要是重新整理和梳理一下。如有和其他文章类似片段或解决方案,纯属前人总结或者业内标准。
双鬼带单
2021/11/18
1.5K0
分库分表的常见问题和示例
MySQL分库分表分区解析
- 概念:分区是在数据库内部层面将一张大表的数据分割成多个更小的部分,每个部分称为一个分区。尽管从逻辑上看仍然是一个完整的表,但在物理层面上,数据被分布在不同的物理区块上,这些区块可以位于同一台服务器的不同硬盘分区,或甚至是不同服务器上。MySQL支持多种分区类型,如范围分区、列表分区、哈希分区等。
用户7353950
2024/05/25
3070
MySQL分库分表分区解析
一文读懂数据库优化之分库分表
作者:tayroctang,腾讯 PCG 后台开发工程师 本文从 5W1H 角度介绍了分库分表手段,其在解决如 IO 瓶颈、读写性能、物理存储瓶颈、内存瓶颈、单机故障影响面等问题的同时也带来如事务性、主键冲突、跨库 join、跨库聚合查询等问题。anyway,在综合业务场景考虑,正如缓存的使用一样,本着非必须勿使用原则。如数据库确实成为性能瓶颈时,在设计分库分表方案时也应充分考虑方案的扩展性,或者考虑采用成熟热门的分布式数据库解决方案,如 TiDB。 阅读此文你将了解: 什么是分库分表以及为什么分库分表 如
腾讯技术工程官方号
2022/12/21
1.9K0
一文读懂数据库优化之分库分表
分库分表常见概念解读+Sharding-JDBC实战
之前有不少刚入坑 Java 的粉丝留言,想系统的学习一下分库分表相关技术,可我一直没下定决心搞,眼下赶上公司项目在使用 sharding-jdbc 对现有 MySQL 架构做分库分表的改造,所以借此机会出一系分库分表落地实践的文章,也算是自己对架构学习的一个总结。
Guide哥
2020/11/09
1.9K0
分库分表常见概念解读+Sharding-JDBC实战
【干货】MySQL 分库分表及其平滑扩容方案
众所周知,数据库很容易成为应用系统的瓶颈。单机数据库的资源和处理能力有限,在高并发的分布式系统中,可采用分库分表突破单机局限。本文总结了分库分表的相关概念、全局ID的生成策略、分片策略、平滑扩容方案、以及流行的方案。
IT技术小咖
2019/06/26
11K1
【干货】MySQL 分库分表及其平滑扩容方案
好好的系统,为什么要分库分表?
今天是《分库分表 ShardingSphere 原理与实战》系列的开篇文章,之前写过几篇关于分库分表的文章反响都还不错,到现在公众号:程序员小富后台不断的有人留言、咨询分库分表的问题,我也没想到大家对于分库分表的话题会这么感兴趣,可能很多人的工作内容业务量较小很难接触到这方面的技能。这个系列在我脑子里筹划了挺久的,奈何手说啥也不干活,就一直拖到了现在。
程序员小富
2022/11/25
9610
分库分表方案
首先回答一下为什么要分库分表,答案很简单:数据库出现性能瓶颈。用大白话来说就是数据库快扛不住了。
长乐坡头
2024/01/10
3530
分库分表方案总结,学不会你捶我!
不管是 IO 瓶颈,还是 CPU 瓶颈,最终都会导致数据库的活跃连接数增加,进而逼近甚至达到数据库可承载活跃连接数的阈值。
架构师修炼
2020/07/19
7870
相关推荐
一种简单易懂的 MyBatis 分库分表方案
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档