1.为什么要有分库分表
当数据量很大的时候,分库分表策略可以减少单个服务器的压力,提高查询性能,并提高扩展性,随时可以添加新的数据库来处理更多的请求,甚至做到业务分离,将不同的业务逻辑和数据存储分离,使得每个数据存储集群或者数据表专注于特定的功能,遵循单一责任原则。
2.分库分表方案
1.水平分库
定义 | 以某个字段为依据,按照一定策略(如哈希、范围等),将一个数据库中的数据拆分到多个数据库中 | |
实现方式 | 哈希分库 | 例如,将id字段进行哈希计算,从而分到不同数据库中 |
范围分库 | 例如,将id范围在1~10000的数据放在MySQL_A中, 将id范围在10000~10001的数据放在MySQL_B中 | |
优点 | 1.通过并处理数据的方式来提高并发访问能力 2.降低单个数据库压力,分散存储压力 |
2.水平分表
定义 | 以某个字段为依据,按照一定策略(如哈希、范围等),将一个表中的数据拆分到多个表中 |
实现方式 | 和上列一致 |
优点 | 提高查询性能(一张数据量100的表,一张数据量10的表,肯定是10的表数据查询效率高),适合高并发的读写操作 |
3.垂直分库
定义 | 以表为依据,按照业务归属的不同,将不同的表拆分到不同的数据库中,简单说就是对于不同的业务模块(如用户模块、订单模块、商品模块等),将相关的表拆分到不同的数据库中 |
举例 | 将 user 、user_profile 、user_preferences 表存储在 user_db 数据库,将 order 、order_detail 表存储在 order_db 中 |
优点 | 将不同业务数据分开,提高稳定性,可扩展性,降低耦合,大大降低了结构解读难度 |
4.垂直分表
定义 |
以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和
扩展表)中
|
举例 | 假设一个user表中字段为 id,username,email,profile_photo_url, followers_count, created_at,bio,website_link,根据活跃性进行分表后:主表:id,username,email,created_at 扩展表:id, profile_photo_url,followers_count,bio,website_link |
优点 | 提高了对高频数据的访问效率,通过减少I/O操作加快查询速度 |
3.常用的分库分表中间件
Apache ShardingSphere | Vitess |
MyCAT | Citus |
TDDL |
Oceanus
|
4.分库分表可能遇到的问题
1.事务问题:使用分布式事务解决。例如,使用分布式事务中间件、或者通过使用事务补偿,来达到最终一致性。
2.跨节点的join,Count、Order By、Group By 以及聚合函数问题:
join | 分别将需要的数据查询处理,然后在通过业务代码将其合并 |
Count | |
Order By | |
Group By |
3.数据迁移,容量规划,扩容等问题
4.ID 问题:数据库被切分后,不能再依赖数据库自身的主键生成机制。使用UUID
5.分页排序问题:可以使用增加pageSize的方式(提高每一次的查询条数,达到用户减少查询次数的目的)
5.策略常用场景
只分库不分表
|
只分表不分库
|
既分库又分表
|
当数据库的读写访问量过高,可能会出现数据库连接数不够用的情况。此时我们就需要考虑分库,通过增加数据库实例的方式来获得更多的数据库连接,从而提升系统的并发性能
|
在单表存储中,数据量非常大,且并发量不高,连接够用,但数据写入和查询的性能出现了瓶颈。此时,就需要考虑分表了,将数据拆分到多张表中来减少单表存储的数据量,从而提升读写的效率
|
结合前面的两种情况,如果同时满足前面的两个条件,也就是数据连接也不够用,并且单表的数据量也很大,从而导致数据库读写速度变慢的情况,这个时候就要考虑既分库又分表
|
例如:假设数据库连接数10,此时来11个请求,那么就会有一个无法打到数据库上,所以增加数据库实例,可以大幅度提高性能 |