赞
踩
关系型数据库以MySQL为例,其单机的存储能力、连接数是有限的,这使得MySQL很容易会成为一个系统的性能瓶颈。当单表数据量在百万级时,我们还可以通过优化索引、添加从库等方式来提升性能。然而一旦数据量跃向千万级,那么再怎么优化数据库,都无法避免数据库操作性能的严重下滑。
为了减少数据库的负担、提升数据库响应速度、缩短查询时间,这时候就需要进行分库分表 。
分库分表就是要将大量数据分散到多个数据库中,减少每个数据库中的数据量、加快响应速度,以此来提升数据库整体性能。其核心思想就是如何对数据进行切分( Sharding ),以及切分后如何对数据快速地定位与整合。
针对数据切分类型,大致可以分为垂直切分和水平切分两种。
垂直切分,也称为纵向切分,是按照业务模块进行切分,将不同模块的表切分到同一或不同的数据库中。垂直切分又分为垂直分库和垂直分表:
垂直分库
垂直分库是基于业务分类的,根据不同的业务将表分到不同的数据库中。这与微服务管理很相似,微服务中每一个独立的服务都拥有自己的数据库,需要不同业务的数据需接口调用。
垂直分表
垂直分表是基于数据表的列为依据切分的,是一种大表拆小表的模式。
例如:一个商品表(product)有很多字段,比如价格,商品详情等。用户在进入一个商城的时候,琳琅满目的商品扑面而来,只有当我们真正的需要了解某个产品的时候,才会点进去查看该产品的详情介绍,于是在设计表结构的时候就可以将商品明细信息单独拆分到扩展表(product_extend)中:
数据库是以行为单位将数据加载到内存中,这样拆分以后核心表大多是访问频率较高的字段,而且字段长度也都较短,可以加载更多数据到内存中,增加查询的命中率,减少磁盘IO,以此来提升数据库性能。
垂直切分可以实现业务间解耦,不同业务的数据进行独立的维护、监控、扩展。在高并发场景下,一定程度上缓解了数据库的压力。
然而垂直切分在一定程度上提升了开发的复杂度,由于业务的隔离性,很多表无法直接访问,必须通过接口方式聚合数据。垂直切分也同时增加了分布式事务的管理难度。
通过垂直切分,可以一定程度上缓解数据库的压力,但无法从根本上解决单表数据量过大的问题。当我们无法对业务逻辑进一步细粒度切分,且此时依旧存在单库读写、存储性能瓶颈的问题,就需要考虑进行水平切分。
水平切分,也称横向切分,是将一张大表以规定的切分规则,按行切分成不同的表或者切分到不同的库中。换言之:水平切分就是将一张大数据量的表,切分成多个表结构相同,且每个表只占原表一部分数据,然后按不同的
条件分散到一个或多个数据库中。
水平切分又分为库内分表和分库分表两种:
库内分表
库内分表将表拆分在同一个数据库实例中。这种拆分方式只是解决了单一表数据量过大的问题,并没有将拆分后的表分布到不同机器的库上。那么对这些表对操作,会竞争同一个物理机的CPU、内存、网络IO。
分库分表
分库分表则是将按照一定规则切分出来的子表,分散到不同的数据库中,从而使得单个表的数据量变小,以达到分布式的效果。
水平切分解决了高并发时单库数据量过大的问题,提升了系统的稳定性和负载能力,对于业务系统改造的工作量不是很大。
然而水平切分跨库之间的事务难以保证其一致性。同时,跨库的join关联查询性能较差,扩容的难度和维护量都相对较大。
分库分表以后会出现一个问题,一张表会出现在多个数据库里,到底该往哪个库的表里存呢?
根据取值范围
按照时间区间或ID区间来切分。比如说:假设有一张用户表(User)需要切分,可以定义每个库的User表里只存10000条数据,第一个库 userId 从1 ~ 9999,第二个库10000 ~ 20000,第三个库20001 ~ 30000…以此类推。同理,也可以按照日期等其他业务逻辑字段进行切分。
根据取之范围切分的优点:
(1)单表数据量是可控的。
(2)且水平扩展简单只需增加节点即可,无需对其他分片的数据进行迁移。
(3)能快速定位要查询的数据在哪个库。
根据取之范围切分的缺点:
(1)由于连续分片可能存在数据热点,如果按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁的读写,而有些分片存储的历史数据,则很少被查询。
hash取模(对hash结果取余)
hash取模(hash() mod N
)的切分方式比较常见,仍以User表为例,对数据库从 0 到 N-1 进行编号,对 User 表中 userId 字段哈希运算得到的值进行取模,得到余数 i:
i = 0:存第一个库,
i = 1:存第二个库,
i = 2:存第三个库,
以此类推…
这样同一个用户的数据都会存在同一个库里,用 userId 作为条件查询就很好定位了。
hash取模切分的优点:
(1)数据分片相对比较均匀,不易出现某个库并发访问的问题
hash取模切分的缺点:
(1)这种算法存在一些问题,当某一台机器宕机,本应该落在该数据库的请求就无法得到正确的处理,这时宕掉的实例会被踢出集群,此时算法变成hash(userId) mod (N-1),用户信息可能就不再在同一个库中。
自己开发分库分表工具的工作量是巨大的,好在业界已经有了很多比较成熟的分库分表中间件,我们可以将更多的时间放在业务实现上:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。