首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
不吹不黑,自己拥有服务器一定要做这些事情
首先,随着我家孩子的视频相片越来越多,我渐渐意识到,想要拥有一个快速备份并且随时可以分享、下载的需求日益凸显,我渐渐的把目标锁定在了nas上了,
萌萌哒草头将军
2025/02/25
2880
不吹不黑,自己拥有服务器一定要做这些事情
个人导航页 – HomeNavigation
程序的起因是因为家里申请了公网 IP,因此购置了一套服务器在家里放着。但是方便操作和记忆,因为写了此导航来可以快速的从内网或者外网访问家里的某些服务,通知导航页面也支持密码访问,登录一次之后便会生成 Cookie,默认 30 天有效期。通过密码来阻挡外人访问页面
素颜520
2023/04/19
9830
个人导航页 – HomeNavigation
如何利用内网穿透,异地访问NAS文件
NAS存储从诞生以来就备受大家的喜欢, 得益于多系统互访、即插即用、小开销、多协议等优点,很多企业都会采用他来存储和共享资源,也有很多个人玩家自建NAS服务,玩起来也是很HIGH。
用户5084575
2019/04/16
3.8K0
如何利用内网穿透,异地访问NAS文件
群晖NAS套件Docker安装宝塔面板教程
群晖科技(Synology )自始便专注于打造高效能、可靠、功能丰富且绿色环保的 NAS 服务器,是全球少数几家以单纯的提供网络存储解决方案获得世界认同的华人企业。
哈德森
2023/04/07
10.5K0
群晖NAS套件Docker安装宝塔面板教程
如何通过宝塔设置反代,去除docker端口号,实现通过二级域名直接访问服务
首先,我们做个假设来举例,这里假设,我们的域名的xxx.com,我们的docker名字是aaa,我们docker的端口是3000
承世
2024/02/27
4.3K0
如何通过宝塔设置反代,去除docker端口号,实现通过二级域名直接访问服务
Openwrt 开启外网访问并配置 SSL
防火墙 ==> 端口转发 中添加端口转发,将外网 5500 应设置 OpenWrt 的 80 端口
听闻所见
2023/08/02
6.6K0
Openwrt 开启外网访问并配置 SSL
轻松实现移动端与 NAS 端远程访问的详细教程
很多小伙伴在问nas设备要怎么才可以在移动端进行访问,想要在平板、手机等设备访问家里的nas其实不难,只要利用节点小宝配置一个外网访问域名就可以实现,下面给大家详细演示一下操作教程:
你可以叫我可乐
2024/07/29
7820
轻松实现移动端与 NAS 端远程访问的详细教程
教你不花一分钱,用十分钟把旧电脑打造成自己的Windows版NAS系统
一年前我前前后后花了2个多星期的时间才将整套系统部署完成,但这是因为其中有很多的坑,需要找到解决方案。我已经尽可能把过程中遇到的所有问题都写明,大家只要跟着去做,还是非常简单的,不需要太长时间。整套系统至今一直非常稳定。
ICT系统集成阿祥
2024/12/30
13.4K1
教你不花一分钱,用十分钟把旧电脑打造成自己的Windows版NAS系统
基于frp的内网穿透实例2-通过自定义域名访问部署于内网的 web 服务
local_port 为本地机器上 web 服务对应的端口,一般为80,绑定自定义域名 www.yourdomain.com
用户6948990
2025/04/03
4150
基于frp的内网穿透实例2-通过自定义域名访问部署于内网的 web 服务
群晖NAS搭建WebDav服务做文件共享,可随时随地远程访问
建议使用支持UTF-8的WebDAV客户端,以免在使用WebDAV服务时出现编码错误,这里我们通过RaiDrive客户端来测试。
FGGIT
2024/10/15
2.8K0
群晖NAS搭建WebDav服务做文件共享,可随时随地远程访问
【搭建服务器】Win10 IIS搭建webdav服务以及公网访问教程 - 挂载webdav
自己用Windows Server搭建了家用NAS主机,WebDAV的文件共享方式当然也是必不可少的。
鱼找水需要时间
2023/06/01
10.1K0
【搭建服务器】Win10 IIS搭建webdav服务以及公网访问教程 - 挂载webdav
为什么NAS需要内网穿透,如何给自建NAS做内网穿透
‌局域网(内网):‌ 指的是我们自己组建的小范围私有网络,比如家里的WiFi、公司的内部网络。在这个网络里的设备(你的电脑、手机、打印机、NAS等)都使用‌私有IP地址‌(比如常见的 192.168.1.100)互相通信。这些地址就像是家里的房间号,只在自家的“房子”(局域网)里有效。
用户11644095
2025/06/03
4790
威联通(NAS)搭建个人图床
图床:一般是指储存图片的服务器,有国内和国外之分。国外的图床由于有空间距离等因素决定访问速度很慢影响图片显示速度。国内也分为单线空间、多线空间和cdn加速三种。更详细的内容,请左转查看百度百科
BigYoung小站
2020/05/05
2.1K0
低成本搭建NAS服务
下载地址:https://pan.baidu.com/s/1EBK_bEiyQb0ROG41Dw4JTA 提取码:lgrr
FHYC
2018/12/24
10.8K0
如何禁止反代项目IP加端口访问
上一篇我使用了宝塔的Supervisor管理器部署了Panlndex,部署完之后在进行反代,发现域名可以访问,ip+端口也能访问,我就在想怎么关闭IP+端口访问,据说安全一点,我百度了很久,百度上全是说怎么防止恶意解析的,过程很复杂,我就想关闭这个项目的ip加端口访问,感觉应该不会那么复杂。
Qwe7
2022/01/22
2.9K0
通过Infortress 端口穿透功能访问内网电脑部署的HTTP服务
在远程办公或跨地域协作场景下,远程访问内网电脑上搭建的HTTP服务成为许多人特别是技术工程人员的一个痛点。借助Infortress的端口穿透功能,无需复杂网络配置,即可轻松访问内网HTTP服务。
用户11644095
2025/05/15
1720
通过frp反向代理实现公网远程访问家里设备
相信玩NAS、软路由一类的同学都有这样一个诉求,就是随时随地地访问到家里的设备。大家听到的异地组网,VPN方案,内网穿透,反向代理等说法,都是实现这个诉求的,当时每一种也有一定的差异,感兴趣的可以自行查阅这些说法背后的原理和依赖的技术工具。
用户1160092
2024/11/12
3600
通过frp反向代理实现公网远程访问家里设备
NAS外网访问及配置DDNS研究记录
# 情况说明:大佬的教程写很全了,没必要搬,直接复制网址过去看就好了。只写一些他们跑不通的点。
华创信息技术
2020/03/11
4K0
Kubernetes通过HostAliases自定义hosts
今天突然就有了那么一个需求,记录一下:腾讯云的redis内网地址都是IP的方式。我们的服务注册在了nacos中。小伙伴本地测试链接上nacos(nacos开通了外网访问),获取redis中redis配置都是内网的redis IP故无法加入注册到集群。同事问我能不能将Redis ip设置成域名的方式,那样他本地好歹能做个假的解析做一个欺骗把服务启动起来?(懒得改代码毕竟)
对你无可奈何
2022/12/01
1.4K1
wokerman 外网ip端口访问,Nginx跨域配置,htpps,ssl,wss
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好。
OwenZhang
2022/05/30
3.4K0
wokerman 外网ip端口访问,Nginx跨域配置,htpps,ssl,wss
推荐阅读
相关推荐
不吹不黑,自己拥有服务器一定要做这些事情
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档