最近收到一位粉丝的提问,关于分库分表在面试中如何结合业务逻辑举例的问题。
他提到之前使用 serverless 数据库时没涉及分库分表,现在遇到了具体场景,想请教合适的方案。
这其实是面试中很常见的考点,既要看技术思路,更要看能否结合业务落地,今天就借着这个问题展开聊聊。
前言
怕有些朋友没有了解过这方面的知识点,先来解释一下这些概念:
-
分库分表的核心目标:解决单库单表因数据量过大(如千万 / 亿级)导致的「写入慢、查询卡、扩容难」问题;
-
分库 vs 分表:分表是将一张大表拆成多张小表(同库或跨库),分库是将数据分散到多个数据库,两者常结合使用;
-
为什么结合业务? :分片策略(如按时间、按 ID)若脱离业务,可能导致「数据倾斜」(某分片数据过多)或「查询效率低」(跨分片查询频繁),这也是面试重点考察的「业务落地能力」。
场景
比如有一个 "设备执行记录表",这个表数据的特点如下:
- 一天中存在早高峰和晚高峰(早上 8 点,晚上 7 点 ------ 对应起床和下班的时间)
- 整点和半点的时候存在极大值
- 数据是 insert 多,query 少
- 假设一天产生 100 万条数据,早晚高峰分别产生 20 万、15 万条数据
粉丝提问
如何设计分库分表? 目前所能想到的方法是按照时间区间去分,比如把一天拆分成 24 份。我的思路是否可行?请问还有没有更好的思路?
解答
"按照时间区间分,比如把一天拆分成 24 份" 基本可行,但结合业务特性可以进一步优化,让方案更灵活且贴合实际场景。下面是我的思路,可以参考一下:
- 基础时间分片(他的初始思路)
按 24 小时拆分确实能解决数据集中的问题,但需要注意:后半夜数据量很小(可能不足 1 万条),如果严格按小时分表,会导致大量空表或小表,反而增加管理成本。这种方案适合数据分布均匀的场景,但对 "早晚高峰突出" 的情况来说,不够精细化。
具体实现时,可借助分库分表中间件(如 ShardingSphere)配置分片规则,例如:
-
分片键设为记录生成时间(create_time)
-
分片算法采用时间范围分片,表达式为
create_time BETWEEN '2024-07-31 00:00:00' AND '2024-07-31 01:00:00'
对应表名device_log_20240731_00
-
需提前创建当日 24 张表,若用自动化脚本可减少人工操作
- 按高峰时段差异化分片
考虑到早 8 点、晚 7 点是高峰(分别产生 20 万、15 万条数据),可以将时段划分为 "高峰区" 和 "非高峰区":
-
早 7-9 点、晚 6-8 点作为高峰时段,单独分表(比如拆成 "设备执行记录_早高峰""设备执行记录_晚高峰");
-
其他时段(尤其是后半夜)合并分表,比如 "设备执行记录_平峰"。
这种方式能避免小表冗余,同时让高峰数据集中存储,方便后续针对性优化(比如高峰表用更高性能的存储引擎)。
该方案需注意跨时段查询问题,例如用户需要查询某天 6-10 点的数据,会涉及早高峰表和相邻平峰表。可通过中间件自动路由聚合结果,也可在应用层维护分片映射关系,查询时先解析时间范围再匹配对应表名。
- 按动态数据量分片(进阶方案)
更灵活的做法是按数据量阈值分表,规则写在配置文件中统一管理:
-
设定单表阈值(比如 20 万条),当某时段数据达到阈值时自动创建新表;
-
例如早 8 点数据达到 20 万,自动生成 "设备执行记录_20240731_08_00",后续数据写入新表;
-
平峰时段数据量小,可能多个小时的数据合并到一个表中(比如 "设备执行记录_20240731_平峰")。
这种方案的优势在于:完全适配 "insert 多、数据量波动大" 的特性,既不会因固定时段产生小表,也能通过配置灵活调整阈值(比如大促期间临时调低阈值),运维成本更低。
具体落地可设计三层架构:
-
配置层:用 Nacos/Apollo 存储阈值(如 single_table_max_rows: 200000)、表名生成规则(如 prefix + date + seq)
-
监控层:通过定时任务统计各表数据量,达到阈值时触发分表事件
-
执行层:事件触发后自动创建新表,并更新分片路由规则(无需重启应用)
分库分表后的查询与运维考量
- 查询优化
虽然该表 query 少,但仍需考虑极端场景。例如需查询某设备一周的执行记录,可通过以下方式优化:
-
建立全局索引表,存储设备 ID 与对应分片的映射关系
-
对历史冷数据(如超过 30 天)做聚合归档,减少查询扫描范围
-
高峰表单独建立本地索引(如设备 ID + 时间),平峰表可省略索引降低写入压力
- 数据迁移与扩容
当单库磁盘占用达到 80% 时,需进行分库扩容:
-
采用 "双写 + 校验" 方案:先扩容新库,写入时同时写新旧库,读请求仍走旧库
-
通过校验工具比对两边数据一致性,完成后切换读路由,最后停写旧库
-
迁移过程中用流量控制确保不影响线上写入性能(如限制每秒迁移 1 万条)
面试时的加分表述技巧
上面这些思路其实是技术演进的过程,面试时可以这样说:
我当时先考虑了最基础的按小时分片,但发现会产生大量小表;接着结合高峰特性,设计了高峰 / 平峰差异化方案;最后考虑到业务可能变化(比如未来数据量翻倍),选择了按动态数据量分片 ------ 通过配置文件管理阈值,既适配当前 100 万 / 天的规模,也能应对后续增长。整个过程是从'解决问题'到'灵活适配'的优化,最终方案既满足性能需求,又降低了长期维护成本。
如果被追问如何处理异常场景,可补充:
我们还做了熔断机制,当分表服务故障时自动降级到不分片模式,同时通过监控告警快速介入;另外针对跨表事务,采用最终一致性方案,用本地消息表保证数据完整性。
这样表述能体现你的思考深度:不仅懂技术方案,更能结合业务做权衡,且有清晰的演进逻辑。
亮点
-
从真实业务场景(设备执行记录表)出发,避免纯理论讨论,贴合面试中 "结合业务举例子" 的要求;
-
提供 "基础方案→进阶方案→最优方案" 的演进思路,每个方案配套具体实现细节,展现技术落地能力;
-
新增查询优化、扩容迁移等运维视角,体现全链路思维,这是面试官非常看重的加分项;
-
明确给出面试时的表述模板,把技术思路转化为加分话术,突出 "灵活设计" 和 "业务适配" 的核心能力。
核心结论
分库分表的设计逻辑是「先明确业务特点(数据量、读写比例、分布规律)→ 选择分片键(如时间)→ 设计策略(从简单到灵活)→ 考虑查询与运维成本 」,面试中需体现「从业务出发的演进思维」。
欢迎关注 ❤
我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。
没准能让你能刷到自己意向公司的最新面试题呢。
感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:面试群。