找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1913

积分

0

好友

255

主题
发表于 18 小时前 | 查看: 1| 回复: 0

今天是《分库分表 ShardingSphere 原理与实战》系列的开篇,市面上关于分库分表的资料虽然很多,但知识点往往比较零碎,要么是简单堆砌概念,要么是浅尝辄止,很难找到一个系统且深入的系列。这个系列的目标是,从基础理论出发,手把手进行ShardingSphere实战,并结合源码解读和常见问题剖析,力求让新人也能看懂。

话不多说,我们直接进入正题。

在开始ShardingSphere框架的实战之前,我们先来系统性地复习一下分库分表的基础概念。技术名词大多晦涩,理解核心思想远比死记硬背更重要。

否认三连表情包

什么是分库分表

分库分表是为了应对海量数据场景下,单库、单表数据量过大导致数据库性能持续下降而演变出的技术方案。

它由“分库”和“分表”两个独立概念组成,但因为实际操作中两者常常并行,所以习惯合称为分库分表。

分库分表概念图

其核心思想是,通过一定的规则,将原本数据量庞大的数据库拆分成多个独立的数据库,将大表拆分成若干小表,从而让单个库、表的性能(尤其是响应速度)达到最优,最终提升整个数据库集群的性能。

为什么需要分库分表?

单机数据库的存储能力和连接数存在上限,很容易成为整个系统的瓶颈。当单表数据量在百万级别时,我们通常还能通过增加从库、优化索引等手段来提升性能。

但是,一旦数据量朝着千万甚至亿级增长,无论怎么优化,很多数据库操作的性能都会急剧下降。为了减轻数据库负担,缩短查询时间,提升响应速度,分库分表就成了必然选择。

为什么需要分库?

  1. 容量瓶颈:分配给数据库实例的磁盘容量是固定的。数据持续快速增长,单机容量很快会被耗尽,最直接的解决方案就是增加容量,也就是分库。
  2. 连接数瓶颈:单机的容量可以扩展,但数据库的连接数是有限的。在高并发场景下,多个业务同时访问同一个数据库,很容易耗尽连接数,导致 too many connections 错误,使后续请求无法访问。

可以通过以下命令查看MySQL的最大连接数:

show variables like '%max_connections%'

MySQL连接数查询结果

将单一数据库按业务拆分成订单库、会员库、积分库等,不仅能有效分摊读写压力,也提高了系统的容错性。如果你想了解更多关于数据库设计与高可用架构的实践,可以参考云栈社区的相关讨论。

为什么需要分表?

做过报表或大数据量查询的同学,可能都经历过一条SQL执行几十秒甚至更久的场景。

导致查询慢的原因很多,但“数据量过大”是MySQL自身难以通过优化(如索引)根治的问题。其根本原因在于InnoDB存储引擎的聚簇索引B+树层级会随着数据增长而变高,导致磁盘IO次数增加,查询性能自然下降。

阿里的开发手册中有一条建议:单表行数超过500万行或单表容量超过2GB,才推荐进行分库分表。当然,这只是一个参考值,很多公司单表几千万甚至上亿数据也仍在运行。

阿里开发规范建议

什么时候应该考虑分库分表?

技术交流群里经常有人问:到底什么情况下才需要考虑分库分表?

关键在于,分库分表解决的是 “现存海量数据”带来的性能瓶颈,以及对 “未来持续激增”的数据量做出的架构预判

最核心的指标就是数据量。 以一个资源网站为例,初期每日新增数据很少,单库单表足以应对。但当某天数据量暴增至每日百万级,资源表总数据达到千万级,查询响应明显变慢,性能瓶颈开始显现。

对于MySQL而言,当单表数据达到亿级,传统优化手段(加索引、SQL调优)收效甚微时,就应当严肃考虑分库分表了。

既然MySQL存海量数据有瓶颈,那能不能直接用其他方案替代?比如高性能的MongoDB?

当然可以,但这取决于数据类型。目前互联网公司的核心业务数据(如交易、账户)大多仍存储在MySQL、Oracle这类关系型数据库中,因为它们具备NoSQL难以比拟的ACID事务特性、稳定性和成熟的生态。而像评论、点赞这类非核心数据,则完全可以考虑使用MongoDB。

如何分库分表?

分库分表的核心在于对数据进行 分片,并将数据相对均匀地路由到不同的库和表中,同时能够快速定位分片数据并整合查询结果。

拆分可以从两个维度进行:垂直(纵向)和水平(横向)。下面我们以经典的订单业务为例进行说明。

分库分表分类图

垂直拆分

1. 垂直分库
垂直分库通常按照业务和功能维度拆分,遵循“专库专用”原则。例如,将订单、支付、会员、积分等相关表分别放入独立的订单库、支付库、会员库、积分库。

垂直分库示意图

不同业务间禁止直接跨库连表查询,数据交互应通过API接口进行,这也是微服务拆分的重要依据之一。垂直分库分摊了单库压力,但并未解决单表数据量过大的根本问题。

2. 垂直分表
垂直分表针对字段众多的大表,将表中一些不常用或长度较大的字段拆分出去,形成一种“大表拆小表”的模式。

例如,一张t_order表有几十个字段,其中订单金额字段计算频繁。为了不影响主表性能,可以将金额相关字段拆分到独立的t_order_price_expansion扩展表中,两张表通过order_no关联。

垂直分表示意图

数据库以行为单位加载数据到内存。拆分后,核心表只保留高频访问的短字段,单次能加载更多数据到内存,减少磁盘IO,提高索引命中率,从而提升性能。

水平拆分

垂直拆分后,单库/表数据量过大的问题可能依然存在。此时就需要进行水平拆分。

1. 水平分库
将同一张表按规则拆分到不同的数据库实例中,每个库可以位于不同服务器,实现水平扩展。

水平分库示意图

例如,db_order_1db_order_2两个库都有结构相同的t_order表。访问订单时,通过对订单号取模(订单编号 mod 2)来决定操作哪个库。这种方式解决了单库存储和性能瓶颈,但也引入了数据访问需要路由的复杂度。

2. 水平分表
在同一个数据库内,将一张大数据量表按规则切分成多个结构完全相同的子表,每个子表只存储原表的一部分数据。

例如,一张900万数据的t_order表,水平拆分成t_order_1t_order_2t_order_3三张表,每张存300万数据。

水平分表示意图

但水平分表后,所有子表仍在同一个数据库实例中,会竞争同一台物理机的CPU、内存、网络IO等资源。要进一步提升,就需要将子表分散到不同的数据库实例,即结合水平分库,实现分布式存储。

分库分表结合示意图

数据该存在哪个库表?

分库分表后,一张逻辑表会分布到多个物理库和表中,那么数据到底该存到哪里?

这取决于我们反复提到的 “一定规则”,即分片路由算法。常见的算法有:

1. 取模算法

这是最常见的路由方式。对某个关键字段(如订单号order_no)进行哈希取模:hash(order_no) mod N(N为数据库或子表数量)。根据余数i决定数据路由到第i个库或表。

取模算法流程图

  • 优点:实现简单,数据分布相对均匀。
  • 缺点:对集群扩缩容不友好。当机器数N变化时(如宕机一台,N变为N-1),取模规则改变,会导致大量数据路由错误,需要迁移数据。

2. 范围限定算法

根据某些范围字段,如时间或ID区间进行拆分。例如,将user_id在1~1000万的数据放入t_user_1,1000~2000万放入t_user_2,以此类推。

范围算法流程图

  • 优点:单表数据量可控;水平扩展简单,增加节点无需迁移历史数据。
  • 缺点:容易产生“数据热点”。例如按时间分片,大促期间的数据会集中写入最新分片,造成该分片负载过高。

3. 范围 + 取模算法

结合上述两种算法,先按范围分库,再在库内按取模分表。例如,先定义每个库存1000万用户数据,db_1userId 1~1000万,db_2存1000~2000万。然后在每个库内,将用户表拆分成t_user_1t_user_2等,再对userId取模路由。

范围+取模算法示意图

这既避免了数据倾斜,又使得水平扩展(加库)变得容易,无需迁移数据。

4. 预定义算法 & 地理位置分片

  • 预定义算法:事先明确分片规则,直接将某类数据路由到指定库表。
  • 地理位置分片:按地域划分,如华东、华北数据存入不同分片。

分库分表带来的挑战

分库分表在提升性能的同时,也极大地增加了系统架构的复杂度,引入了一系列新问题:

  1. 跨节点查询问题:分页、排序、联合查询(JOIN)变得异常复杂。需要在多个节点查询数据,然后在应用层进行合并、排序,效率低下。
    跨节点数据合并示意图

  2. 分布式事务一致性:数据分布在不同库,跨库事务成为难题。后续通常需要引入Seata或基于XA协议等方案来解决。

  3. 全局唯一主键:分表后,数据库自增ID无法保证全局唯一。需要引入独立的分布式ID生成器(发号器)。

  4. 多库多表治理:面对成百上千个分片表,如何高效地进行建表、监控、排查问题,是一个巨大的运维挑战。

  5. 历史数据迁移:架构落地后,如何平滑地将历史数据迁移到新的分片集群,并保证迁移过程中数据的完整性和业务连续性,是一个复杂工程。

分库分表的架构模式

主要分为两种模式:Client模式(客户端模式)和Proxy模式(代理模式)。

Client模式

分库分表的逻辑整合在应用内部。应用直接连接多个数据库,执行拆分后的SQL,并在本地进行数据聚合。
Client模式架构图

Proxy模式

在应用与数据库之间部署一个独立的代理服务。对应用来说,代理服务就是数据库。代理服务实现了MySQL协议,根据内部配置将SQL转发到正确的分片执行。
Proxy模式架构图

如何选择?

方面 Client模式 Proxy模式
性能 直接连接DB,链路短,性能稍好。 多一层网络跳转,略有损耗。
复杂度 以JAR包形式集成,使用简单。 需独立部署和维护高可用代理服务。
升级 升级需所有应用更新JAR包,成本高。 升级代理服务即可,业务无感知。
治理监控 治理功能内嵌,不便统一管控。 便于实现统一的SQL限流、监控、审计等。

本文系统回顾了分库分表的核心概念,为后续深入ShardingSphere实战打下基础。下一篇文章,我们将对ShardingSphere的基础知识点进行全面梳理。

ShardingSphere知识体系思维导图




上一篇:脚本与风险:一位架构师因自动化工具引发的离职风波
下一篇:分库分表实战详解:垂直与水平拆分原理、路由算法与工具选型
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-1 21:00 , Processed in 0.506056 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表