一次难得的分库分表实践(上)

简介: 一次难得的分库分表实践

背景


前不久发过两篇关于分表的文章:




从标题可以看得出来,当时我们只做了分表;还是由于业务发展,截止到现在也做了分库,目前看来都还比较顺利,所以借着脑子还记得清楚来一次复盘。


先来回顾下整个分库分表的流程如下:



整个过程也很好理解,基本符合大部分公司的一个发展方向。


很少会有业务一开始就会设计为分库分表,虽说这样会减少后续的坑,但部分公司刚开始都是以业务为主。


直到业务发展到单表无法支撑时,自然而然会考虑分表甚至分库的事情。


于是本篇会作一次总结,之前提过的内容可能会再重复一次。


分表


首先讨论下什么样的情况下适合分表?


根据我的经验来看,当某张表的数据量已经达到千万甚至上亿,同时日增数据量在 2% 以上。


当然这些数字并不是绝对的,最重要的还是对这张表的写入和查询都已经影响到正常业务执行,比如查询速度明显下降,数据库整体 IO 居高不下等。


而谈到分表时我们着重讨论的还是水平分表;



也就是将一张大表数据通过某种路由算法将数据尽可能的均匀分配到 N 张小表中。


Range


而分表策略也有好几种,分别适用不同的场景。


首先第一种是按照范围划分,比如我们可以将某张表的创建时间按照日期划分存为月表;也可以将某张表的主键按照范围划分,比如 【1~10000】在一张表,【10001~20000】在一张表,以此类推。



这样的分表适合需要对数据做归档处理,比如系统默认只提供近三个月历史数据的查询功能,这样也方便操作;只需要把三月之前的数据单独移走备份保存即可)。


这个方案有好处也有弊端:


  • 好处是自带水平扩展,不需要过多干预。


  • 缺点是可能会出现数据不均匀的情况(比如某个月请求暴增)。


Hash


按照日期这样的范围分表固然简单,但适用范围还是比较窄;毕竟我们大部分的数据查询都不想带上时间。


比如某个用户想查询他产生的所有订单信息,这是很常见的需求。


于是我们分表的维度就得改改,分表算法可以采用主流的 hash+mod 的组合。

这是一个经典的算法,大名鼎鼎的 HashMap 也是这样来存储数据。


假设我们这里将原有的一张大表订单信息分为 64 张分表:



这里的 hash 便是将我们需要分表的字段进行一次散列运算,使得经过散列的数据尽可能的均匀并且不重复。


当然如果本身这个字段就是一个整形并且不重复也可以省略这个步骤,直接进行 Mod 得到分表下标即可。


分表数量选择


至于这里的分表数量(64)也是有讲究的,具体设为多少这个没有标准值,需要根据自身业务发展,数据增量进行预估。


根据我个人的经验来看,至少需要保证分好之后的小表在业务发展的几年之内都不会出现单表数据量过大(比如达到千万级)。


我更倾向于在数据库可接受的范围内尽可能的增大这个分表数,毕竟如果后续小表也达到瓶颈需要再进行一次分表扩容,那是非常痛苦的。


目前笔者还没经历这一步,所以本文没有相关介绍。


但是这个数量又不是瞎选的,和 HashMap 一样,也建议得是 2^n,这样可以方便在扩容的时尽可能的少迁移数据。


Range + Hash


当然还有一种思路,RangeHash 是否可以混用。


比如我们一开始采用的是 Hash 分表,但是数据增长巨大,导致每张分表数据很快达到瓶颈,这样就不得不再做扩容,比如由 64 张表扩容到 256 张。


但扩容时想要做到不停机迁移数据非常困难,即便是停机,那停多久呢?也不好说。


所以我们是否可以在 Mod 分表的基础上再分为月表,借助于 Range 自身的扩展性就不用考虑后续数据迁移的事情了。



这种方式理论可行,但我没有实际用过,给大家的思路做个参考吧。


烦人的数据迁移


分表规则弄好后其实只是完成了分表的第一步,真正麻烦的是数据迁移,或者说是如何做到对业务影响最小的数据迁移。


除非是一开始就做了分表,所以数据迁移这一步骤肯定是跑不掉的。


下面整理下目前我们的做法供大家参考:


  1. 一旦分表上线后所有的数据写入、查询都是针对于分表的,所以原有大表内的数据必须得迁移到分表里,不然对业务的影响极大。


  1. 我们估算了对一张 2 亿左右的表进行迁移,自己写的迁移程序,大概需要花 4~5 天的时间才能完成迁移。


  1. 意味着这段时间内,以前的数据对用户是不可见的,显然这样业务不能接受。


  1. 于是我们做了一个兼容处理:分表改造上线后,所有新产生的数据写入分表,但对历史数据的操作还走老表,这样就少了数据迁移这一步骤。


  1. 只是需要在操作数据之前做一次路由判断,当新数据产生的足够多时(我们是两个月时间),几乎所有的操作都是针对于分表,再从库启动数据迁移,数据迁移完毕后将原有的路由判断去掉。


  1. 最后所有的数据都从分表产生和写入。


至此整个分表操作完成。


相关文章
|
存储 前端开发 JavaScript
十二款·富文本编辑器:数字创作的瑞士军刀
在数字化时代,内容创作已经成为我们日常生活中不可或缺的一部分。无论是撰写一封电子邮件、准备一份报告、还是在社交媒体上分享心情,文字都是我们表达和沟通的基石。而在这个过程中,富文本编辑器就如同一把瑞士军刀,为我们提供了多种功能以增强和美化我们的文字内容。
912 1
|
数据可视化 UED 容器
JavaFX布局详解与代码实例
JavaFX布局详解与代码实例
232 0
|
XML API 数据格式
天气预报API接口
原文:天气预报API接口 一、中央气象台API接口: 1.
19051 0
|
5月前
|
网络协议 安全 物联网
《复杂环境下IPv6地址规划与子网划分全攻略》
随着网络环境日益复杂及设备数量激增,IPv6以其超大地址空间和即插即用优势成为网络变革的关键。本文深入探讨IPv6地址规划与子网划分的挑战与方法,包括夯实基础知识、遵循层次性与高效性原则、应对物联网与云计算等特殊场景需求,以及验证优化的重要性。通过合理规划与科学划分,可构建高效、稳定且安全的IPv6网络,为未来发展奠定基础。
357 19
|
11月前
|
JavaScript 前端开发 API
vue尚品汇商城项目-day03【20.获取Banner轮播图的数据+21.使用swiper轮播图插件】
vue尚品汇商城项目-day03【20.获取Banner轮播图的数据+21.使用swiper轮播图插件】
171 0
|
JavaScript API
如何使用Vue 3和Type Script进行组件化设计
【8月更文挑战第16天】如何使用Vue 3和Type Script进行组件化设计
253 1
|
Web App开发 存储 缓存
如何解决ChatGPT发送消息没有反应的问题
帮你解决ChatGPT发送消息没有反应的问题
571 0
如何解决ChatGPT发送消息没有反应的问题
|
Ubuntu 算法 Linux
怎么解决在vmware虚拟机下ubuntu linux系统重启后不能联网的问题
怎么解决在vmware虚拟机下ubuntu linux系统重启后不能联网的问题
780 0
|
缓存 架构师 算法
Java内存溢出如何解决,Java oom排查方法,10个定位解决办法
在Java开发过程中,有效的内存管理是保证应用程序稳定性和性能的关键。不正确的内存使用可能导致内存泄露甚至是致命的OutOfMemoryError(OOM)。
274 0
|
Java 应用服务中间件 调度
xxl-job任务调度2.0.2升级到2.3.0版本,执行器改造过程中经验总结
xxl-job任务调度2.0.2升级到2.3.0版本,执行器改造过程中经验总结
1373 0

热门文章

最新文章