数据库分库分表存在的问题及解决方案

读写分离分散了数据库读写操作的压力,但是没有分散存储压力,当数据库的数据量达到千万甚至上亿条的时候,单台数据库服务器的存储能力就会达到瓶颈,主要体现在以下几个方面:

  1. 数据量太大,读写性能会下降,即使有索引,索引也会变得很大,性能同样会下降
  2. 数据文件会变得很大,数据库备份和恢复需要消耗更长的时间
  3. 数据文件越大,极端情况下丢失数据的风险就会越高

基于上述原因,单个数据库服务器存储的数据量不能太大,需要控制在一定的范围内,为了满足业务数据存储的需求,需要将存储分散到多台数据库服务器上

常见的分散存储的方法有分库和分布两大类

  • 业务分库  业务分库之的是按照业务模块将数据分散到不同的数据库服务器,虽然业务分库能够分散存储和访问的压力,但是同时也带来了新的问题,主要存在的问题如下:
  1. join操作问题     业务分库后,原本在同一个数据库中的表分散到不同数据库中,导致无法使用SQL中的join查询
  2. 事务问题           原本在同一个数据库中不同的表可以在同一个事物中修改,业务分库后,表分散到不同的数据库中,无法通过事务统一修改,虽然数据库厂商针对此问题提供了一些分布式事务解决方案(例如,MySQL的XA),但是性能实在太低,与高性功能存储的目标是相违背的
  3. 成本问题          业务分库同时也带来了成本的代价,本来1台服务器搞定的事情,现在需要3台,如果考虑备份,那就是2台变成了6台

基于上述原因,对于初创业务,并不建议一开始就这样拆分,主要有几个原因:

  1. 初创业务存在很大的不确定性,业务不一定能发展起来,业务开始的时候并没有真正的存储和访问压力,业务分库并不能为业务带来价值
  2. 业务分库后,表之间的join查询,数据库事务无法简单实现了发
  3. 业务分库后,因为不同的数据要读写不同的数据库,代码需要增加根据数据类型映射到不同数据库的逻辑,增加了工作量,而业务初创期最重要的是快速实现,快速验证,业务分库会拖慢业务节奏
  • 分表  将不同的业务数据分散存储到不同的数据库服务器,能够支撑百万甚至千万用户规模的业务,但是如果业务继续发展,同一个业务的单表数据也会达到单台数据库服务器的处理瓶颈,此时就需要对单表进行拆分,单表数据拆分有两种方式:垂直分表和水平分表

分表能够有效的分散存储压力和带来性能提升,但是和分库一样,也会引入各种复杂性,主要存在的问题如下:

  1. 垂直分表  垂直分表适合将表中某些不常用而且占了大量空间的列拆分出去,垂直分表的引入的复杂性主要体现在表操作的数量会增加,例如原来只要一次查询的就可以获取,现在要查询两次或者多次才能获得想要的数据
  2. 水平分表  水平分表适合表行数特别大的表,如果单表行数超过5000万就必须进行分表,这个数字可以作为参考,但是并不是绝对的标准,关键还是要看表的访问性能

水平分表相比垂直分表,会引入更多的复杂性,主要表现在以下几个方面:

  • 路由   水平分表后,某条数据具体属于哪个切分后的表,需要增加路由算法进行计算,这个算法会引入一定的复杂性,常见的路由算法有如下几种:
  1. 范围路由   选择有序的数据列作为路由条件,不同分段分散到不同的数据库表中,以常见的用户ID为例,路由算法可以按照10000的范围大小进行分段 1-9999放到数据库1中的表,10000-19999的数据放到数据库2中的表,依次类推,范围路由算法的复杂性主要体现在分段大小的选取上,分段太小会导致切分后的子表数据量过多,增加维护复杂度;分段太大可能会导致单表依然存在性能问题,一般建议分段大学在100万到200万之间,具体要根据业务选择合适的大小分段,路由算法的优点就是可以随着数据的增加可以平滑的扩充新的表,原有的数据不需要懂,范围路由的一个比较隐含的缺点就是分布不均匀
  2. Hahs路由算法  选择某个列(或者某几个列组合也可以)的进行Hash运算,然后根据Hash结果分散到不同的数据库表中,同样根据用户ID为例,假如一开始就规划10个数据库表,路由算法可以简单的用user_id%10的值来表示数据所属的数据库表编号,ID为985的用户放到编号为5的子表中,ID为10086的用户放到编号为6的子表中;Hash 路由算法设计的复杂点主要体现在初始表数量的选取上,表数量太多维护比较麻烦,表数据量太少又可能导致单表性能问题,而用了Hash路由后,增加表的数量非常麻烦,所有数据都要重新分布,Hash路由算法的优缺点和范围路由基本相反,Hash路由算法的优点是表分布比较均匀,缺点是扩充新的表很麻烦,所有数据需要重新分布
  3. 配置路由  配置路由就是路由表,用一张独立的表来记录路由信息,同样根据用户ID为例,我们新增一张user_router表,这个表包含user_id和table_id两列,根据user_id就可以查询对应的table_id,配置路由设计简单,使用起来非常灵活,尤其是在扩充表的时候,只需要迁移指定书,然后修改路由表就可以。配置路由的缺点就是必须多查询一次,会影响整体的性能;而且路由表本身如果太大,性能同样可能成为瓶颈,如果我们再次将路由表分库分表,则面临一个死循环式的路由算法选择问题

分表操作和分库操作一样,同样会存在一些问题,主要体现在如下几个方面:

  1. join操作           水平分表后,数据分散到多个表中,如果需要与其他表进行join 查询,需要在业务代码或者数据库中间件中进行多次join查询,然后将结果合并
  2. count()操作     水平分表后,虽然物理上数据分散到多个表中,但是某些业务逻辑上还是会将这些表当作一个表进行处理,例如,获取记录总数用于分页或展示,水平分表之前用一个count()就能完成的操作,在分表之后就没有那么简单了,常见的处理方式有如下两种:
  • count()相加   具体做法就是在业务代码或者数据库中间件中对每个表进行count()操作,然后将结果相加,这种方式实现简单,缺点就是性能比较低
  • 记录数表       具体做法就是新建一张表,例如表名为:记录数表,包含table_name,row_count两个字段,每次插入或删除子表数据成功后,都更新记录数表,这种方式获取表记录数的性能要大大优于count()相加方式,因为只需要一次简单的查询就可以获得数据,缺点是复杂度增加不少,对子表的操作要同步操作记录数表,如果一个业务逻辑遗漏了,数据就会不一致;而且针对记录数表的操作和针对子表的操作无法放在同一个事物中进行处理,异常的情况会出现操作子表成功了而操作记录数表示不,同样导致数据不一致,同时,记录数表的方式也增加了数据库的写压力,因为每次针对子表的insert 和 delete操作需要update记录数表,所以对于一些不要去记录数实时保持精确的业务,也可以通过后台定时更新记录数表,定时更新实际上就是count()相加和记录数表的结合,定时通过count()相加计算表的记录数,然后更新记录数表中的数据

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

原文地址:https://www.cnblogs.com/anqli-java/p/9942107.html

时间: 2024-07-28 14:12:28

数据库分库分表存在的问题及解决方案的相关文章

高并发、高负载解决方案之----------数据库分库分表的应用场景及解决方案

数据库分库分表的应用场景及解决方案  现实业务场景中,为了保障客户体验并满足业务的线性增长.会对数据量巨大,且业务会始终进行的产品进行分表分库策略.但是如何合理的根据业务采取争取的分表分库策略至关重要.下面以具体实例来进行分析. • 场景一:用户中心,单key业务如何进行数据库切分 • 场景二:订单中心,多key业务如何进行数据库切分 场景一:用户中心数据库切分架构实践|场景介绍 用户中心是一个十分常见的业务系统,涵盖用户登录.注册.信息查询与修改等服务. 用户的核心元数据为: User(uid

数据库分库分表

1. 数据库分库分表 1.1. 前言 1.1.1. 名词解释 1.2. 数据库架构演变 1.3. 分库分表前的问题 1.3.1. 用户请求量太大 1.3.2. 单库太大 1.3.3. 单表太大 1.4. 分库分表的方式方法 1.4.1. 垂直拆分 1.4.2. 水平拆分 1.5. 分库分表后面临的问题 1.5.1. 事务支持 1.5.2. 多库结果集合并(group by,order by) 1.5.3. 跨库join 1.6. 分库分表方案产品 1.7. 为什么不建议分库分表 1.8. 参考

关系型数据库分库分表解决方案

关系型数据库分库分表解决方案 关系型数据库单库或单表在数据达到一定量级后,单个节点的就会出现性能瓶颈.通常的做法就是考虑分库分表. 为什么要分? 分库降低了单点机器的负载:分表,提高了数据操作的效率,尤其是Write操作的效率. 如何分? 按号段分: (1) user_id为区分,1-1000的对应DB1,1001-2000的对应DB2,以此类推:优点:可部分迁移缺点:数据分布不均 (2)hash取模分: 对user_id进行hash(或者如果user_id是数值型的话直接使用user_id 的

数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示

本文原文连接: http://blog.csdn.net/bluishglc/article/details/7696085 ,转载请注明出处!本文着重介绍sharding切分策略,如果你对数据库sharding缺少基本的了解,请参考我另一篇从基础理论全面介绍sharding的文章:数据库Sharding的基本思想和切分策略 第一部分:实施策略 图1.数据库分库分表(sharding)实施策略图解(点击查看大图) 1.准备阶段 对数据库进行分库分表(Sharding化)前,需要开发人员充分了解系

16、MySQL数据库分库分表备份脚本

MySQL数据库分库分表备份脚本 ===================学员分享分库分表========================== 脚本单双引号的区别: 单引号是强引用,强制输出是所见即所得. 双引号是解析变量 和 多个字符串.数字等连接一个字符串 条件1  ||    条件2                      或   假真   真假 条件1 && 条件2                      并   真真    假假 !条件1  && 条件2    

数据库分库分表(sharding)

第一部分:实施策略 图1.数据库分库分表(sharding)实施策略图解(点击查看大图) 1.准备阶段 对数据库进行分库分表(Sharding化)前,需要开发人员充分了解系统业务逻辑和数据库schema.一个好的建议是绘制一张数据库ER图或领域模型图,以这类图为基础划分shard,直观易行,可以确保开发人员始终保持清醒思路.对于是选择数据库ER图还是领域模型图要根据项目自身情况进行选择.如果项目使用数据驱动的开发方式,团队以数据库ER图作为业务交流的基础,则自然会选择数据库ER图,如果项目使用的

转数据库分库分表(sharding)系列(二) 全局主键生成策略

本文将主要介绍一些常见的全局主键生成策略,然后重点介绍flickr使用的一种非常优秀的全局主键生成方案.关于分库分表(sharding)的拆分策略和实施细则,请参考该系列的前一篇文章:数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示 本文原文连接: http://blog.csdn.net/bluishglc/article/details/7710738 ,转载请注明出处! 第一部分:一些常见的主键生成策略 一旦数据库被切分到多个物理结点上,我们将不能再依赖数据库自身的主键

数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量

当团队对系统业务和数据库进行了细致的梳理,确定了切分方案后,接下来的问题就是如何去实现切分方案了,目前在sharding方面有不少的开源框架和产 品可供参考,同时很多团队也会选择自主开发实现,而不管是选择框架还是自主开发,都会面临一个在哪一层上实现sharding逻辑的问题,本文会对这一系 列的问题逐一进行分析和考量.本文原文连接: http://blog.csdn.net/bluishglc/article/details/7766508转载请注明出处! 一.sharding逻辑的实现层面 从

数据库分库分表(sharding)系列

数据库分库分表(sharding)系列     目录; (一) 拆分实施策略和示例演示 (二) 全局主键生成策略 (三) 关于使用框架还是自主开发以及sharding实现层面的考量 (四) 多数据源的事务处理 (五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案 (一) 拆分实施策略和示例演示 第一部分:实施策略 图1.数据库分库分表(sharding)实施策略图解 1.准备阶段 对数据库进行分库分表(Sharding化)前,需要开发人员充分了解系统业务逻辑和数据库sch