分库分表
Posted nogos
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分库分表相关的知识,希望对你有一定的参考价值。
互联网行业中,由于有庞大的用户量存在,所以会产生海量的请求。这些请求产生的交易数据和信息都需要存储在关系型数据库中。由于数据量很大,单个数据库已经难以容纳所有数据,所以产生了分库分表的需求。分库分表,顾名思义,就是使用多个库和多个表甚至多个数据库实例来存储海量的数据。
什么是分库分表
数据拆分是对数据分而治之的通用概念,在数据库存储方面是通过分库分表来实现数据拆分的,对数据的拆分主要体现在两个方面:垂直拆分和水平拆分。
垂直拆分
根据业务的维度,将原来的一个库(表)拆分成多个库(表),每个库(表)与原来的结果不同。
优点:
- 拆分后业务清晰,拆分规则明确。
- 系统之间进行整合或扩展容易。
- 按照成本、应用的重要程度、应用的类型将表放在不同的机器上,便于管理。
- 便于实现动静分离、冷热分离的数据库表的设计模式。
- 数据维护简单。
缺点:
- 部分业务表无法关联Join,只能通过接口方式解决,提高了系统的复杂性。
- 事务处理复制。
水平分片
根据分片算法,将一个库(表)拆分为多个库(表),每个库依旧保留原有的结构。
优点:
- 单库单表的数据保持在一定的量级,有助于性能的提高。
- 切分的表的结构相同,应用层改造较少,只需要增加路由规则即可。
- 提高了系统的稳定性和负载能力。
缺点:
- 切分后,数据分散,很难利用数据库的Join操作。
- 拆分规则难以抽象。
- 分片事务的一致性难以解决。
- 数据库扩容的难度和维护成本大。
以上两种拆分方式可能会同时存在,在互联网应用的开发过程中,通常先进行垂直拆分,使单体应用 拆分成多个微服务,在微服务内再进行水平库(表)拆分。
什么时候需要分库分表
- 如果库中表数据达到一定量级,则需要进行分表。这样数据被分散到不同的表上,表的索引大小得到了控制,会提升查询性能,对索引及表结构的变更会更加方便和高效。
- 如果数据库的吞吐量达到了瓶颈,就需要增加数据库实例,利用多个数据库实例来分解大量数据库请求带来的系统压力。
分库分表的典型实例
假设我们的某个业务使用了User表,而User表有16亿条数据记录,若将这16条数据记录进行的增删改操作放在一个数据库单表中,则性能一定不会太好。
首先,我们可以将数据进行行分片处理。例如,按照5000万条数据记录一个单位来分片,总共32个分片,对应32个数据库表。如果,我们将32个数据库表放入一个数据库实例,单个数据库实例的网卡I/O、内存、CPU和磁盘性能是有限的,随着数据访问频率的增加,会达到单个数据库实例的瓶颈。
因此,我们可以把这32个表分散到多个数据库和多个数据库实例中。
分库分表的实现方式
客户端分片
顾名思义,客户端分片就是使用分库分表的数据库的应用层直接操作分片逻辑,分片规则需要在同一个应用的多个节点间同步,每个应用层都嵌入一个操作分片的逻辑实现(分片规则)。
优点:性能高,实现简单。
缺点:侵入业务。
代理分片
代理分片就是在应用层和数据库层之间增加一个代理层,把分片的路由规则配置在代理层,代理层对外提供统一规范的接口给应用层。应用层的开发人员不用关心分片规则,只需关心业务逻辑实现。
优点:分片逻辑对应用层透明
缺点:增加一层网络传输,性能有所影响。
支持事务的分布式数据库
现在有很多产品,例如OceanBase、TiDB等,都对外提供可伸缩的体系架构,并提供一定的分布式事务支持,将可伸缩的特点和分布式事务的实现包装到分布式数据库内部实现,对使用者透明,使用者不需要直接控制这些特性。例如TiDB对外提供统一的接口,让应用层可以像mysql等传统数据库一样来使用TiDB;而无需关心其内部是如何伸缩、分片及处理分布式事务的。
分库分表引起的问题
分库分表按照某种规则将数据的集合拆分成多个子集合,数据的完整性被打破,因此在特定场景下会引入问题。
扩容和迁移问题
如果,某个分片已经达到了承载数据的最大值,就需要对集群进行扩容。通用的扩容包括如下五个步骤:
- 按照新旧分片规则,对新旧数据库进行双写。
- 将双写前按照旧分片规则写入的历史数据,根据新分片规则迁移写入新的数据库。
- 将按照旧的分片规则查询改成按照新的分片规则查询。
- 将双写数据库逻辑从代码中下限,只按照新的分片规则写入数据。
- 删除按照旧分片规则写入的历史数据。
数据量巨大,迁移过程中,容易产生数据不一致。
查询问题
在分库分表后,如果查询的标准是分片的主键,则可以通过分片规则再次路由并查询。但是,对于其他主键的查询、范围查询、关联查询、查询结果排序等,并不是按照分库分表的维度来查询的。
常用的解决方案
- 在多个分片表查询后合并数据集,这种方式的效率低下。
- 记录两份数据,例如一份按照卖家维度分表,一份按照商品维度分表。
- 通过所有引擎解决,但如果实时性要求很高,就需要实现实时搜索。
事务实现
数据分散,跨数据库实现困难。
内容源自:《可伸缩服务架构——框架和中间件》
以上是关于分库分表的主要内容,如果未能解决你的问题,请参考以下文章
TribeDB — Node.js 的 MySQL 分表分库访问中间件(牛逼!)
DB 分库分表:一种支持自由规划无须数据迁移和修改路由代码的 Sharding 扩容方案