文章目录
- 前言
- 一、为什么要分库分表?
- 二、分库分表的策略:
- 2.1 垂直切分:
- 2.2.1 垂直分库:
- 2.2.2 垂直分表:
- 2.2.3 垂直拆分的优缺点:
- 2.2 水平切分:
- 2.2.1 库内分表:
- 2.2.2 分库分表:
- 2.2.3 水平切分优缺点:
- 三、分库分表的实现方案:
- 3.1 数据库代理类中间件:
- 3.2 数据源代理实现:
- 四、数据迁移:
- 4.1 停机迁移:
- 4.1 不停机迁移:
- 总结:
- 参考:
前言
随着单库中业务数据的增加,数据库的查询QPS越来越高,相应的,对数据库的读写所需要的时间也越来越多,数据库的读写性能可能会成为业务发展的瓶颈。对应的,就需要做数据库性能方面的优化。如果单表数据量过大,当数据量超过一定量级后,常规的优化手段已经不起作用了,比如:SQL调优、添加索引、主从复制、读写分离,这是量变产生了质变,这时候就需要去换个思路来解决问题,既然单台数据库无法容纳如此多的数据,那么就把这些数据分而治之,分散到不同的表甚至不同的库中去,以此解决单台数据库的性能瓶颈问题。
一、为什么要分库分表?
关系型数据库以MySQL为例,单机的存储能力、连接数是有限的,它自身就很容易会成为系统的瓶颈。当单表数据量在百万以里时,我们还可以通过添加从库、优化索引提升性能。一旦数据量朝着千万以上趋势增长,再怎么优化数据库,很多操作性能仍下降严重。为了减少数据库的负担,提升数据库响应速度,缩短查询时间,这时候就需要进行分库分表。分库分表有一下几个方面的优势:
-
扩展性:当应用的数据量增长到单个数据库无法处理的规模时,分库分表可以提供更大的扩展性。通过将数据分布在多个数据库和数据表中,可以增加存储容量和吞吐量,以满足大规模并发请求。
-
性能:拆分数据到多个数据库和数据表中可以提高查询和写入操作的性能。每个数据库和数据表都处理部分数据,减轻了单个数据库的负载压力,允许更高效的查询和数据操作。
-
可用性:通过分库分表,可以实现多个独立实例,提高整体系统的可用性。如果一个数据库或数据表发生故障,其他数据库和数据表仍然可用,保持部分功能仍能正常运行,提高了系统的容错能力。
-
管理和维护:大规模单一数据库的管理和维护成本往往很高。通过分库分表,可以将数据划分为更为管理和维护的单元,更便于对每个单元进行备份、恢复、优化和维护操作。
-
安全性:分库分表可以提供更好的数据安全性。敏感或机密的数据可以存储在单独的数据库中,并进行额外的安全措施和权限管理,减少数据泄露和风险。
需要注意的是,分库分表并非在所有情况下都是必要的。分库分表需要综合考虑应用需求、数据模型、查询模式、数据一致性和系统复杂性等因素来决定是否进行分库分表,以及如何进行拆分和管理。
二、分库分表的策略:
分库分表就是要将大量数据分散到多个数据库中,使每个数据库中数据量小响应速度快,以此来提升数据库整体性能。核心理念就是对数据进行切分(Sharding),以及切分后如何对数据的快速定位与整合。针对数据切分类型,大致可以分为:垂直(纵向)切分和水平(横向)切分两种。
2.1 垂直切分:
垂直切分又细分为垂直分库和垂直分表;
2.2.1 垂直分库:
垂直分库是基于业务分类的,和我们常听到的微服务治理观念很相似,每一个独立的服务都拥有自己的数据库,需要不同业务的数据需接口调用。而垂直分库也是按照业务分类进行划分,每个业务有独立数据库。
2.2.2 垂直分表:
垂直分表是基于数据表的列为依据切分的,改变表结构,增加表的数量,是一种大表拆小表的模式。
数据库是以行为单位将数据加载到内存中,这样拆分以后核心表大多是访问频率较高的字段,而且字段长度也都较短,可以加载更多数据到内存中,增加查询的命中率,减少磁盘IO,以此来提升数据库性能。
2.2.3 垂直拆分的优缺点:
优点:
-
数据隔离:垂直拆分可以将不同类型或功能的数据分离到不同的数据库中。这样可以避免不同数据之间的冲突、干扰和复杂性,提高数据的隔离性和独立性。
-
性能提升:将热点数据与不常用的数据分离开来,可以对热点数据进行优化,提高查询和操作的性能。例如,将经常被查询的表放在高性能的服务器上,提供更快的响应时间。
-
安全性提高:通过垂直拆分,可以将核心数据和敏感数据放置在独立的数据库中,并应用更严格的安全措施和权限控制。这样可以降低数据泄露和风险,提高数据的安全性。
-
管理和维护的简化:垂直拆分将不同类型的数据分散到多个数据库中,简化了管理和维护的复杂性。可以更专注地管理每个数据库,并根据不同需求进行备份、优化和维护操作。
缺点:
-
数据关联与一致性:垂直拆分容易导致数据之间的关联问题和一致性的挑战。如果需要跨数据库进行查询和操作,会增加开发和维护的复杂度,并可能引入数据不一致的风险。
-
扩展性限制:垂直拆分可能对扩展性产生限制。如果一个特定表的数据量增长迅速,而其他表的数据却不增长或增长较慢,可能导致某些数据库的负载过重,需要重新调整拆分策略。
-
跨库查询与事务:由于数据被拆分到不同的数据库中,跨库查询和事务的处理变得更加复杂和耗费资源。需要设计合适的机制来支持跨库操作和确保数据一致性。
总的来说,垂直拆分的优点包括数据隔离、性能提升、安全性增强和管理简化。但同时也带来了数据关联和一致性的挑战,以及对扩展性和跨库操作的限制。因此,在进行垂直拆分时需要仔细考虑业务需求和数据模型,确保拆分的合理性和可行性。
2.2 水平切分:
水平切分将一张大数据量的表,切分成多个表结构相同(表结构不变),而每个表只占原表一部分数据,然后按不同的条件分散到多个数据库中。水平切分又分有库内分表和分库分表。
2.2.1 库内分表:
库内分表虽然将表拆分,但子表都还是在同一个数据库实例中,只是解决了单一表数据量过大的问题,并没有将拆分后的表分布到不同机器的库上,还在竞争同一个物理机的CPU、内存、网络IO。
2.2.2 分库分表:
分库分表则是将切分出来的子表,分散到不同的数据库中,从而使得单个表的数据量变小,达到分布式的效果。
2.2.3 水平切分优缺点:
优点:
-
扩展性:水平切分允许将数据行分布在多个数据库或数据表中,使得系统能够处理更大的数据量和更高的并发请求。通过横向扩展,可以提升系统的性能和容量。
-
并发性能:由于数据行被分散处理,每个数据库或数据表只负责部分数据,可以并行处理并发请求,提高系统的响应速度和并发读写能力。
-
高可用性:通过将数据行复制到不同的数据库或数据表中,水平切分提供了冗余备份机制,从而提高了系统的可用性。当某个节点或分片发生故障时,可以从其他节点获取数据,实现障转移与恢复。
-
数据隔离:水平切分使得不同数据行分布在不同的数据库或数据表中,实现了数据的隔离和分离。这种隔离性可以提高系统的稳定性和可靠性,减少某个数据行的故障对其他数据行的影响。
缺点:
-
数据一致性:水平切分可能导致数据的一致性问题。例如,跨多个数据库或数据表的查询可能需要额外的机制来保证数据一致性,如分布式事务处理或一致性哈希算法。
-
查询复杂性:某些查询需要跨多个数据库或数据表获取数据,这会增加查询的复杂性和开销。需要特殊的查询机制来优化跨分片查询操作。
-
分片管理:水平切分需要充分考虑数据行的划分和分片管理。均衡地划分分片,免部分分片负载过重,需要仔细的规划和管理。
-
可操作性:水平切分后,数据库的操作和维护变得更加复杂。例如,备份和恢复需要分别处理每个分片,管理分布式系统的操作复杂度较高。
综上所述,水平切分能够实现扩展性、并发性能和高可用性的提升,同时也带来了数据一致性、查询复杂性、分片管理和操作复杂性的挑战。在进行水平切分时,需要仔细考虑业务需求、数据模型和系统架构,合理划分分片并设计相应的管理和查询机制。
三、分库分表的实现方案:
分库分表的实现可以通过 数据库代理或者数据源代理实现:
3.1 数据库代理类中间件:
这类分库分表中间件的核心原理是在应用和数据库的连接之间搭起一个代理层,应用连接这个代理层发送SQL请求,代理层再根据用户配置的分库分表等规则进行解析后,将SQL路由到真实的数据库,代表的产品是MyCAT。
优点:对于应用透明,应用可以像连接MySQL一样连接MyCAT,配置简单且无代码侵入
缺点:SQL需要进行额外的转发,且部署MyCAT增加组件运维成本,且对开发和运维人员要求较高
3.2 数据源代理实现:
代表框架为Sharding-JDBC:定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
优点:性能高,无需额外部署和依赖
缺点:需要改动大量配置和SQL代码,且存在部分不兼容SQL的情况,代码侵入性高
四、数据迁移:
数据迁移 主要包括停机迁移和不停机迁移;
4.1 停机迁移:
停机迁移,将系统或服务停机,将数据从源环境迁移到目标环境,在此期间服务不可用,适用于短时间内可以完成数据迁移的场景;
4.1 不停机迁移:
不停机迁移是指在迁移过程中不中断系统或服务的运行,采用数据同步、分批迁移、双写模式或代理中间件等技术和方法来实现。在迁移过程中不中断系统或服务的运行,保持系统的可用性和连续性。
思想:
- 对于历史的数据,截止一个时间点;
- 对截止时间点的数据通过程序进行数据迁移;
- 对于新产生的数据,通过cannal 将新产生的数据,同步到消息队列中;
- 在历史数据迁移完成之后,通过程序,消费增量数据;
- 增量数据消费完成之后,将新的数据库上线,旧的数据库下线;
总结:
随着业务数据量的增加,单库单表有明显的性能瓶颈,此时可以考虑对数据进行垂直或者水平的拆分,以达到多台db 数据库分担流量,提高数据库读写性能。
参考:
1 分库分表的实现;
2 分库分表策略;