分表分库
1.分库(Database Sharding)
- 定义:将数据拆分到多个数据库,每个数据库存储一部分数据
- 目的:解决单一数据库的存储和性能瓶颈,提供系统的并发能力
示例:
- 原始数据库:db_users
- 分库后: db_users_1, db_users_2, db_users_3
2.分表(Table Sharding)
- 定义:在一个数据库内,将一张大表拆分为多张小表。
目的:减少单表的数据量,挺高查询和写入性能
- 原始数据库:users
- 分表后:users_0,users_1,users_2
3.分库分表(Database Sharding, Table Sharding)
- 定义:结合分表和分库,将数据分布到多个库和表
- 目的:同时解决数据库和表的性能瓶颈问题。
示例:
- 原始数据单库单表
- 分表后:db_users_1.users_0,db_users_2.users_1
分库分表的优点
性能提升
- 减少单个数据库或者表的数据量,提升查询,插入,更新的性能
提升并发能力
- 将请求分散到不同的库和表中,降低单点的压力,提高整体系统吞吐量
提高扩展性
- 数据量增长时可以通过增加库或者表来实现水平扩展,而不是垂直扩展硬件资源
提升数据存储容量
- 单个数据库的存储上线(例如2TB)限制可以通过多库分散突破
分库分表的缺点
复杂性增加
- 数据路由、分片逻辑和事务处理的复杂度上升。
跨库查询困难
- 查询涉及多个库时,需要合并结果集,增加延迟和计算量
分布式事务
- 传统数据库的事务特性(ACID)在分布式场景下很难实现,需要引入分布式事务管理工具
数据迁移复杂
- 分库分表后如果需要调整分片规则或扩展分片,数据迁移成本高
运维成本增加
- 需要管理更多的数据库实例和表,运维复杂度提升
分库分表的常见策略
范围分片
- 规则:根据某个字段的值的范围分片
- 示例:用户ID 1-10000放在db_1, 10001-20000放在db_2
- 优点:简单直观,方便维护。
- 缺点:容易出现数据倾斜,导致分片压力过大
按哈希分片
- 规则:对分片键(如用户 ID、订单号)进行哈希计算后取模
- 示例:user_id % 4 分为 4 个分片。
- 优点:数据分布较均匀,避免热点问题。
- 缺点:扩容时需要重新计算哈希,导致数据迁移成本高
按时间分片
- 规则:根据时间字段(如创建时间)将数据分片
- 示例:2024 年数据放在 db_2024,2025 年数据放在 db_2025
- 优点:适合时间序列数据,历史数据方便归档
- 缺点:可能导致部分分片(最新数据)压力较大
- 按地理位置分片
分库分表的实现方式
- 数据库中间件
- 说明:通过数据库中间件(如 ShardingSphere、MyCAT)实现分库分表。
特点:
- 对应用透明,不需要修改业务代码。
- 支持跨库查询、分布式事务等功能。
- 缺点:增加系统复杂性,可能引入性能瓶颈。
- 应用层控制
- 说明:在应用程序中自行实现分库分表逻辑。
特点:
- 灵活性高,可根据业务需求定制。
- 无额外中间件依赖。
- 缺点:开发工作量大,运维复杂。
- 云原生数据库
- 说明:使用云厂商提供的分布式数据库(如 TiDB、Amazon Aurora)。
特点:
- 内置分库分表能力
- 易于维护
- 缺点:成本较高,对云服务依赖强。
分库分表导致主键冲突
自增主键导致冲突:
- 在多个数据库或表中使用自增主键时,由于各分片独立维护自己的自增计数器,同样的主键值可能在多个分片中生成,从而导致冲突
分布式 ID 生成规则设计不当:
- 自行设计的 ID 生成策略(如时间戳拼接、随机数等)未能确保分片间的唯一性,导致冲突
不使用分片键生成 ID:
- 数据分片时主键生成逻辑未与分片键关联,导致不同分片中出现相同的主键。
主键范围未分区
- 分片时没有为主键分配独立的范围,导致不同分片中的主键值相同
如何解决主键冲突
- 使用全局唯一ID:通过分布式 ID 生成器来确保每个分片生成的主键全局唯一
常见方案:
雪花算法:
- 基于时间戳 + 数据中心ID + 机器ID + 自增序列
- 生成的 ID 是全局唯一且趋势递增的 64 位整数
UUID(通用唯一标识符)
- 生成 128 位的唯一字符串
- 缺点是长度较长,查询效率低
数据库中间件(如 ShardingSphere):
- 提供全局主键生成服务
适用场景:
- 分布式系统中需要全局唯一主键的场景。
- 为主键分配分片标识
常见方案:
分片 ID + 自增序列:
- 主键格式为
[shard_id][local_id]
,例如: - 分片 A:1_00001, 1_00002...
- 分片 B:2_00001, 2_00002...
- 主键格式为
范围分配:
不同分片分配不同的主键范围:
- 分片 A 的主键范围是 1~1亿。
- 分片 B 的主键范围是 1亿+1~2亿。
优点:
- 简单易实现,无需复杂逻辑。
缺点:
- 主键设计不够灵活,范围用尽需要重新分配。
- 基于分片键生成主键
方法:
- 主键的生成规则与分片键绑定,确保分片键和主键的对应关系。
举例:
- 如果分片键为 user_id,主键可以为 hash(user_id) + 时间戳。
- 逻辑主键与物理主键分离
方法:
- 在数据库表中使用逻辑主键(如订单号、业务 ID),物理主键使用内部自增 ID。
优点:
- 业务层逻辑主键具有全局唯一性,物理主键的冲突只在表内部处理。
使用Sharding JDBC实现分库分表
使用 ShardingSphere-JDBC 实现分库分表是一种高效且灵活的方式。ShardingSphere 是一个开源的分布式数据库中间件,其中 ShardingSphere-JDBC 通过代理数据库操作,在应用层实现透明的分库分表功能。以下是实现的详细步骤和关键点。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。