首页 >> 基础教程

mysql分库策略

         MySQL 分库策略是为了解决单库性能瓶颈(数据量过大、并发过高、I/O压力大)和实现水平扩展的核心手段。它通常与分表策略结合使用(合称分库分表Sharding),但分库更侧重于将数据分散到不同的数据库实例上。

1. 垂直分库 (Vertical Sharding - By Business Module)

  • 核心思想: 按照业务功能模块领域将不同的表拆分到不同的数据库实例中。

  • 实现方式:

    • 将与用户相关的表(useruser_profileuser_address)放到 用户库

    • 将与商品相关的表(productproduct_categoryproduct_sku)放到 商品库

    • 将与订单相关的表(orderorder_itempayment)放到 订单库

    • 将与内容相关的表(articlecomment)放到 内容库

  • 优点:

    • 业务解耦清晰: 不同业务模块独立,便于维护和扩展。

    • 降低单库压力: 将负载分散到不同数据库实例。

    • 方便按业务扩展: 可以针对增长快的业务模块单独扩容其对应的数据库资源。

    • 减少跨表Join: 同一业务域内的表通常还在同一个库内,库内Join效率较高。

  • 缺点:

    • 无法解决单表过大问题: 如果某个业务模块内的单张表数据量或访问量极大(如海量订单表),垂直分库本身无能为力,需要进一步结合水平分表/分库。

    • 跨库事务复杂: 涉及多个业务库的事务需要分布式事务解决方案(如XA、TCC、Saga、Seata等),实现复杂且性能有损耗。

    • 跨库查询困难: 需要跨多个库进行关联查询(如查用户信息和其订单)变得非常低效,通常需要在应用层做数据聚合或使用其他存储(如Elasticsearch)。

  • 适用场景: 业务模块相对独立、耦合度低、模块间数据交互较少的大型系统。这是最常用也是优先考虑的拆分方式。

2. 水平分库 (Horizontal Sharding - By Data Row)

  1. 核心思想: 将同一张表的数据按照某种规则(分片键/Sharding Key)分散存储到多个结构相同的数据库实例中。每个分片库都包含该表的一部分数据。

  2. 关键要素:

    1. 分片键 (Sharding Key): 选择用于决定数据行分配到哪个分片的列。常见的有user_idorder_idshop_idregion_id等。选择至关重要,应满足业务高频查询场景。

    2. 分片算法 (Sharding Algorithm): 根据分片键的值计算目标分片(库、表)的算法。

  3. 常用分片算法:

    1. 范围分片 (Range Sharding):

      1. 按分片键的连续范围划分。例如:user_id 1-1000万在 db1, 1000万-2000万在 db2

      2. 优点: 易于管理,范围查询高效(如果查询条件包含分片键范围)。

      3. 缺点: 容易产生数据倾斜(新数据集中写入最新分片,造成热点);扩容时可能需要迁移大量数据。

    2. 哈希分片 (Hash Sharding):

      1. 对分片键值进行哈希计算(如MD5, CRC32, 一致性哈希),然后根据哈希值取模或其他方式映射到特定分片。例如:hash(user_id) % 4 决定落在哪个库。

      2. 优点: 数据分布相对均匀,减少热点问题。

      3. 缺点: 扩容困难(增加分片数量时,取模规则改变导致数据需要大规模重新分布/迁移);范围查询效率低(需要查询所有分片)

    3. 一致性哈希分片 (Consistent Hashing):

      1. 哈希分片的优化版。将分片节点和数据都映射到一个哈希环上。数据根据其哈希值顺时针找到最近的节点。增加或删除节点时,只影响环上相邻小部分数据,大大减少数据迁移量。

      2. 优点: 扩容缩容时数据迁移量小。

      3. 缺点: 实现相对复杂;仍然存在少量数据迁移。

    4. 列表分片 (List Sharding):

      1. 根据分片键的枚举值或特定列表映射到分片。例如:按 region_id (bjshgzsz) 分配到不同的地域分库。

      2. 优点: 规则明确,直接按业务属性划分。

      3. 缺点: 灵活性差,新增枚举值或改变映射关系需要修改配置;也可能存在数据不均匀。

    5. 复合分片 (Composite Sharding):

      1. 结合使用以上多种策略。例如:先按 user_id 范围分库,再在库内按 user_id 哈希分表。

  4. 优点:

    1. 解决海量数据存储和访问: 有效分散单库单表的数据量和访问压力。

    2. 高性能高并发: 读写负载被分散到多个节点。

    3. 高可用性: 一个分片故障不影响其他分片(需要配合高可用方案如主从)。

  5. 缺点:

    1. 架构复杂: 需要引入分库分表中间件或自研路由逻辑。

    2. 跨分片查询复杂: 涉及多个分片的查询(如不带分片键的条件查询、聚合查询、排序分页)非常麻烦且低效,通常需要查询所有分片然后在应用层合并结果。

    3. 跨分片事务复杂: 同样需要分布式事务。

    4. 扩容复杂度高: 尤其是哈希分片,扩容时数据迁移是痛点。一致性哈希缓解了此问题。

    5. 维护成本高: DDL变更(如加索引、改表结构)需要在所有分片上执行。

  6. 适用场景: 单表数据量巨大(亿级以上)、并发读写极高、垂直分库后仍无法满足性能需求的场景。如大型电商平台的订单表、用户行为日志表等。

3. 混合分库策略

  • 核心思想: 在实践中,通常先进行垂直分库(按业务拆分),再对垂直分库后的大表进行水平分库(按数据行拆分)

  • 示例:

    • 垂直分库:拆分成 用户库商品库订单库

    • 水平分库:由于订单库中的 order 表数据量巨大,再对 order 表按 user_id 进行水平分库(分成 order_db0order_db1order_db2order_db3)。

  • 优点: 结合了两种策略的优势,是大型分布式系统最常见的数据库拆分方案。

  • 缺点: 同时具有两种策略的复杂性。


实施分库的需要关注点

  1. 分库分表中间件 (Sharding Middleware):

    • 应用透明性:让应用程序像访问单库单表一样访问分库分表后的数据。

    • 核心功能:SQL解析、路由(根据分片键定位目标库表)、结果归并、读写分离支持、分布式事务支持(弱)、分布式主键生成等。

    • 流行方案:ShardingSphere-JDBC (Java 客户端层代理, 轻量级, 性能好),ShardingSphere-Proxy (独立中间件, 支持多语言), MyCat (老牌中间件), Vitess (Kubernetes 原生, 云友好)。

  2. 分布式全局唯一ID生成:

    • 分库后,数据库自增ID不再适用(不同库会产生相同ID)。

    • 常用方案:Snowflake算法/UUID(较长, 无序)/ Redis自增/ Leaf (美团)/ TinyID (滴滴)/数据库号段模式。

  3. 分布式事务:

    • 跨多个库的写操作需要保证原子性。

    • 常用方案:基于XA协议的强一致(性能差)/ 柔性事务(最终一致):TCC (Try-Confirm-Cancel), Saga (补偿事务), 本地消息表事务消息 (如RocketMQ)。

  4. 跨分片查询:

    • 应用层聚合:中间件查询所有相关分片,在内存中排序、分页、聚合。效率低,资源消耗大。

    • 使用其他存储:将需要复杂查询的数据同步到适合检索的存储引擎(如Elasticsearch)进行查询。

    • 基因法:在分片键中融入查询维度的信息(如将shop_id融入order_id),使按店铺查订单的请求能路由到特定分片,避免全扫描。

  5. 数据迁移与扩容:

    • 在线不停服扩容是巨大挑战。

    • 常用工具:pt-online-schema-change (OSC), gh-ost (GitHub), 中间件自带工具(如ShardingSphere的Scaling)。

    • 策略:双写过渡、数据同步、一致性哈希减少迁移量。


最新文章
mysql分页问题2025-08-04
千万数据先insert和先建索引哪个快2025-08-04
MySQL 中大小表关联查询如何优化2025-08-04
sql技巧-每个班年龄排前两名的人2025-08-03
MySQL 导致 cpu 飙升的话,要怎么处理呢?2025-07-29
MySQL 中为千万级大表添加字段2025-07-29
mysql中百万级别以上的数据如何删除2025-07-29
分库分表带来的问题2025-07-29
mysql中常用的分库分表中间件有哪些2025-07-29
mysql不停机扩容2025-07-29
备案号:蜀ICP备2023042032号-1