数据库分库分表策略,如何分库,如何分表?

  导语:随着线下店业务发展,线下店开店数越来越多,价格系统的数据增长非常快速,部分单表已达到3亿之多,为了适应业务的发展,考虑对价格系统进行分库分表,因此特别了解了一下分库分表的相关知识,根据相关资料,再次复习一下。
  大家知道,随着流量和数据增长,关系型数据库本身往往容易成为系统的瓶颈点,读写分离能缓减读写压力,却并不能分散存储压力,当数据达到一定量以后,单台数据库服务器会成为瓶颈,主要体现在以下几个方面:

  • 数据量太大,读写的性能会下降,即使有索引,索引也会变得很大,性能同样会降下。
  • 数据库文件会得很大,数据库备份和恢复需要耗时很长。
  • 数据库文件越大,极端情况下丢失数据的风险越高。
      因此,当流量越来越大时,且单机容量达到上限时,此时需要考虑对其进行切分,切分的目的就在于减少单机数据库的负担,将由多台数据库服务器一起来分担,缩短查询时间。

切分策略

  数据切分分为两种方式,纵向切分和水平切分

  1. 纵向切分
      常见有纵向分库纵向分表两种。
    1). 纵向分库就是根据业务耦合性,将关联度低的不同表存储在不同的数据库,做法与大系统拆分为多个小系统类似,按业务分类进行独立划分。与“微服务治理”的做法相似,每个微服务使用单独的一个数据库。
    2). 垂直分表是基于数据库中的列进行,某个表字段较多,可以新建一张扩展表,将不经常用或者字段长度较大的字段拆出到扩展表中。在字段很多的情况下,通过大表拆小表,更便于开发与维护,也能避免跨页问题,MYSQL底层是通过数据页存储的,一条记录占用空间过大会导致跨页,造成额外的开销。另外,数据库以行为单位将数据加载到内存中,这样表中字段长度越短且访问频次较高,内存能加载更多的数据,命中率更高,减少磁盘IO,从而提升数据库的性能。
  • 垂直切分的优点:
    • 解决业务系统层面的耦合,业务清晰
    • 与微服务的治理类似,也能对不同业务的数据进行分级管理,维护,监控,扩展等。
    • 高并发场景下,垂直切分一定程度的提升IO,数据库连接数,单机硬件资源的瓶颈。
  • 垂直切分的缺点
    • 部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度。
    • 分布式事处理复杂
    • 依然存在单表数据量过大的问题。
  1. 水平切分
      当一个应用难以再细粒度的垂直切分或切分后数据量行数依然巨大,存在单库读写,存储性能瓶颈,这时候需要进行水平切分。
      水平切分为库内分表和分库分表,是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。
      库内分表只解决单一表数据量过大的问题,但没有将表分布到不同机器的库上,因些对于减轻mysql的压力来说帮助不是很大,大家还是竞争同一个物理机的CPU、内存、网络IO,最好通过分库分表来解决。
  • 水平切分优点
    • 不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力。
    • 应用端改造较小,不需要拆分业务模块。
  • 水平切分缺点
    • 跨分片的事务一致性难以保证
    • 跨库的join关联查询性能较差
    • 数据多次扩展维度和维护量极大。
      #路由规则
        水平切分后同一张表会出现在多个数据库或表中,每个库和表的内容不同,对于水平分表后分库后,如何知道哪条数据在哪个库里或表里,则需要路由算法进行计算,这个算法会引入一定的复杂性。
  • 范围路由

  选取有序的数据列,如时间戳作为路由的条件,不同分段分散到不同的数据库表中,以最常见的用户ID为例,路由算法可以按照1000000的范围大小进行分段,1 ~ 9999999放到数据库1的表中,10000000~199999999放到数据库2的表中,以此累推。
  范围路由设计的复杂点主要体现在分段大小的选取上,分段太小会导致切分后子表数量过多增加维护复杂度,分段太大可能会导致单表依然存在性能问题,按一般大老们的经验,分段大小100W至2000W之间,具体需要根据业务选 取合适的分段大小。

  • 范围路由的优点
    • 可以随着数据的增加平滑地扩充新的表或库,原有的数据不需要动。
    • 单表大小可控
    • 使用分片字段进行范围查找时,连续分片可快速定位查询,有效避免分片查询的问题。
  • 热点数据成为性能瓶颈,连续分片可能存在数据热点,例如按时单字段分片,有些分片存储最近时间内的数据,可能会被频繁读写,而有些历史数据则很少被查询。
  • hash算法

  选取某个列或几个列的值进行hash运算,然后根据hash的结果分散到不同的数据库表中,以用ID为例,假如我们一开始就规划10个数据库表,路由算法可以简单地用id % 10的值来表示数据所属的数据库编号,ID为985的用户放到编号为5的子表中。ID为10086编号放到编号为6的表中。
  Hash路由设计的复杂点主要体现 在初始表数量的选取上,表数量太多维护比较麻烦,表数量太小又可能导致单表性能存在问题。而用Hash路由后,增加字表数量是非常麻烦的,所有数据都要重新分布。
  Hash路由的优缺点与范围路由相反,Hash路由的优点是表分布比较均匀,缺点是扩容时很麻烦,所有数据均需要重新分布。

  • 路由配置

  配置路由就是路由表,用一张独立的表来记录路由信息。同样以用户ID为例,我们新增一张ROUTER表,这个表包含table_Id两列,根据user_id就可以查询对应的修改路由表就可以了。
配置路由设计简单,使用起来非常灵活,尤其是在扩充表的时候,只需要迁移指定的数据,然后修改路由表就可以了。
其缺点就是必须多查询一次,会影响整体性能,而且路由表本身如果太大,性能会成为瓶颈点,如果我们再将路由表分库分表,则又面临一个死循环。

分库分表带来的问题

  • join操作

水平分表后,虽然物理上分散在多个表中,如果需要与其它表进行join查询,需要在业务代码或者数据库中间件中进行多次join查询,然后将结果合并。

  • COUNT(*)操作

水平分表后,某些场景下需要将这些表当作一个表来处理,那么count(*)显得没有那么容易 了。

  • order by 操作

分表后,数据分散到多个表中,排序操作无法在数据库中完成,只能由业务代码或数据中间件分别查询每个子表中的数据,然后汇总进行排序。

  • 事务问题

解决事务问题通常有两种方法:一是使用分部式事务,另一种由应用程序和数据库一起控制,这两个方法各有优势。
1、使用分布式事务
优点:由数据库本身来管理,较为简单
缺点:当shard越来越多时,性能代价高特别高
2、应用程序和数据库共同控制
将多个分布式事务拆到小事务上,并由各个应用程序来控制,这样带来的好处,性能较高,而缺点是需要应用程序在事务控制上做灵活设计

猜你喜欢

转载自blog.csdn.net/vipshop_fin_dev/article/details/106730588