分库分表与 Spring 集成

共 17 题
📑 题目列表 17 题
#
★★★

1. 分库分表与 Spring Data 的 @Table/@ShardingSphere 整合

分库分表场景下,Spring Data 的 @Table 注解与 ShardingSphere 如何整合使用?

  • @Table 注解的用途与逻辑表
  • ShardingSphere 分片规则的作用
  • 逻辑表名与真实表名的映射

在分库分表场景下,Spring Data JPA 实体上的 @Table(name = "order") 声明的是"逻辑表名"(逻辑表),即业务代码中统一使用的表名,而真实物理表是 order_0、order_1、order_2 等分片表。ShardingSphere 负责把对逻辑表的 SQL 改写为对真实物理表的 SQL:它根据配置的分片规则(分片键、分片算法)把逻辑表名替换为实际表名,并路由到对应的数据源。因此 @Table 指向逻辑表,ShardingSphere 通过配置(如 spring.shardingsphere.rules.sharding.tables.order.actual-data-nodes)把逻辑表与物理表关联起来。整合要点:实体用逻辑表名,ShardingSphere 配置分片策略与数据源,Spring Data 负责对象关系映射,二者通过逻辑表名衔接,无需改实体代码。使用 ShardingSphere-JDBC 时,它作为 DataSource 的嵌入式代理,Spring 的 DataSource 指向 ShardingSphere 的数据源即可无缝集成。

本题考察 ShardingSphere 与 Spring Data 的整合边界。核心是"逻辑表 vs 物理表"的映射:@Table 用逻辑表名,ShardingSphere 按分片规则改写路由到物理表。

#
★★★

2. 分库分表后的分布式事务(Seata)

分库分表后,跨库跨表的数据一致性如何通过 Seata 等分布式事务方案解决?

  • 分布式事务的挑战
  • Seata 的 AT/TCC/SAGA 模式
  • 与 Spring/分库的集成

分库分表后,数据分布在不同库/不同表,单库事务无法保证跨库一致性,需引入分布式事务方案。Seata 是主流方案之一,提供多种模式:AT 模式(自动补偿,通过 undo log 记录数据变更并自动回滚,对业务侵入小,适合数据库事务);TCC 模式(Try-Confirm-Cancel,业务显式实现三个方法,适合跨服务/跨资源);SAGA 模式(长事务,通过状态机编排,适合流程长、延迟高的场景)。Seata 通过全局事务协调器(TC)管理分支事务,与 Spring 的 @GlobalTransactional 结合,在分库分表场景下,各分片的分支事务由 RM 参与,TC 统一提交/回滚。取舍:AT 模式简单但性能开销大、依赖 undo log;TCC 性能好但侵入性强;SAGA 适合长流程。选择需结合业务对一致性要求的强度与性能。

本题考察分布式事务在分库分表下的解法。核心是 Seata 的几种模式(AT/TCC/SAGA)的机制与适用场景,以及各模式在一致性、性能、侵入性上的取舍。

#
★★★

3. ShardingSphere 的 broadcast 表(字典表)应用

ShardingSphere 的 broadcast 表(广播表)是什么?在什么场景下应用?

  • broadcast 表的概念
  • 广播表的数据同步机制
  • 适用场景

ShardingSphere 的 broadcast 表(广播表)是指那些数据量小、每个分片库都需要完整副本的基础表(如字典表、配置表、区域表)。在分库分表场景下,广播表会同时存在于所有分片库中,且每个库都保存完全相同的数据。ShardingSphere 对广播表的 SQL 处理是:写操作(INSERT/UPDATE/DELETE)会广播到所有分片库执行,保证各库数据一致;读操作则从任意一个分片库读取即可(如默认取第一个或随机)。其应用场景是:分库分表后,那些需要被所有分片表 join 或查询的全局字典数据,如"商品分类表""用户状态字典表"等。由于量小、变化不频繁,广播表避免了跨库查询字典的麻烦,同时要注意其数据同步的一致性(写广播失败的处理)。

本题考察广播表的概念与场景。核心是"每个分片库都有完整副本、写广播、读任意库",适用于量小且需全局使用的基础字典数据。

#
★★★

4. ShardingSphere 的分片策略(hash/range)与绑定表/广播表的应用场景?

ShardingSphere 的分片策略(hash/range)与绑定表、广播表分别适用于什么应用场景?

  • hash 分片与 range 分片的特点
  • 绑定表(binding table)的用途
  • 广播表与其他策略的取舍

hash 分片(哈希取模/一致性哈希)把数据按分片键哈希后均匀分布到各分片,优点是数据均匀、避免热点,缺点是不支持范围查询跨分片有序扫描(需聚合);range 分片(按区间如时间、ID 区间)把数据按连续区间分布,优缺点恰好相反:支持范围查询、适合按时间归档,但可能倾斜(如某区间数据量大)。绑定表(binding table)用于关联查询场景:当两张表(如订单表 order 与订单明细表 order_item)按同一分片键分片且分片规则一致时,把它们声明为绑定表,ShardingSphere 可保证 join 在同一个分片内完成,避免跨分片 join。广播表用于量小、需全局副本的字典表。应用场景:订单系统常用 hash 分片 + 绑定表(order/order_item 按 user_id 或 order_id 分片);日志/流水按时间用 range 分片;字典表用广播表。

本题考察分片策略的选型。hash 均匀但范围查询差,range 支持范围但可能倾斜;绑定表解决同分片 join,广播表解决全局字典。回答要给出对应场景。

#
★★★

5. 查询未携带分片键时的路由策略与业务约束(禁止全库扫描、路由提示与索引兜底)

分库分表后,查询未携带分片键时 ShardingSphere 如何处理?应如何通过业务约束规避全库扫描?

  • 未携带分片键的默认路由
  • 全库扫描的危害
  • 路由提示(hint)与索引兜底

分库分表后,若查询未携带分片键,ShardingSphere 无法确定数据落在哪个分片,默认会"全库扫描"——即把 SQL 广播到所有分片库执行,再合并结果。全库扫描在数据量大时性能极差,是分库分表的大忌。业务约束上应避免:一是强制查询必须携带分片键(如通过用户 ID 定位),在代码层面约束;二是对无法携带分片键的查询,用 ShardingSphere 的 hint 强制路由(SpecifiedShardingStrategy / @HintSharding 指定分片范围),或使用中间表/索引表(通过冗余字段先定位分片);三是为必要的查询建立索引兜底,并配合读写分离降低全库扫描压力。工程上应把"禁止无分片键查询"作为设计约束,必要时用 hint 或反查索引表缩小扫描范围。

本题考察分片路由的约束。核心是"未携带分片键默认全库扫描"的危害,以及通过业务约束、hint 路由、索引表兜底三种手段规避。

#
★★★

6. 分库分表后的全局 ID、分布式事务与跨库查询(聚合/Join)如何降级处理?

分库分表后,全局 ID、分布式事务与跨库查询(聚合/Join)分别如何降级处理?

  • 全局 ID 方案
  • 分布式事务的降级
  • 跨库聚合与 Join 的降级

分库分表后需处理三类问题。全局 ID:使用雪花算法、号段模式(LEAF)或分布式 ID 中心生成全局唯一且趋势递增的 ID,避免跨库重复。分布式事务:跨库写操作无法用单库事务保证,需引入 Seata(AT/TCC/SAGA)或 XA;降级处理时,若实时强一致要求不高,可退化为"本地消息表 + 最终一致"或"最大努力通知",通过异步补偿与幂等保证最终一致。跨库查询(聚合/Join):跨分片 Join 与聚合无法直接执行,需降级处理——用字段冗余(冗余 Join 所需字段)、宽表(预聚合数据)、应用层聚合(分片查询后在内存合并排序分页)、或引入 ES(搜索引擎/OLAP)承载复杂查询。整体思路是:把无法在分库分表下高效完成的操作,通过"数据冗余、预聚合、异步化、独立查询引擎"降级实现。

本题考察分库分表的三类"降级"处理。全局 ID 用分布式 ID;分布式事务用 Seata 或最终一致;跨库聚合/Join 用字段冗余、宽表、应用层聚合、ES 等替代。

#
★★

7. ShardingSphere 的 hint 强制路由

ShardingSphere 的 hint 强制路由是什么?适用于什么场景?

  • hint 路由机制
  • 与分片键路由的差异
  • 适用场景

ShardingSphere 的 hint 强制路由(Force Routing)允许在 SQL 不含分片键、或无法从 SQL 中推导分片键的情况下,通过代码显式指定路由目标(分片键值或分片表名),从而绕过分片键的自动推导。它通过 ShardingSphereDataSourceHintManager 实现:HintManager.getInstance().addDatabaseShardingValue("t_order", "user_id", 100) 指定在某逻辑表上按 user_id=100 路由。适用场景:查询未携带分片键但运行时已知分片键(如从上下文、线程变量、请求头获取);分片键不规范难以推导;多表关联时强制指定。注意 hint 需在使用后 close 释放,且是线程/请求级上下文,需注意清理。

本题考察 hint 路由的原理与场景。核心是"在 SQL 无法推导分片键时,用代码显式指定路由目标",通过 HintManager 实现,并注意生命周期管理。

try (HintManager hintManager = HintManager.getInstance()) {
    hintManager.addDatabaseShardingValue("t_order", "user_id", 100L);
    List<Order> orders = orderMapper.selectByCondition(...); // 无分片键也可路由
}
#
★★

8. ShardingSphere-JDBC 的 SQL 改写与路由

ShardingSphere-JDBC 的 SQL 改写与路由机制是怎样的?

  • SQL 解析与路由
  • SQL 改写
  • 结果归并

ShardingSphere-JDBC 作为嵌入式 JDBC 代理,对 SQL 的处理分四步:SQL 解析(parse)、路由(route)、改写(rewrite)、执行与结果归并(merge)。SQL 解析:把 SQL 解析为 AST(抽象语法树),识别表名、分片键、条件等。路由:根据分片键与分片规则,确定 SQL 应发往哪些数据源与分片表,分为单库路由、多库路由、广播路由等。改写:把逻辑表名改写为真实物理表名(如 order → order_0),并调整分片键条件、聚合/排序/分页结构(如把 LIMIT 改写为各分片的 LIMIT 再加总)。执行:在目标分片执行改写后的 SQL。结果归并:把各分片结果合并,包括排序、分页、聚合(SUM/COUNT/AVG)、去重等归并。整个过程对上层应用透明,Spring Data 通过 DataSource 指向 ShardingSphere 数据源即可。

本题考察 ShardingSphere-JDBC 的核心处理管线。核心是"解析→路由→改写→执行→归并"五步,重点在路由(按分片键)与改写(逻辑表→物理表、分页聚合改写)。

#
★★

9. 分库分表扩容的数据迁移(双写/停机/平滑)方案如何选择?

分库分表扩容时,双写、停机与平滑迁移三种数据迁移方案如何选择?

  • 三种迁移方案的特点
  • 停机窗口与数据一致性
  • 选型依据

分库分表扩容的数据迁移主要有三种方案。停机迁移:停服后在旧库导出数据,按新分片规则重新分片导入新库,再验证后切换。优点是简单、一致性强,缺点是需要停机窗口,适合业务允许短时停服、数据量可控的场景。双写迁移:新旧库同时写入,历史数据通过工具(如 binlog 同步、ETL)回放,校验一致后切换。优点是无需停机、风险低,缺点是双写逻辑复杂、需处理幂等与失败补偿。平滑迁移:利用 sharding 的平滑扩容(如一致性哈希、双层结构、分片间迁移任务)在运行中逐步迁移数据,配合灰度切换,对业务影响最小但实现最复杂。选型依据:停机容忍度、数据量、系统复杂度与团队投入。要求高可用、数据量大、无法停机时选双写或平滑迁移;数据量小、允许停机时选停机迁移。

本题考察扩容迁移的选型。停机迁移简单但需停服,双写迁移无需停机但复杂,平滑迁移最平滑但最复杂,需按停机容忍度与数据量取舍。

#
★★

10. 分库分表后的全局唯一 ID 方案,雪花算法、号段模式与 UUID 的并发/排序特性对比如何?

分库分表后的全局唯一 ID 方案中,雪花算法、号段模式与 UUID 在并发与排序特性上有何对比?

  • 三种 ID 方案的原理
  • 并发性能
  • 排序性与索引效率

雪花算法(Snowflake):由时间戳 + 机器 ID + 序列号组成 64 位 ID,趋势递增、全局唯一、无中心化、高并发,但依赖时钟,时钟回拨会产生重复或异常。号段模式(LEAF/snowflake 的号段):从数据库批量取一段连续 ID(如 1000 个)由应用分发,趋势递增、有序、性能好,但依赖数据库作为号段源,且停机时号段可能浪费。UUID:全局唯一、无中心化、生成简单,但无序、过长(32 位十六进制),作为主键会影响 InnoDB 索引的插入性能(随机插入导致页分裂),且不便于排序。对比:并发性能上雪花与号段都很高,UUID 生成也快但索引性能差;排序性上雪花与号段趋势递增、UUID 无序;索引效率上递增 ID 有利于聚簇索引,UUID 因随机性索引效率低。分库分表场景通常推荐雪花算法或号段模式,避免 UUID 的主键。

本题考察三种全局 ID 的对比。重点在趋势递增(利于索引)vs 无序(UUID 伤索引)、并发性能、时钟依赖与数据库依赖。

#
★★

11. 分库分表后的跨分片查询,全局聚合、分页排序与分布式事务(XA/柔性事务)如何处理?

分库分表后的跨分片查询,全局聚合、分页排序与分布式事务(XA/柔性事务)分别如何处理?

  • 跨分片聚合与分页排序
  • 分页排序的校正
  • 分布式事务(XA/柔性)的取舍

跨分片查询的全局聚合与分页排序需要"分片执行 + 归并"。聚合由各分片先算局部结果,再在应用层归并(SUM/COUNT/AVG 需先算各分片再合并,AVG 需按总数加权)。分页排序较复杂:若要全局正确排序分页,不能简单各分片取 LIMIT 返回,因为各分片排序后合并未必是全局前几——需把各分片按排序键取足量(如把所有分片的排序结果归并堆排序),或采用"二次分页"(先取足够多的每片数据再归并排序取页)。深分页(大 offset)代价极高,应避免或改用游标/keyset 分页。分布式事务处理:跨库写操作需事务保证,XA 是强一致但性能差、锁资源占用高,适合对一致性要求极高的场景;柔性事务(Seata AT/TCC/SAGA、本地消息表)牺牲部分一致换取性能与可用性,适合大多数业务。整体思路是:跨分片查询尽量用归并引擎(ShardingSphere 自动处理),深分页要规避,分布式事务按一致性要求选 XA 或柔性。

本题考察跨分片查询与事务的工程处理。聚合与分页排序需要分片执行+归并,深分页代价高需规避;分布式事务按强一致(XA)或柔性(Seata)取舍。

#
★★

12. 数据倾斜与热点分片(订单尾号不均匀)的识别与治理(预分片、热点扩容、读写分离)

分库分表后出现数据倾斜与热点分片(如订单尾号不均匀)如何识别与治理?预分片、热点扩容、读写分离各有什么作用?

  • 数据倾斜的识别
  • 预分片与热点扩容
  • 读写分离

数据倾斜与热点分片指数据或流量不均匀地集中在少数分片,导致这些分片成为瓶颈。识别方法:监控各分片的数据量、QPS、连接数、I/O 压力,对比分片间差异;订单尾号不均匀的典型场景是某尾号(如 0 或 9)订单量远大于其他,或某大客户(如平台单)集中在单分片。治理手段:预分片(提前规划分片数,避免过少分片导致扩容难;用一致性哈希减少重分布);热点扩容(对热点分片追加分片或对该分片子分片,把热点数据再拆分);读写分离(把读流量分流到只读副本,缓解主分片压力);此外可加盐/随机因子打散热点键、按业务维度单独分片(如大客户单独架区)。整体是"识别-打散-扩容-分流"的思路。

本题考察数据倾斜的治理。识别靠分片监控指标对比,治理靠预分片(规划)、热点扩容(拆分)、读写分离(分流)及加盐打散。

#
★★

13. 读写分离与分库分表叠加时的路由优先级与主从延迟处理

读写分离与分库分表叠加时,路由优先级如何确定?主从延迟如何处理?

  • 读写分离与分片的路由叠加
  • 路由优先级
  • 主从延迟的处理

读写分离与分库分表叠加时,路由是"先分片、后读写分离":先按分片键确定目标分片库,再在分片库内按读写分离规则选择主库或从库。写操作路由到主库,读操作路由到从库(按负载均衡策略)。路由优先级上,ShardingSphere 会先判断是否分片(需要分片键),再在该分片内决定主从。主从延迟处理:主从库存在复制延迟,刚写入的数据可能从从库读不到。处理手段包括:强制某些关键读走主库(HintManager 强制主库路由、@Transactional 内读走主库);设置 hint 或按需求禁止读从库;使用"半同步复制"或延迟容忍策略;对强一致读场景(如刚下单后立即查)走主库。工程上需在"读写分离提升吞吐"与"主从延迟导致一致性问题"之间权衡。

本题考察读写分离与分片的叠加路由。核心是"先分片后分主从"的优先级,以及主从延迟下强一致读走主库、延迟容忍读走从库的处理。

#

14. ShardingSphere/MyCat 的接入方式,Proxy 与 JDBC 两种模式的差异与 Spring 集成要点如何?

ShardingSphere 与 MyCat 的 Proxy 与 JDBC 两种接入方式有何差异?与 Spring 集成时有哪些要点?

  • Proxy 与 JDBC 模式差异
  • 部署方式与性能
  • Spring 集成要点

JDBC 模式(ShardingSphere-JDBC 为代表):以嵌入式依赖形式嵌入应用,通过实现 DataSource 代理,应用直连各真实数据库,无额外中间件,性能好、部署简单,但应用需承担分片逻辑,且每个应用实例都需配置。Proxy 模式(ShardingSphere-Proxy / MyCat 为代表):作为独立部署的中间件服务,对应用暴露统一数据库连接(如 MySQL 协议),应用连接 Proxy 再访问真实库,无需改造应用,支持多语言、集中管理,但多一层网络开销、性能略降、需运维 Proxy。Spring 集成要点:JDBC 模式把 DataSource 指向 ShardingSphere 的 ShardingSphereDataSource,Spring 的 JPA/MyBatis 透明使用;Proxy 模式把 Spring 的 DataSource 配置为连接 Proxy 的普通 JDBC 驱动即可。选择:轻量、需减少部署组件选 JDBC;多语言、集中治理、避免侵入应用选 Proxy。

本题考察 Proxy 与 JDBC 两种接入方式。核心差异是"嵌入式代理(JDBC,无中间件)vs 独立中间件(Proxy,多语言集中)",Spring 集成要点是 DataSource 的指向方式。

#

15. 分片键的选择与路由,范围分片/哈希分片/一致性哈希的适用场景如何?

分片键的选择与路由中,范围分片、哈希分片与一致性哈希各适用于什么场景?

  • 分片键的选择原则
  • 三种分片算法的适用场景
  • 扩容与数据分布的权衡

分片键的选择应遵循"高基数、均匀分布、查询常用"的原则,最好是查询的基本维度(如用户 ID、订单 ID),保证大多数查询能定位到单个分片。三种分片算法:范围分片(按 ID/时间区间):数据按连续区间分布,支持范围查询、适合按时间归档,但可能数据倾斜(区间内数据量不均),扩容时需迁移区间边界。哈希分片(取模):把分片键哈希后取模分片,数据分布均匀、避免热点,但不支持范围查询(需聚合),扩容时取模需要重新分布(数据迁移大)。一致性哈希:把分片键映射到哈希环,数据均匀分布,扩容/缩容时只需迁移环上少量数据(相邻分片),迁移成本低、适合动态扩容,但实现较复杂。适用场景:按时间归档用范围分片;按用户/订单等均匀查询键用哈希分片;需要频繁扩容、负载均衡用一致性哈希。

本题考察分片键与分片算法选型。核心是分片键要高基数均匀常用,范围分片适合时间归档、哈希分片均匀但扩容迁移大、一致性哈希扩缩容成本低。

#

16. 分库分表的扩容迁移,双写、停机与在线迁移如何取舍?

分库分表的扩容迁移中,双写、停机与在线迁移三种方案如何取舍?

  • 三种迁移方案对比
  • 停机窗口与一致性
  • 选型依据

停机迁移:停服后导出旧库数据、按新规则重分片导入新库,校验后切换。简单、一致性强,但需停机窗口,适合允许停服、数据量可控的场景。双写迁移:新旧库同时写入,历史数据用 binlog 同步或 ETL 回放,校验一致后切换。无需停机、风险低,但需处理双写逻辑、幂等与失败补偿,复杂度高。在线迁移(平滑迁移):利用分片引擎的平滑扩容能力(如一致性哈希、双层 hash、分片间迁移任务)在运行中逐步迁移数据,配合灰度切换,对业务影响最小,但实现最复杂、需要强大的迁移工具支撑。取舍:允许停机、数据量小选停机迁移;不允许停机、追求低风险选双写;数据量大、要求在线无缝、团队有迁移工程能力选在线迁移。核心权衡是停机容忍度、数据量与迁移复杂度。

本题考察扩容迁移的三方案取舍。停机迁移简单但需停服,双写无需停机但复杂,在线迁移最平滑但实现最复杂,按停机容忍度选型。

#

17. 分库分表后跨分片 JOIN 的替代,字段冗余、宽表、应用层聚合与 ES 的取舍

分库分表后跨分片 JOIN 的替代方案中,字段冗余、宽表、应用层聚合与 ES 如何取舍?

  • 四种替代方案机制
  • 各自的适用场景
  • 一致性权衡

分库分表后跨分片 JOIN 无法直接执行,需用替代方案。字段冗余:在需要 Join 的表里冗余存储对方的关键字段(如订单表冗余用户手机号),避免 Join,只查询单表;简单但需处理冗余字段的一致性(更新时同步)。宽表:预先把关联数据合并成一张宽表,查询单表即可;适合查询频繁、数据相对静态的场景,但宽表维护成本高、数据量大。应用层聚合:分别查询各分片的关联表,在应用内存中做 Join 与合并;灵活但受限于数据量,性能与内存消耗大。ES(搜索引擎):把需要关联查询/聚合/全文检索的数据同步到 ES,用 ES 承载复杂查询;适合复杂查询、聚合、高并发检索,但引入了 ES 组件、数据同步的延迟与一致性需处理。取舍:数据量小、简单关联用字段冗余或应用层聚合;查询稳定、数据静态用宽表;复杂查询、高并发检索用 ES。核心权衡是查询复杂度、数据量与一致性要求。

本题考察跨分片 Join 的替代方案。字段冗余与宽表避免 Join、应用层聚合在内存 Join、ES 承载复杂查询,按查询复杂度与一致性取舍。