数据切分 垂直切分、垂直拆分与水平拆分的优缺点

数据切分 垂直切分

关于数据库的水平切分和垂直切分的一些概念
 垂直拆分
  垂直拆分就是要把表按模块划分到不同数据库表中(当然原则还是不破坏第三范式),这种拆分在大型网站的演变过程中是很常见的。当一个网站还在很小的时候,只有小量的人来开发和维护,各模块和表都在一起,当网站不断丰富和壮大的时候,也会变成多个子系统来支撑,这时就有按模块和功能把表划分出来的需求。其实,相对于垂直切分更进一步的是服务化改造,说得简单就是要把原来强耦合的系统拆分成多个弱耦合的服务,通过服务间的调用来满足业务需求看,因此表拆出来后要通过服务的形式暴露出去,而不是直接调用不同模块的表,淘宝在架构不断演变过程,最重要的一环就是服务化改造,把用户、交易、店铺、宝贝这些核心的概念抽取成独立的服务,也非常有利于进行局部的优化和治理,保障核心模块的稳定性
  垂直拆分:单表大数据量依然存在性能瓶颈
  水平拆分
  上面谈到垂直切分只是把表按模块划分到不同数据库,但没有解决单表大数据量的问题,而水平切分就是要把一个表按照某种规则把数据划分到不同表或数据库里。例如像计费系统,通过按时间来划分表就比较合适,因为系统都是处理某一时间段的数据。而像SaaS应用,通过按用户维度来划分数据比较合适,因为用户与用户之间的隔离的,一般不存在处理多个用户数据的情况,简单的按user_id范围来水平切分
  通俗理解:水平拆分行,行数据拆分到不同表中, 垂直拆分列,表数据拆分到不同表中
  垂直与水平联合切分
  由上面可知垂直切分能更清晰化模块划分,区分治理,水平切分能解决大数据量性能瓶颈问题,因此常常就会把两者结合使用,这在大型网站里是种常见的策略
  案例:
  以mysql为例,简单购物系统暂设涉及如下表:
  1.产品表(数据量10w,稳定)
  2.订单表(数据量200w,且有增长趋势)
  3.用户表 (数据量100w,且有增长趋势)
  以mysql为例讲述下水平拆分和垂直拆分,mysql能容忍的数量级在百万静态数据可以到千万
  垂直拆分:
  解决问题:
  表与表之间的io竞争
  不解决问题:
  单表中数据量增长出现的压力
  方案:
  把产品表和用户表放到一个server上
  订单表单独放到一个server上
  水平拆分:
  解决问题:
  单表中数据量增长出现的压力
  不解决问题:
  表与表之间的io争夺
  方案:
  用户表通过性别拆分为男用户表和女用户表
  订单表通过已完成和完成中拆分为已完成订单和未完成订单
  产品表 未完成订单放一个server上
  已完成订单表盒男用户表放一个server上
  女用户表放一个server上(女的爱购物)
--------------------------------------------------------------------------------
深入理解关系型数据库的数据水平切分和垂直切分
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt330

虽然在云计算时代,传统数据库存在着先天性的弊端,但是NoSQL数据库又无法将其替代,NoSQL只能作为传统数据的补充而不能将其替代,所以规避传统数据库的缺点是目前大数据时代必须要解决的问题。如果传统数据易于扩展,可切分,就可以避免单机(单库)的性能缺陷,但是由于目前开源或者商用的传统数据库基本不支持大规模自动扩展,所以就需要借助第三方来做处理,下面就来分析一下如何进行数据切分。

何为数据切分?

简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。

数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式。一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直(纵向)切分;另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。

垂直切分的最大特点就是规则简单,实施也更为方便,尤其适合各业务之间的耦合度非常低,相互影响很小,业务逻辑非常清晰的系统。在这种系统中,可以很容易做到将不同业务模块所使用的表分拆到不同的数据库中。根据不同的表来进行拆分,对应用程序的影响也更小,拆分规则也会比较简单清晰。

水平切分于垂直切分相比,相对来说稍微复杂一些。因为要将同一个表中的不同数据拆分到不同的数据库中,对于应用程序来说,拆分规则本身就较根据表名来拆分更为复杂,后期的数据维护也会更为复杂一些。

垂直切分

一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面,如下图:

blob.png

系统被切分成了,用户,订单交易,支付几个模块。

一个架构设计较好的应用系统,其总体功能肯定是由很多个功能模块所组成的,而每一个功能模块所需要的数据对应到数据库中就是一个或者多个表。而在架构设计中,各个功能模块相互之间的交互点越统一越少,系统的耦合度就越低,系统各个模块的维护性以及扩展性也就越好。这样的系统,实现数据的垂直切分也就越容易。

但是往往系统之有些表难以做到完全的独立,存在这扩库join的情况,对于这类的表,就需要去做平衡,是数据库让步业务,共用一个数据源,还是分成多个库,业务之间通过接口来做调用。在系统初期,数据量比较少,或者资源有限的情况下,会选择共用数据源,但是当数据发展到了一定的规模,负载很大的情况,就需要必须去做分割。

一般来讲业务存在着复杂join的场景是难以切分的,往往业务独立的易于切分。如何切分,切分到何种程度是考验技术架构的一个难题。

下面来分析下垂直切分的优缺点:

优点:

拆分后业务清晰,拆分规则明确。

系统之间整合或扩展容易。

数据维护简单。

缺点:

部分业务表无法join,只能通过接口方式解决,提高了系统复杂度。

受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高。

事务处理复杂。

由于垂直切分是按照业务的分类将表分散到不同的库,所以有些业务表会过于庞大,存在单库读写与存储瓶颈,所以就需要水平拆分来做解决。

水平切分

相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,如图:

blob.png

拆分数据就需要定义分片规则。关系型数据库是行列的二维模型,拆分的第一原则是找到拆分维度。比如:从会员的角度来分析,商户订单交易类系统中查询会员某天某月某个订单,那么就需要按照会员结合日期来拆分,不同的数据按照会员ID做分组,这样所有的数据查询join都会在单库内解决;如果从商户的角度来讲,要查询某个商家某天所有的订单数,就需要按照商户ID做拆分;但是如果系统既想按会员拆分,又想按商家数据,则会有一定的困难。如何找到合适的分片规则需要综合考虑衡量。

几种典型的分片规则包括:

按照用户ID求模,将数据分散到不同的数据库,具有相同数据用户的数据都被分散到一个库中。

按照日期,将不同月甚至日的数据分散到不同的库中。

按照某个特定的字段求摸,或者根据特定范围段分散到不同的库中。

如图,切分原则都是根据业务找到适合的切分规则分散到不同的库,下面用用户ID求模举例:

blob.png

既然数据做了拆分有优点也就优缺点。

优点有:

拆分规则抽象好,join操作基本可以数据库做。

不存在单库大数据,高并发的性能瓶颈。

应用端改造较少。

提高了系统的稳定性跟负载能力。

缺点有:

拆分规则难以抽象。

分片事务一致性难以解决。

数据多次扩展难度跟维护量极大。

跨库join性能较差。

前面讲了垂直切分跟水平切分的不同跟优缺点,会发现每种切分方式都有缺点,但共同的特点缺点有:

引入分布式事务的问题。

跨节点Join的问题。

跨节点合并排序分页问题。

多数据源管理问题。

针对数据源管理,目前主要有两种思路:

A. 客户端模式,在每个应用程序模块中配置管理自己需要的一个(或者多个)数据源,直接访问各个数据库,在模块内完成数据的整合;

B. 通过中间代理层来统一管理所有的数据源,后端数据库集群对前端应用程序透明;

可能90%以上的人在面对上面这两种解决思路的时候都会倾向于选择第二种,尤其是系统不断变得庞大复杂的时候。确实,这是一个非常正确的选择,虽然短期内需要付出的成本可能会相对更大一些,但是对整个系统的扩展性来说,是非常有帮助的。

 

由于数据切分后数据Join的难度在此也分享一下数据切分的经验:

第一原则:能不切分尽量不要切分。

第二原则:如果要切分一定要选择合适的切分规则,提前规划好。

第三原则:数据切分尽量通过数据冗余或表分组(Table Group)来降低跨库Join的可能。

第四原则:由于数据库中间件对数据Join实现的优劣难以把握,而且实现高性能难度极大,业务读取尽量少使用多表Join。
-----------------------------------------------------------------------------
数据库垂直拆分 水平拆分
        当我们使用读写分离、缓存后,数据库的压力还是很大的时候,这就需要使用到数据库拆分了。
        
        数据库拆分简单来说,就是指通过某种特定的条件,按照某个维度,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面以达到分散单库(主机)负载的效果。 
 
        切分模式: 垂直(纵向)拆分、水平拆分。
 
垂直拆分
 
        专库专用
 
        一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面,如下图:
        
优点:
        1. 拆分后业务清晰,拆分规则明确。
        2. 系统之间整合或扩展容易。
        3. 数据维护简单。
 
缺点:
        1. 部分业务表无法join,只能通过接口方式解决,提高了系统复杂度。
        2. 受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高。
        3. 事务处理复杂。
 
水平拆分
 
        垂直拆分后遇到单机瓶颈,可以使用水平拆分。相对于垂直拆分的区别是:垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆到不同的数据库中。
 
        相对于垂直拆分,水平拆分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中 的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,主要有分表,分库两种模式,如图:
                
 
        
优点:
        1. 不存在单库大数据,高并发的性能瓶颈。
        2. 对应用透明,应用端改造较少。     
        3. 按照合理拆分规则拆分,join操作基本避免跨库。
        4. 提高了系统的稳定性跟负载能力。
 
缺点:
        1. 拆分规则难以抽象。
        2. 分片事务一致性难以解决。
        3. 数据多次扩展难度跟维护量极大。
        4. 跨库join性能较差。
 
拆分的处理难点
 
两张方式共同缺点
 
        1. 引入分布式事务的问题。
        2. 跨节点Join 的问题。
        3. 跨节点合并排序分页问题。
 
针对数据源管理,目前主要有两种思路:
 
        A. 客户端模式,在每个应用程序模块中配置管理自己需要的一个(或者多个)数据源,直接访问各个 数据库,在模块内完成数据的整合。 
        优点:相对简单,无性能损耗。   
        缺点:不够通用,数据库连接的处理复杂,对业务不够透明,处理复杂。
 
       B. 通过中间代理层来统一管理所有的数据源,后端数据库集群对前端应用程序透明;   
        优点:通用,对应用透明,改造少。   
        缺点:实现难度大,有二次转发性能损失。
 
拆分原则
    
        1. 尽量不拆分,架构是进化而来,不是一蹴而就。(SOA)
        2. 最大可能的找到最合适的切分维度。
        3. 由于数据库中间件对数据Join 实现的优劣难以把握,而且实现高性能难度极大,业务读取  尽量少使用多表Join -尽量通过数据冗余,分组避免数据垮库多表join。
        4. 尽量避免分布式事务。
        5. 单表拆分到数据1000万以内。
 
切分方案
    
        范围、枚举、时间、取模、哈希、指定等
 
案例分析
 
场景一
建立一个历史his系统,将公司的一些历史个人游戏数据保存到这个his系统中,主要是写入,还有部分查询,读写比约为1:4;由于是所有数据的历史存取,所以并发要求比较高; 
 
分析:
历史数据
写多都少
越近日期查询越频繁?
什么业务数据?用户游戏数据
有没有大规模分析查询?
数据量多大?
保留多久?
机器资源有多少?
 
方案1:按照日期每月一个分片
带来的问题:1.数据热点问题(压力不均匀)
 
方案2:按照用户取模,  --by Jerome 就这个比较合适了
带来的问题:后续扩容困难
 
方案3:按用户ID范围分片(1-1000万=分片1,xxx)
带来的问题:用户活跃度无法掌握,可能存在热点问题
 
场景二
建立一个商城订单系统,保存用户订单信息。
 
分析:
电商系统
一号店或京东类?淘宝或天猫?
实时性要求高
存在瞬时压力
基本不存在大规模分析
数据规模?
机器资源有多少?
维度?商品?用户?商户?
 
方案1:按照用户取模,
带来的问题:后续扩容困难
 
方案2:按用户ID范围分片(1-1000万=分片1,xxx)
带来的问题:用户活跃度无法掌握,可能存在热点问题
 
方案3:按省份地区或者商户取模
数据分配不一定均匀
 
场景3
上海公积金,养老金,社保系统
 
分析:
社保系统
实时性要求不高
不存在瞬时压力
大规模分析?
数据规模大
数据重要不可丢失
偏于查询?
 
方案1:按照用户取模,
带来的问题:后续扩容困难
 
方案2:按用户ID范围分片(1-1000万=分片1,xxx)
带来的问题:用户活跃度无法掌握,可能存在热点问题
 
方案3:按省份区县地区枚举
数据分配不一定均匀
 
 
 
        数据库问题解决后,应用面对的新挑战就是拆分应用等
 
参考
        Mycat在线视频培训【链接:http://pan.baidu.com/s/1nuR26rZ 密码:1gr9 (2015)】
        大型网站系统与Java中间件实践.pdf
        MySQL数据库的演化可以参考:http://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=207666963&idx=2&sn=0d0710e071420c6fc6af8d4a3bc3dfe6&scene=1#rd
        http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651959773&idx=1&sn=7e4ad0dcd050f6662dfaf39d9de36f2c&chksm=bd2d04018a5a8d17b92098b4840aac23982e32d179cdd957e4c55011f6a08f6bd31f9ba5cfee&mpshare=1&scene=23&srcid=1220t4ttl8wZaYHlQRzO0xYB#rd【一分钟掌握数据库垂直拆分-沈剑】
 
 
垂直拆分
  垂直拆分就是要把表按模块划分到不同数据库表中(当然原则还是不破坏第三范式),这种拆分在大型网站的演变过程中是很常见的。当一个网站还在很小的时候,只有小量的人来开发和维护,各模块和表都在一起,当网站不断丰富和壮大的时候,也会变成多个子系统来支撑,这时就有按模块和功能把表划分出来的需求。其实,相对于垂直切分更进一步的是服务化改造,说得简单就是要把原来强耦合的系统拆分成多个弱耦合的服务,通过服务间的调用来满足业务需求看,因此表拆出来后要通过服务的形式暴露出去,而不是直接调用不同模块的表,淘宝在架构不断演变过程,最重要的一环就是服务化改造,把用户、交易、店铺、宝贝这些核心的概念抽取成独立的服务,也非常有利于进行局部的优化和治理,保障核心模块的稳定性
  垂直拆分:单表大数据量依然存在性能瓶颈
  水平拆分
  上面谈到垂直切分只是把表按模块划分到不同数据库,但没有解决单表大数据量的问题,而水平切分就是要把一个表按照某种规则把数据划分到不同表或数据库里。例如像计费系统,通过按时间来划分表就比较合适,因为系统都是处理某一时间段的数据。而像SaaS应用,通过按用户维度来划分数据比较合适,因为用户与用户之间的隔离的,一般不存在处理多个用户数据的情况,简单的按user_id范围来水平切分
  通俗理解:水平拆分行,行数据拆分到不同表中, 垂直拆分列,表数据拆分到不同表中
  垂直与水平联合切分
  由上面可知垂直切分能更清晰化模块划分,区分治理,水平切分能解决大数据量性能瓶颈问题,因此常常就会把两者结合使用,这在大型网站里是种常见的策略
  案例:
  以mysql为例,简单购物系统暂设涉及如下表:
  1.产品表(数据量10w,稳定)
  2.订单表(数据量200w,且有增长趋势)
  3.用户表 (数据量100w,且有增长趋势)
  以mysql为例讲述下水平拆分和垂直拆分,mysql能容忍的数量级在百万静态数据可以到千万
  垂直拆分:
  解决问题:
  表与表之间的io竞争
  不解决问题:
  单表中数据量增长出现的压力
  方案:
  把产品表和用户表放到一个server上
  订单表单独放到一个server上
  水平拆分:
  解决问题:
  单表中数据量增长出现的压力
  不解决问题:
  表与表之间的io争夺
  方案:
  用户表通过性别拆分为男用户表和女用户表
  订单表通过已完成和完成中拆分为已完成订单和未完成订单
  产品表 未完成订单放一个server上
  已完成订单表盒男用户表放一个server上
  女用户表放一个server上(女的爱购物)
 
 
 
《大型网站系统与Java中间件实践》本书围绕大型网站和支撑大型网站架构的 Java 中间件的实践展开介绍。从分布式系统的知识切入,让读者对分布式系统有基本的了解;然后介绍大型网站随着数据量、访问量增长而发生的架构变迁;接着讲述构建 Java 中间件的相关知识;之后的几章都是根据笔者的经验来介绍支撑大型网站架构的 Java 中间件系统的设计和实践。本节为大家介绍专库专用,数据垂直拆分。

AD:
51CTO 网+ 第十二期沙龙:大话数据之美_如何用数据驱动用户体验

2.2.7 读写分离后,数据库又遇到瓶颈

通过读写分离以及在某些场景用分布式存储系统替换关系型数据库的方式,能够降低主库的压力,解决数据存储方面的问题。不过随着业务的发展,我们的主库也会遇到瓶颈。我们的网站演进到现在,交易、商品、用户的数据还都在一个数据库中。尽管采取了增加缓存、读写分离的方式,这个数据库的压力还是在继续增加,因此我们需要去解决这个问题,我们有数据垂直拆分和水平拆分两种选择。

2.2.7.1 专库专用,数据垂直拆分

垂直拆分的意思是把数据库中不同的业务数据拆分到不同的数据库中。结合现在的例子,就是把交易、商品、用户的数据分开,如图2-20 所示。

 



 

这样的变化给我们带来的影响是什么呢?应用需要配置多个数据源,这就增加了所需的配置,不过带来的是每个数据库连接池的隔离。不同业务的数据从原来的一个数据库中拆分到了多个数据库中,那么就需要考虑如何处理原来单机中跨业务的事务。一种办法是使用分布式事务,其性能要明显低于之前的单机事务;而另一种办法就是去掉事务或者不去追求强事务支持,则原来在单库中可以使用的表关联的查询也就需要改变实现了。

对数据进行垂直拆分之后,解决了把所有业务数据放在一个数据库中的压力问题。并且也可以根据不同业务的特点进行更多优化。

 

2.2.7.2 垂直拆分后的单机遇到瓶颈,数据水平拆分

与数据垂直拆分对应的还有数据水平拆分。数据水平拆分就是把同一个表的数据拆到两个数据库中。产生数据水平拆分的原因是某个业务的数据表的数据量或者更新量达到了单个数据库的瓶颈,这时就可以把这个表拆到两个或者多个数据库中。数据水平拆分与读写分离的区别是,读写分离解决的是读压力大的问题,对于数据量大或者更新量的情况并不起作用。数据水平拆分与数据垂直拆分的区别是,垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆到不同的数据库中。例如,经过垂直拆分后,用户表与交易表、商品表不在一个数据库中了,如果数据量或者更新量太大,我们可以进一步把用户表拆分到两个数据库中,它们拥有结构一模一样的用户表,而且每个库中的用户表都只涵盖了一部分的用户,两个数据库的用户合在一起就相当于没有拆分之前的用户表。我们先来简单看一下引入数据水平拆分后的结构,如图2-21 所示。

我们来分析一下水平拆分后给业务应用带来的影响。

首先,访问用户信息的应用系统需要解决SQL 路由的问题,因为现在用户信息分在了两个数据库中,需要在进行数据库操作时了解需要操作的数据在哪里。

此外,主键的处理也会变得不同。原来依赖单个数据库的一些机制需要变化,例如原来使用Oracle 的Sequence 或者MySQL 表上的自增字段的,现在不能简单地继续使用了。并且在不同的数据库中也不能直接使用一些数据库的限制来保证主键不重复了。

 



 

最后,由于同一个业务的数据被拆分到了不同的数据库中,因此一些查询需要从两个数据库中取数据,如果数据量太大而需要分页,就会比较难处理了。

不过,一旦我们能够完成数据的水平拆分,我们将能够很好地应对数据量及写入量增长的情况。具体如何完成数据水平拆分,在后面分布式数据访问层的章节中我们将进行更加详细的介绍。

 

2.2.8 数据库问题解决后,应用面对的新挑战

2.2.8.1 拆分应用

前面所讲的读写分离、分布式存储、数据垂直拆分和数据水平拆分都是在解决数据方面的问题。下面我们来看看应用方面的变化。

之前解决了应用服务器从单机到多机的扩展,应用就可以在一定范围内水平扩展了。随着业务的发展,应用的功能会越来越多,应用也会越来越大。我们需要考虑如何不让应用持续变大,这就需要把应用拆开,从一个应用变为两个甚至多个应用。我们来看两种方式。

第一种方式,根据业务的特性把应用拆开。在我们的例子中,主要的业务功能分为三大部分:交易、商品和用户。我们可以把原来的一个应用拆成分别以交易和商品为主的两个应用,对于交易和商品都会有涉及用户的地方,我们让这两个系统自己完成涉及用户的工作,而类似用户注册、登录等基础的用户工作,可以暂时交给两系统之一来完成(注意,我们在这里主要是通过例子说明拆分的做法),如图2-22 所示,这样的拆分可以使大的应用变小。

 



 

我们还可以按照用户注册、用户登录、用户信息维护等再拆分,使之变成三个系统。不过,这样拆分后在不同系统中会有一些相似的代码,例如用户相关的代码。如何能够保证这部分代码的一致以及如何对其复用是需要解决的问题。此外,按这样的方式拆分出来的新系统之间一般没有直接的相互调用。而且,新拆出来的应用可能会连接同样的数据库。

来看一个具体的例子,如图2-23 所示。

我们根据业务的不同功能拆分了几个业务应用,而且这些业务应用之间不存在直接的调用,它们都依赖底层的数据库、缓存、文件系统、搜索等。这样的应用拆分确实能够解决当下的一些问题,不过也有一些缺点。  



 

 

2.2.8.2 走服务化的路

我们再来看一下服务化的做法。图2-24 是一个示意图。从中可以看到我们把应用分为了三层,处于最上端的是Web 系统,用于完成不同的业务功能;处于中间的是一些服务中心,不同的服务中心提供不同的业务服务;处于下层的则是业务的数据库。当然,我们在这个图中省去了缓存等基础的系统,因此可以说是服务化系统结构的一个简图。

 



 

图2-24 与之前的图相比有几个很重要的变化。首先,业务功能之间的访问不仅是单机内部的方法调用了,还引入了远程的服务调用。其次,共享的代码不再是散落在不同的应用中了,这些实现被放在了各个服务中心。第三,数据库的连接也发生了一些变化,我们把与数据库的交互工作放到了服务中心,让前端的Web 应用更加注重与浏览器交互的工作,而不必过多关注业务逻辑的事情。连接数据库的任务交给相应的业务服务中心了,这样可以降低数据库的连接数。而服务中心不仅把一些可以共用的之前散落在各个业务的代码集中了起来,并且能够使这些代码得到更好的维护。第四,通过服务化,无论是前端Web 应用还是服务中心,都可以是由固定小团队来维护的系统,这样能够更好地保持稳定性,并能更好地控制系统本身的发展,况且稳定的服务中心日常发布的次数也远小于前端Web 应用,因此这个方式也减小了不稳定的风险。

要做到服务化还需要一些基础组件的支撑,在后面服务框架的章节我们会具体介绍。

 

 

通过某种特定的条件,将存放在同一个数据库中的数据分散存放到多个数据库上,实现分布存储,通过路由规则路由访问特定的数据库,这样一来每次访问面对的就不是单台服务器了,而是N台服务器,这样就可以降低单台机器的负载压力。提示:sqlserver 2005版本之后,可以友好的支持“表分区”。

  垂直(纵向)拆分:是指按功能模块拆分,比如分为订单库、商品库、用户库...这种方式多个数据库之间的表结构不同。

  水平(横向)拆分:将同一个表的数据进行分块保存到不同的数据库中,这些数据库中的表结构完全相同。

SQL Server:数据库/数据表 拆分
▲(纵向拆分)

SQL Server:数据库/数据表 拆分
▲(横向拆分)

  1,实现原理:使用垂直拆分,主要要看应用类型是否合适这种拆分方式,如系统可以分为,订单系统,商品管理系统,用户管理系统业务系统比较明的,垂直拆分能很好的起到分散数据库压力的作用。业务模块不明晰,耦合(表关联)度比较高的系统不适合使用这种拆分方式。但是垂直拆分方式并不能彻底解决所有压力问题,例如 有一个5000w的订单表,操作起来订单库的压力仍然很大,如我们需要在这个表中增加(insert)一条新的数据,insert完毕后,数据库会针对这张表重新建立索引,5000w行数据建立索引的系统开销还是不容忽视的,反过来,假如我们将这个表分成100个table呢,从table_001一直到table_100,5000w行数据平均下来,每个子表里边就只有50万行数据,这时候我们向一张只有50w行数据的table中insert数据后建立索引的时间就会呈数量级的下降,极大了提高了DB的运行时效率,提高了DB的并发量,这种拆分就是横向拆分

  2,实现方法:垂直拆分,拆分方式实现起来比较简单,根据表名访问不同的数据库就可以了。横向拆分的规则很多,这里总结前人的几点,

  (1)顺序拆分:如可以按订单的日前按年份才分,2003年的放在db1中,2004年的db2,以此类推。当然也可以按主键标准拆分。

  优点:可部分迁移

  缺点:数据分布不均,可能2003年的订单有100W,2008年的有500W。

  (2)hash取模分: 对user_id进行hash(或者如果user_id是数值型的话直接使用user_id的值也可),然后用一个特定的数字,比如应用中需要将一个数据库切分成4个数据库的话,我们就用4这个数字对user_id的hash值进行取模运算,也就是user_id%4,这样的话每次运算就有四种可能:结果为1的时候对应DB1;结果为2的时候对应DB2;结果为3的时候对应DB3;结果为0的时候对应DB4,这样一来就非常均匀的将数据分配到4个DB中。

  优点:数据分布均匀

  缺点:数据迁移的时候麻烦;不能按照机器性能分摊数据 。

  (3)在认证库中保存数据库配置

  就是建立一个DB,这个DB单独保存user_id到DB的映射关系,每次访问数据库的时候都要先查询一次这个数据库,以得到具体的DB信息,然后才能进行我们需要的查询操作。

  优点:灵活性强,一对一关系

  缺点:每次查询之前都要多一次查询,会造成一定的性能损失。

 ---------------------------------------------------------------------------------
数据切分可以是物理上的,对数据通过一系列的切分规则将数据分布到不同的DB服务器上,通过路由规则路由访问特定的数据库,这样一来每次访问面对的就不是单台服务器了,而是N台服务器,这样就可以降低单台机器的负载压力。

数据切分也可以是数据库内的,对数据通过一系列的切分规则,将数据分布到一个数据库的不同表中,比如将article分为article_001,article_002等子表,若干个子表水平拼合有组成了逻辑上一个完整的article表,这样做的目的其实也是很简单的。 举个例子说明,比如article表中现在有5000w条数据,此时我们需要在这个表中增加(insert)一条新的数据,insert完毕后,数据库会针对这张表重新建立索引,5000w行数据建立索引的系统开销还是不容忽视的。但是反过来,假如我们将这个表分成100 个table呢,从article_001一直到article_100,5000w行数据平均下来,每个子表里边就只有50万行数据,这时候我们向一张只有50w行数据的table中insert数据后建立索引的时间就会呈数量级的下降,极大了提高了DB的运行时效率,提高了DB的并发量。当然分表的好处还不知这些,还有诸如写操作的锁操作等,都会带来很多显然的好处。

综上,分库降低了单点机器的负载;分表,提高了数据操作的效率,尤其是Write操作的效率。
----------------------------------------------------------------------------------

垂直拆分与水平拆分的优缺点

数据的拆分(Sharding)根据其拆分分规则的类型,可以分为两种拆分模式。一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切可以称之为数据的垂直(纵向)拆分;
另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)拆分。

垂直拆分的优点:
拆分后业务清晰,拆分规则明确
系统之间进行整合或扩展很容易
按照成本、应用的等级、应用的类型等将表放到不同的机器上便于管理
方便实现动静分离,冷热分离的数据库表的设计模式
数据维护相对简单


垂直拆分的缺点:
部分业务表无法Join,只能通过接口方式解决,提高了系统的复杂度
受每种业务的不同限制,存在单库性能瓶颈,不易进行数据扩展和提升性能
事务处理复杂


水平拆分的优点:
单库单表的数据能保持在一定的量级,有助于性能的提高。
切分的表结构相同,应用层改造较少,只需要增加路由规则即可。
提高了系统的稳定性和负载能力。
水平拆分的缺点:
切分后,数据是分散的,跨库join操作难和性能差
拆分规则难以抽象
分片事务的一致性难以解决
数据扩容的难度和维护量极大


综上所述,垂直拆分和水平拆分的共同点为:
存在分布式事务的问题
存在跨节点Join问题
存在跨节点合并排序和分页问题
存在多数据源管理的问题
----------------------------------------------------------------------------------
垂直拆分:
       垂直拆分是根据数据库里面的数据表的相关性进行拆分,比如:一个数据库里面既存在用户数据,又存在订单数据,那么垂直拆分可以把用户数据放入到用户库,把订单数据放到订单库。垂直分表是对数据表进行垂直拆分的一种方式,常见是把一个多字段的大表按常用字段和非常用字段进行拆分,每个表里面的数据记录数一般情况下是相同的,只是字段不一样,使用主键关联。

比如原始用户表是:

 

垂直拆分后的表是:



垂直拆分的优点是:

  1. 可以使得数据变小,一个数据块(block)就能存放更多的数据,在查询时就会减少I/O次数(每次查询时读取的Block就少)

  2. 可以达到最大化利用Cache的目的,具体在垂直拆分的时候可以将不常变的字段放一起,将经常改变的放一起

  3. 数据维护简单

 缺点是:

  1. 主键出现冗余,需要管理冗余例

  2.  会引起表连接JOIN操作(增加CPU开销)可以通过在业务服务器上进行join来减少数据库压力

  3.  依然存在单表数据量过大的问题(需要水平拆分)

  4. 事务处理复杂

 

水平拆分
概述

水平拆分是通过某种策略将数据分片来存储,分库内分表和分库两部分,每片数据会分散到不同的MySQL表或库,达到分布式的效果,能够支持非常大的数据量。前面的表分区本质上也是一种特殊的库内分表

库内分表,仅仅是单纯的解决了单一表数据过大的问题,由于没有把表的数据分布到不同的机器上,因此对于减轻MySQL服务器的压力来说,并没有太大的作用,大家还是竞争同一个物理机上的IO、CPU、网络,这个就要通过分库来解决

水平拆分表如下:



 

实际情况中往往会是垂直拆分和水平拆分的结合,即将Users_A_M和Users_N_Z再拆成Users和UserExtras,这样一共四张表

水平拆分的优点是:

不存在单库大数据和高并发的性能瓶颈
应用端改造较少
提高了系统的稳定性和负载能力
缺点是:

分片事务一致性难以解决
跨节点Join性能差,逻辑复杂
数据多次扩展难度跟维护量极大
--------------------- 

猜你喜欢

转载自blog.csdn.net/Leon_Jinhai_Sun/article/details/86423304