数据库分库分表概述

    随着业务的发展,数据库的数据量也越来越大,数据慢慢达到GB,TB级别,获取数据的效率越来越慢,简单的数据库分区以及单个数据服务器已经不能满足数据的增长,这个时候我们就需要用到数据库集群了,有了数据库的集群肯定会涉及到数据库的分库分表操作数据库的分库分表操作又统称为数据库分片,其分为垂直拆分和水平拆分,我们先在下面介绍下分库分表的概念:

    分库:

    其又称为垂直拆分,或纵向拆分,主要是按照业务来对原来的表拆分到不同的数据库里面。如果对于一个业务系统来说,其具有明确的业务逻辑且结构清晰、模块耦合性低,那么这种业务系统数据库就非常适合进行分库操作。

    分库的优点就是拆分后业务清晰,拆分规则明确;系统之间的整合或扩展都相对容易;数据也更容易维护。其缺点也很明显,即部分业务表无法join,只能通过接口的方式进行调用解决,提高了系统的复杂度;对于不同的业务其对应的单个数据库会存在数据瓶颈的问题,对数据的扩展和性能的提升有明显的影响;最后是对数据库事务的处理也更加复杂。

    分表:

    其又称为水平拆分,它主要是由于数据存放到一张表中无法快速实现增删改查操作,而且在一个表中可能已经无法存放下,于是将表中数据按照某一个或某几个字段来根据某些规则将表中的数据拆分成多份,每一份数据只包含其中一部分数据,并且将拆分的数据分别保存到多个表结构一样的表中,拆分出来的表结构可以存放到一到多个数据库中,这就是分表的基本理论。

    分表又分为垂直分表和水平分表,垂直分表它是指将本来可以存放在同一个表的数据按照规则把可以独立出来的字段整理到另外一张或多张表中,其原理就是按照数据库第三范式进行关系关联;水平分表是指按照某种规则将数据存放到与原表有相同表结构的表中,这样可以保证一张表不会因为数据过大而影响性能,这些相同结构的表可以存放在一到多个数据库中。

    分表的优点是只要拆分规则抽象的好,那么join操作基本可以在数据库中,无需调用外部接口;不会存在单库数据量过大,从而形成高并发的瓶颈;在应用端改造也会较少;最终提高了系统的稳定性和负载能力。其缺点也还是挺明显的,主要是拆分规则难以抽象,而分表后的分片事务一致性难以保证,分表后的数据维护以及扩展都比较困难,如果出现了跨库join也是很麻烦的,且会对性能造成影响。

    在通常情况下分表都可以通过下面的规则来进行:

    1.根据范围进行拆分,常用的范围拆分有按照时间、数值进行拆分。
    2.根据列表进行拆分,也就是按照某一类相同的数据进行拆分,比如按照地域、组织及分类进行的拆分。
    3.根据散列进行拆分,所谓的散列就是大家熟悉的根据hash(某个字段)%分片数、一致性hash算法等进行的拆分。
    4.根据上面几种拆分进行综合的复合拆分。

    通过上面对分库分表的介绍我们大致了解到了无论是分库还是分表都有存在以下几个问题:

    1.分布式事务问题。
    2.跨节点join问题。
    3.跨节点合并后的排序问题。
    4.多数据源管理问题。

    因此为了能够解决以上问题,我们需要自己设计或者寻找一个有如下功能的软件来进行统一处理:

    1.要能解析SQL
    2.能支持读写分离
    3.能支持从库读的负载均衡
    4.支持分库操作
    5.支持分表操作
    6.支持跨库关联查询
    7.对事务处理的支持
    8.主键ID生成
    9.数据源管理

    从目前的实现方案来看,数据库中间件主要有客户端实现和服务器代理实现,其代表分别有shardingjdbc和mycat(cobar发展而来)。

    客户端模式,是指在应用程序中集成数据库中间件模块,通过该模块来配置管理应用需要的一个或多个数据源,以及访问各个数据源,在模块内完成数据的整合。

    服务端(代理)模式,通过中间代理层来统一管理所有的数据源,后端数据库集群对前端应用程序透明,同时易于数据库扩展。独立的服务能提供更强的处理能力。适用于大型复杂系统。

    我们看下常用的数据库中间件对比:

数据库分库分表概述_第1张图片

    从上图可以看出shardingjdbc和mycat是比较常用的数据库中间件,无论是在活跃度还是数据库支持的种类上面。对于mycat的具体事务可以查看官网介绍http://www.mycat.org.cn/ 。现在我们来整体的总结下分库分表的优缺点及规则,我们首先看下分片的优点: 

    1. 解决磁盘系统最大文件限制,比如常见的有:
        FAT16(最大分区2GB,最大文件2GB)
        FAT32(最大分区32GB,最大容量2TB,最大文件32G)
        NTFS(最大分区2TB,最大容量,最大文件2TB)
        EXT3(最大文件大小: 2TB,最大文件极限: 仅受文件系统大小限制,最大分区/文件系统大小: 4TB,最大文件名长度: 255 字符)
    2.减少增量数据写入时的锁对查询的影响,减少长时间查询造成的表锁,影响写入操作等锁竞争的情况,节省排队的时间开支,增加呑吐量。
    3.由于单表数量下降,常见的查询操作由于减少了需要扫描的记录,使得单表单次查询所需的检索行数变少,减少了磁盘IO,时延变短。

    分库规则的基本思路就是分析业务功能,以及表间的聚合关系,把关系紧密的表放在一起。而分库的粒度对后续的影响也是非常大的,所谓的分库的粒度指的是在做切分时允许几级的关联表放在一起,关联打 断的越多,则受影响的join操作越多。实际的粒度掌控需要结合“业务紧密程度”和“表的数据量”两个因素综合考虑,若划归到一起的表关系紧密,且数据量并不大,增速也非常缓慢,则适宜放在一起,不需要再进行水平切分;若划归到一起的表的数据量巨大且增速迅猛,则势必要在分库的基础上再进行分表,这就意味着原单一的库还可能会被拆分成多个库,这会导致更多的复杂性,一开始最好就要考虑进去。对于垂直分表,通常是按照业务功能的使用频次,把主要的、热门的字段放在一起做为主要表;然后把不常用的,按照各自的业务属性进行聚集,拆分到不同的次要表中;主要表和次要表的关系一般都是一对一的。对于水平分表,通常是按照具体的业务规则和数据的格式,选择能够把数据进行合理拆分的业务数据做为拆分标准,以此来对数据进行拆分,在上面也已经提及到。因此分片规则总体来说可以有以下原则:

    第一原则:能不切分尽量不要切分,1000 万以内的表,不建议分片,通过合适的索引,读写分离等方式,可以很好的解决性能问题。

    第二原则:如果要切分一定要选择合适的切分规则,提前规划好。分片规则的选择,需要考虑数据的增长模式,数据的访问模式,分片关联性问题,以及分片扩容问题,最常用的分片策略为范围分片,枚举分片,一致性 Hash 分片,这几种分片都有利于扩容。

    第三原则:数据切分尽量通过数据冗余或表分组(Table Group)来降低跨库Join 的可能。分片数量尽量少,分片尽量均匀分布在多个DataHost上,因为一个查询SQL跨分片越多,则总体性能越差,虽然要好于所有数据在一个分片的结果,只在必要的时候进行扩容,增加分片数量。

    第四原则:由于数据库中间件对数据Join实现的优劣难以把握,而且实现高性能难度极大,业务读取尽量少使用多表Join。尽量不要在一个事务中的 SQL 跨越多个分片,分布式事务一直是个不好处理的问题。

    第五原则:查询条件尽量优化,尽量避免 Select * 的方式,大量数据结果集下,会消耗大量带宽和 CPU 资源,查询尽量避免返回大量结果集,并且尽量为频繁使用的查询语句建立索引。

    数据拆分原则:

    1.达到一定数量级才拆分(800 万)。

    2.不到 800 万但跟大表(超 800 万的表)有关联查询的表也要拆分,在此称为大表关联表。

    大表关联表如何拆:小于 100 万的使用全局表;大于 100 万小于 800 万跟大表使用同样的拆分策略;无法跟大表使用相同规则的,可以考虑从 java 代码上分步骤查询,不用关联查询,或者破例使用全局表。

    3.破例的全局表:如 item_sku 表 250 万,跟大表关联了,又无法跟大表使用相同拆分策略,也做成了全局表。破例的全局表必须满足的条件:没有太激烈的并发 update,如多线程同时 update 同一条 id=1 的记录。虽有多线程 update,但不是操作同一行记录的        不在此列。多线程 update 全局表的同一行记录会死锁。批量 insert没问题。

   4.拆分字段是不可修改的。

    5.拆分字段只能是一个字段,如果想按照两个字段拆分,必须新建一个冗余字段,冗余字段的值使用两个字段的值拼接而成(如大区+年月拼成 zone_yyyymm 字段)。

    6.拆分算法的选择和合理性评判:按照选定的算法拆分后每个库中单表不得超过 800 万。

    7.能不拆的就尽量不拆。如果某个表不跟其他表关联查询,数据量又少,直接不拆分,使用单库即可。

    再说下上面提及到的mycat使用时的性能建议:

    1.尽量避免使用 Left join 或 Right join,而用 Inner join。

    2.在使用 Left join 或 Right join 时,ON 会优先执行,where 条件在最后执行,所以在使用过程中,条件尽可能的在 ON 语句中判断,减少 where 的执行。

    3.少用子查询,而用 join。

    Mycat 目前版本支持跨分片的 join,主要实现的方式有四种,全局表,ER 分片,catletT(人工智能)和 ShareJoin,ShareJoin 在开发版中支持,前面三种方式 1.3.0.1 支持。

 

你可能感兴趣的:(数据库,分库分表,mycat)