面试记录 2026-09-23
题目:什么是数据倾斜,会带来哪些问题?如何解决?
难度:low
标签:db/sharding, general/knowledge, difficulty/low
评分:⭐⭐⭐☆☆(3/5)
我的回答
数据倾斜一般是在分库分表之后产生的一个衍生问题。由于我们分表了,把所有的数据分散到不同的表中。这时候如果大量的数据只插入到分表后的某一个表,而在其他的表中,数据量差异比较大,数量比较少,就造成了数据倾斜。大量的数据其实还在一个数据库表中,这时候我们分表的意义就会有些得不偿失,它并没有解决原本的想要把数据拆分成多份,可以更好的提升数据访问的作用,因为大量数据还是集中在一个表中,这时候要考虑我们选择的分表方式是否存在问题。比如如果选择的是哈希,是否是因为数据量哈希的这个值有问题?然后如果是选择的时间,是否是在这个时间区间内,数据有激增增长,是否要调整这个时间区间的范围?解决数据倾斜基本上是考虑调整数据的划分方式,修改数据插入到数据库表中的方式来实现处理数据倾斜的问题。
点评
优点:
- 抓住倾斜的本质定义:"数据都堆一张表,分表就白分了"
- 有排查思维:回到分片键、哈希算法、时间区间三个维度找根因
- 用反问句组织排查路径,思考顺序对
不足:
- 没给量化表现(热点节点磁盘 90% vs 其他 10%、某分片 QPS 是均值 10 倍)
- 解决方案单薄,只提"改算法",缺二次分片、复合分片键、一致性哈希虚拟节点、热点自动迁移
- 漏掉分片键选错、大用户场景、热点 Key 三种高频倾斜
- 没提扩容时的负载倾斜(一致性哈希扩容后不均)
补充:
- 两类倾斜:数据量倾斜(存储/IO 热点)+ 访问倾斜(QPS/热点 key)
- 典型场景:分片键=用户 ID 但大客户 ID 号段集中;分片键=时间戳但业务有明显峰值
- 核心解决套路:
- 分片键选择:优先选分布均匀、查询主路径命中的字段
- 一致性哈希 + 虚拟节点:解决扩容后负载不均
- 复合分片:主键分库、次键分表,或 hash(user_id, order_id) 二级路由
- 热点检测 + 动态迁移:实时监控水位,触发再平衡
- 大对象/大卖家单独路由:识别后走独立分片
完整讲解
第一部分:知识重点剖析
核心考点定位:能否识别分库分表引入的次生问题,并给出可落地的治理手段。
知识点拆解:
- 倾斜的两类本质:
- 数据量倾斜:存储和 IO 集中在少数分片,热点分片磁盘满、备份慢、DDL 阻塞时间长
- 访问倾斜(QPS 倾斜):热点 key / 大卖家 / 热点活动导致单分片 QPS 打满,其他分片闲着
- 常见成因:
- 分片键选择不当(用创建时间,但业务流量集中在近 3 个月)
- 分片键值域分布不均(用户 ID 号段被大客户占大头)
- 哈希函数冲突(哈希空间过小时模数取错)
- 扩容后没重平衡(一致性哈希扩容后负载不均衡)
- 业务影响:
- 热点分片性能瓶颈(磁盘/IO/CPU 单点打满)
- 扩容空间被压缩(其他分片有余量但没法用)
- 主从复制延迟放大(大分片的 binlog 复制慢)
- DDL 长阻塞、备份窗口拉长
- 治理手段:
- 事前:分片键选择(均匀分布 + 主查询命中 + 不可变)
- 事中:热点监控(Prometheus + 各分片水位、QPS、TPS)+ 一致性哈希虚拟节点
- 事后:热点分片拆分(二次分片)、复合分片、大卖家/大对象独立路由、离线数据订正迁移
- 典型场景案例:
- 电商订单:按 user_id 分片但天猫/京东大卖家单店数据量 = 10 万小卖家总和 → 大卖家独立分片
- 物联网时序:按时间戳分片但白天 90% 流量集中在 10:00-11:00 → 按 hash(device_id) 分片
- 社交 Feed:按用户 ID 分片但明星粉丝流量打爆单个分片 → 读热点走缓存 + 热点分片扩容
- 与缓存倾斜、K8s Pod 倾斜、HDFS 数据倾斜的对比:底层原理一致,都是"分片维度选错导致负载不均"
第二部分:考察方向与延伸递进
考察方向:
- 深度:能否区分数据量倾斜 vs 访问倾斜,各自的根因和治理手段不同
- 广度:能否关联一致性哈希、热点 key、动态扩容等相邻知识域
- 应用:能否落地"事前预防 + 事中监控 + 事后治理"完整闭环
延伸递进面试题:
- 一致性哈希如何解决数据倾斜?扩容时负载会如何变化?
- 解答要点:普通哈希扩容后大量 key 迁移(N 变 N+1 时约 N/(N+1) 比例重映射);一致性哈希只迁移 1/(N+1);虚拟节点进一步均衡
- 线上如何主动发现数据倾斜?需要哪些监控指标?
- 解答要点:分片间数据量方差、QPS/TPS P99 与均值比、磁盘水位差、连接数分布;SLO 触发告警
- 已经倾斜了如何在线治理?不停服如何迁移?
- 解答要点:双写 + 数据回补 + 灰度切流 + 校验对账 + 反向迁移,配合分片中间件(如 ShardingSphere-Proxy 的在线 DDL)
第三部分:面试者参考回答(300-600 字口语化)
面试官您好,数据倾斜是分库分表最容易踩的坑,本质是"数据本该均匀分布,但实际集中在少数分片"。
我一般会把它分成两类来看。第一类是数据量倾斜,就是存储层面不均,热点分片磁盘可能 90% 满,其他分片才 10%。第二类是访问倾斜,就是 QPS 不均,热点 key 或大卖家把所有请求都打到同一个分片。第二类在实际项目里更常见也更难,因为它是运行时才暴露的。
成因通常就几种:
- 分片键选错了。比如订单表按创建时间分片,但 80% 流量都在最近 3 个月——所有新订单都在同一个时间片,历史订单基本没人查。
- 分片键值域分布天然不均。比如按 user_id 分片,但业务里存在大客户,某个大卖家的数据量等于 10 万个小卖家总和。
- 扩容后没做重平衡。普通哈希扩容到 N+1,几乎所有 key 都要重映射,负载不但不均还引发流量抖动。
治理上我分三个阶段:
事前:选分片键有三个标准——分布均匀、主查询命中、业务上不可变(一旦变了数据搬家很痛)。比如订单表我一般会选 buyer_id 而不是 order_id,因为买家查询是主路径,且买家 ID 用雪花算法生成天然均匀。
事中:监控必须做。我们一般用 Prometheus 抓每个分片的行数、磁盘水位、QPS、TPS、连接数,看各分片的方差和 P99/均值比。超过 3 倍就告警。
事后:如果已经倾斜了,看情况分两种处理。数据量倾斜可以走"双写 + 回补 + 灰度切流 + 反向校验",把热点分片的数据迁一部分到新分片,业务无感;访问倾斜可以先用热点缓存兜住 QPS,再判断要不要真的迁数据。大卖家/明星这种特殊账号,我们会单独识别,走独立分片或者广播表,不跟普通用户混在一起。
还有一个关键点:一致性哈希加虚拟节点是应对扩容倾斜的通用方案,普通哈希扩容一次就要重映射大部分数据,一致性哈希只影响 1/N,虚拟节点能让负载进一步均匀。我们在 ShardingSphere 里就是用的这个方案。
最后提一句,倾斜不只是分库分表的问题。Kafka 消费倾斜、HDFS 数据倾斜、Redis 大 Key、K8s Pod 调度不均,底层都是"分片维度选错导致负载不均",方法论是相通的。