通 过MySQLReplication功能所实现的扩展老是会受到数据库大小的限制,一旦数据库过于庞大,尤为是当写入过于频繁,很难由一台主机支撑的时 候,咱们仍是会面临到扩展瓶颈。这时候,咱们就必须许找其余技术手段来解决这个瓶颈,那就是咱们这一章所要介绍恶的数据切分技术。前端
可 能不少读者朋友在网上或者杂志上面都已经屡次见到关于数据切分的相关文章了,只不过在有些文章中称之为数据的Sharding。其实无论是称之为数据的 Sharding仍是数据的切分,其概念都是同样的。简单来讲,就是指经过某种特定的条件,将咱们存放在同一个数据库中的数据分散存放到多个数据库(主 机)上面,以达到分散单台设备负载的效果。数据的切分同时还能够提升系统的整体可用性,由于单台设备Crash以后,只有整体数据的某部分不可用,而不是 全部的数据。mysql
数 据的切分(Sharding)根据其切分规则的类型,能够分为两种切分模式。一种是按照不一样的表(或者Schema)来切分到不一样的数据库(主机)之上, 这种切能够称之为数据的垂直(纵向)切分;另一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切 分称之为数据的水平(横向)切分。sql
垂 直切分的最大特色就是规则简单,实施也更为方便,尤为适合各业务之间的耦合度很是低,相互影响很小,业务逻辑很是清晰的系统。在这种系统中,能够很容易作 到将不一样业务模块所使用的表分拆到不一样的数据库中。根据不一样的表来进行拆分,对应用程序的影响也更小,拆分规则也会比较简单清晰。数据库
水平切分于垂直切分相比,相对来讲稍微复杂一些。由于要将同一个表中的不一样数据拆分到不一样的数据库中,对于应用程序来讲,拆分规则自己就较根据表名来拆分更为复杂,后期的数据维护也会更为复杂一些。后端
当咱们某个(或者某些)表的数据量和访问量特别的大,经过垂直切分将其放在独立的设备上后仍然没法知足性能要求,这时候咱们就必须将垂直切分和水平切分相结合,先垂直切分,而后再水平切分,才能解决这种超大型表的性能问题。服务器
下面咱们就针对垂直、水平以及组合切分这三种数据切分方式的架构实现及切分后数据的整合进行相应的分析。架构
我 们先来看一下,数据的垂直切分究竟是如何一个切分法的。数据的垂直切分,也能够称之为纵向切分。将数据库想象成为由不少个一大块一大块的“数据块”(表) 组成,咱们垂直的将这些“数据块”切开,而后将他们分散到多台数据库主机上面。这样的切分方法就是一个垂直(纵向)的数据切分。负载均衡
一 个架构设计较好的应用系统,其整体功能确定是由不少个功能模块所组成的,而每个功能模块所须要的数据对应到数据库中就是一个或者多个表。而在架构设计 中,各个功能模块相互之间的交互点越统一越少,系统的耦合度就越低,系统各个模块的维护性以及扩展性也就越好。这样的系统,实现数据的垂直切分也就越容 易。框架
当咱们的功能模块越清晰,耦合度越低,数据垂直切分的规则定义也就越容易。彻底能够根据功能模块来进行数据的切分,不一样功能模块的数据存放于不一样的数据库主机中,能够很容易就避免掉跨数据库的Join存在,同时系统架构也很是的清晰。分布式
当 然,很难有系统可以作到全部功能模块所使用的表彻底独立,彻底不须要访问对方的表或者须要两个模块的表进行Join操做。这种状况下,咱们就必须根据实际 的应用场景进行评估权衡。决定是迁就应用程序将须要Join的表的相关某快都存放在同一个数据库中,仍是让应用程序作更多的事情,也就是程序彻底经过模块 接口取得不一样数据库中的数据,而后在程序中完成Join操做。
通常来讲,若是是一个负载相对不是很大的系统,并且表关联又很是的频繁,那可能数据库让步,将几个相关模块合并在一块儿减小应用程序的工做的方案能够减小较多的工做量,是一个可行的方案。
当 然,经过数据库的让步,让多个模块集中共用数据源,实际上也是简介的默许了各模块架构耦合度增大的发展,可能会让之后的架构愈来愈恶化。尤为是当发展到一 定阶段以后,发现数据库实在没法承担这些表所带来的压力,不得不面临再次切分的时候,所带来的架构改形成本可能会远远大于最初的时候。
因此,在数据库进行垂直切分的时候,如何切分,切分到什么样的程度,是一个比较考验人的难题。只能在实际的应用场景中经过平衡各方面的成本和收益,才能分析出一个真正适合本身的拆分方案。
好比在本书所使用示例系统的example数据库,咱们简单的分析一下,而后再设计一个简单的切分规则,进行一次垂直垂直拆分。
系统功能能够基本分为四个功能模块:用户,群组消息,相册以及事件,分别对应为以下这些表:
1. 用户模块表:user,user_profile,user_group,user_photo_album
2. 群组讨论表:groups,group_message,group_message_content,top_message
3. 相册相关表:photo,photo_album,photo_album_relation,photo_comment
4. 事件信息表:event
初略一看,没有哪个模块能够脱离其余模块独立存在,模块与模块之间都存在着关系,莫非没法切分?
固然不是,咱们再稍微深刻分析一下,能够发现,虽然各个模块所使用的表之间都有关联,可是关联关系还算比较清晰,也比较简单。
◆群组讨论模块和用户模块之间主要存在经过用户或者是群组关系来进行关联。通常关联的时候都会是经过用户的id或者nick_name以及group的id来进行关联,经过模块之间的接口实现不会带来太多麻烦;
◆相册模块仅仅与用户模块存在经过用户的关联。这两个模块之间的关联基本就有经过用户id关联的内容,简单清晰,接口明确;
◆ 事件模块与各个模块可能都有关联,可是都只关注其各个模块中对象的ID信息,一样能够作到很容易分拆。
因此,咱们第一步能够将数据库按照功能模块相关的表进行一次垂直拆分,每一个模块所涉及的表单独到一个数据库中,模块与模块之间的表关联都在应用系统端经过藉口来处理。以下图所示:
经过这样的垂直切分以后,以前只能经过一个数据库来提供的服务,就被分拆成四个数据库来提供服务,服务能力天然是增长几倍了。
垂直切分的优势
◆ 数据库的拆分简单明了,拆分规则明确;
◆ 应用程序模块清晰明确,整合容易;
◆ 数据维护方便易行,容易定位;
垂直切分的缺点
◆ 部分表关联没法在数据库级别完成,须要在程序中完成;
◆ 对于访问极其频繁且数据量超大的表仍然存在性能平静,不必定能知足要求;
◆ 事务处理相对更为复杂;
◆ 切分达到必定程度以后,扩展性会遇到限制;
◆ 过读切分可能会带来系统过渡复杂而难以维护。
针 对于垂直切分可能遇到数据切分及事务问题,在数据库层面实在是很难找到一个较好的处理方案。实际应用案例中,数据库的垂直切分大可能是与应用系统的模块相对 应,同一个模块的数据源存放于同一个数据库中,能够解决模块内部的数据关联问题。而模块与模块之间,则经过应用程序以服务接口方式来相互提供所须要的数 据。虽然这样作在数据库的整体操做次数方面确实会有所增长,可是在系统总体扩展性以及架构模块化方面,都是有益的。可能在某些操做的单次响应时间会稍有增 加,可是系统的总体性能极可能反而会有必定的提高。而扩展瓶颈问题,就只能依靠下一节将要介绍的数据水平切分架构来解决了。
上 面一节分析介绍了数据的垂直切分,这一节再分析一下数据的水平切分。数据的垂直切分基本上能够简单的理解为按照表按照模块来切分数据,而水平切分就再也不是 按照表或者是功能模块来切分了。通常来讲,简单的水平切分主要是将某个访问极其平凡的表再按照某个字段的某种规则来分散到多个表之中,每一个表中包含一部分 数据。
简 单来讲,咱们能够将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其余的数据库中。固然,为了能 够比较容易的断定各行数据被切分到哪一个数据库中了,切分老是都须要按照某种特定的规则来进行的。如根据某个数字类型字段基于特定数目取模,某个时间类型字 段的范围,或者是某个字符类型字段的hash值。若是整个系统中大部分核心表均可以经过某个字段来进行关联,那这个字段天然是一个进行水平分区的上上之选 了,固然,很是特殊没法使用就只能另选其余了。
一 般来讲,像如今互联网很是火爆的Web2.0类型的网站,基本上大部分数据都可以经过会员用户信息关联上,可能不少核心表都很是适合经过会员ID来进行数 据的水平切分。而像论坛社区讨论系统,就更容易切分了,很是容易按照论坛编号来进行数据的水平切分。切分以后基本上不会出现各个库之间的交互。
如 咱们的示例系统,全部数据都是和用户关联的,那么咱们就能够根据用户来进行水平拆分,将不一样用户的数据切分到不一样的数据库中。固然,惟一有点区别的是用户 模块中的groups表和用户没有直接关系,因此groups不能根据用户来进行水平拆分。对于这种特殊状况下的表,咱们彻底能够独立出来,单独放在一个 独立的数据库中。其实这个作法能够说是利用了前面一节所介绍的“数据的垂直切分”方法,我将在下一节中更为详细的介绍这种垂直切分与水平切分同时使用的联 合切分方法。
所 以,对于咱们的示例数据库来讲,大部分的表均可以根据用户ID来进行水平的切分。不一样用户相关的数据进行切分以后存放在不一样的数据库中。如将全部用户ID 经过2取模而后分别存放于两个不一样的数据库中。每一个和用户ID关联上的表均可以这样切分。这样,基本上每一个用户相关的数据,都在同一个数据库中,即便是需 要关联,也能够很是简单的关联上。
咱们能够经过下图来更为直观的展现水平切分相关信息:水平切分的优势
◆ 表关联基本可以在数据库端所有完成;
◆ 不会存在某些超大型数据量和高负载的表遇到瓶颈的问题;
◆ 应用程序端总体架构改动相对较少;
◆ 事务处理相对简单;
◆ 只要切分规则可以定义好,基本上较难遇到扩展性限制;
水平切分的缺点
◆ 切分规则相对更为复杂,很难抽象出一个可以知足整个数据库的切分规则;
◆ 后期数据的维护难度有所增长,人为手工定位数据更困难;
◆ 应用系统各模块耦合度较高,可能会对后面数据的迁移拆分形成必定的困难。
上 面两节内容中,咱们分别,了解了“垂直”和“水平”这两种切分方式的实现以及切分以后的架构信息,同时也分析了两种架构各自的优缺点。可是在实际的应用场 景中,除了那些负载并非太大,业务逻辑也相对较简单的系统能够经过上面两种切分方法之一来解决扩展性问题以外,恐怕其余大部分业务逻辑稍微复杂一点,系 统负载大一些的系统,都没法经过上面任何一种数据的切分方法来实现较好的扩展性,而须要将上述两种切分方法结合使用,不一样的场景使用不一样的切分方法。
在这一节中,我将结合垂直切分和水平切分各自的优缺点,进一步完善咱们的总体架构,让系统的扩展性进一步提升。
一 般来讲,咱们数据库中的全部表很难经过某一个(或少数几个)字段所有关联起来,因此很难简单的仅仅经过数据的水平切分来解决全部问题。而垂直切分也只能解 决部分问题,对于那些负载很是高的系统,即便仅仅只是单个表都没法经过单台数据库主机来承担其负载。咱们必须结合“垂直”和“水平”两种切分方式同时使 用,充分利用二者的优势,避开其缺点。
每 一个应用系统的负载都是一步一步增加上来的,在开始遇到性能瓶颈的时候,大多数架构师和DBA都会选择先进行数据的垂直拆分,由于这样的成本最早,最符合 这个时期所追求的最大投入产出比。然而,随着业务的不断扩张,系统负载的持续增加,在系统稳定一段时期以后,通过了垂直拆分以后的数据库集群可能又再一次 不堪重负,遇到了性能瓶颈。
这 时候咱们该如何抉择?是再次进一步细分模块呢,仍是寻求其余的办法来解决?若是咱们再一次像最开始那样继续细分模块,进行数据的垂直切分,那咱们可能在不 久的未来,又会遇到如今所面对的一样的问题。并且随着模块的不断的细化,应用系统的架构也会愈来愈复杂,整个系统极可能会出现失控的局面。
这 时候咱们就必需要经过数据的水平切分的优点,来解决这里所遇到的问题。并且,咱们彻底没必要要在使用数据水平切分的时候,推倒以前进行数据垂直切分的成果, 而是在其基础上利用水平切分的优点来避开垂直切分的弊端,解决系统复杂性不断扩大的问题。而水平拆分的弊端(规则难以统一)也已经被以前的垂直切分解决掉 了,让水平拆分能够进行的驾轻就熟。
对 于咱们的示例数据库,假设在最开始,咱们进行了数据的垂直切分,然而随着业务的不断增加,数据库系统遇到了瓶颈,咱们选择重构数据库集群的架构。如何重 构?考虑到以前已经作好了数据的垂直切分,并且模块结构清晰明确。而业务增加的势头愈来愈猛,即便如今进一步再次拆分模块,也坚持不了过久。咱们选择了在 垂直切分的基础上再进行水平拆分。
在 经历过垂直拆分后的各个数据库集群中的每个都只有一个功能模块,而每一个功能模块中的全部表基本上都会与某个字段进行关联。如用户模块所有均可以经过用户 ID进行切分,群组讨论模块则都经过群组ID来切分,相册模块则根据相册ID来进切分,最后的事件通知信息表考虑到数据的时限性(仅仅只会访问最近某个事 件段的信息),则考虑按时间来切分。
下图展现了切分后的整个架构:
实 际上,在不少大型的应用系统中,垂直切分和水平切这两种数据的切分方法基本上都是并存的,并且常常在不断的交替进行,以不断的增长系统的扩展能力。咱们在 应对不一样的应用场景的时候,也须要充分考虑到这两种切分方法各自的局限,以及各自的优点,在不一样的时期(负载压力)使用不一样的结合方式。
联合切分的优势
◆ 能够充分利用垂直切分和水平切分各自的优点而避免各自的缺陷;
◆ 让系统扩展性获得最大化提高;
联合切分的缺点
◆ 数据库系统架构比较复杂,维护难度更大;
◆ 应用程序架构也相对更复杂;
通 过前面的章节,咱们已经很清楚了经过数据库的数据切分能够极大的提升系统的扩展性。可是,数据库中的数据在通过垂直和(或)水平切分被存放在不一样的数据库 主机以后,应用系统面临的最大问题就是如何来让这些数据源获得较好的整合,可能这也是不少读者朋友很是关心的一个问题。这一节咱们主要针对的内容就是分析 可使用的各类能够帮助咱们实现数据切分以及数据整合的总体解决方案。
数据的整合很难依靠数据库自己来达到这个效果,虽然MySQL存在Federated存储引擎,能够解决部分相似的问题,可是在实际应用场景中却很难较好的运用。那咱们该如何来整合这些分散在各个MySQL主机上面的数据源呢?
总的来讲,存在两种解决思路:
1. 在每一个应用程序模块中配置管理本身须要的一个(或者多个)数据源,直接访问各个数据库,在模块内完成数据的整合;
2. 经过中间代理层来统一管理全部的数据源,后端数据库集群对前端应用程序透明;
可能90%以上的人在面对上面这两种解决思路的时候都会倾向于选择第二种,尤为是系统不断变得庞大复杂的时候。确实,这是一个很是正确的选择,虽然短时间内须要付出的成本可能会相对更大一些,可是对整个系统的扩展性来讲,是很是有帮助的。
因此,对于第一种解决思路我这里就不许备过多的分析,下面我重点分析一下在第二种解决思路中的一些解决方案。
★ 自行开发中间代理层
在决定选择经过数据库的中间代理层来解决数据源整合的架构方向以后,有很多公司(或者企业)选择了经过自行开发符合自身应用特定场景的代理层应用程序。
经过自行开发中间代理层能够最大程度的应对自身应用的特定,最大化的定制不少个性化需求,在面对变化的时候也能够灵活的应对。这应该说是自行开发代理层最大的优点了。
固然,选择自行开发,享受让个性化定制最大化的乐趣的同时,天然也须要投入更多的成原本进行前期研发以及后期的持续升级改进工做,并且自己的技术门槛可能也比简单的Web应用要更高一些。因此,在决定选择自行开发以前,仍是须要进行比较全面的评估为好。
因为自行开发更多时候考虑的是如何更好的适应自身应用系统,应对自身的业务场景,因此这里也很差分析太多。后面咱们主要分析一下当前比较流行的几种数据源整合解决方案。
★利用MySQLProxy实现数据切分及整合
MySQLProxy 是MySQL官方提供的一个数据库代理层产品,和MySQLServer同样,一样是一个基于GPL开源协议的开源产品。可用来监视、分析或者传输他们之 间的通信信息。他的灵活性容许你最大限度的使用它,目前具有的功能主要有链接路由,Query分析,Query过滤和修改,负载均衡,以及基本的HA机制 等。
实际上,MySQLProxy自己并不具备上述全部的这些功能,而是提供了实现上述功能的基础。要实现这些功能,还须要经过咱们自行编写LUA脚原本实现。
MySQLProxy 其实是在客户端请求与MySQLServer之间创建了一个链接池。全部客户端请求都是发向MySQLProxy,而后经由MySQLProxy进行相 应的分析,判断出是读操做仍是写操做,分发至对应的MySQLServer上。对于多节点Slave集群,也能够起作到负载均衡的效果。如下是 MySQLProxy的基本架构图:
通 过上面的架构简图,咱们能够很清晰的看出MySQLProxy在实际应用中所处的位置,以及能作的基本事情。关于MySQLProxy更为详细的实施细则 在MySQL官方文档中有很是详细的介绍和示例,感兴趣的读者朋友能够直接从MySQL官方网站免费下载或者在线阅读,我这里就不累述浪费纸张了。
★利用Amoeba实现数据切分及整合
Amoeba是一个基于Java开发的,专一于解决分布式数据库数据源整合Proxy程序的开源框架,基于GPL3开源协议。目前,Amoeba已经具备Query路由,Query过滤,读写分离,负载均衡以及HA机制等相关内容。
Amoeba 主要解决的如下几个问题:
1. 数据切分后复杂数据源整合;
2. 提供数据切分规则并下降数据切分规则给数据库带来的影响;
3. 下降数据库与客户端的链接数;
4. 读写分离路由;
咱们能够看出,Amoeba所作的事情,正好就是咱们经过数据切分来提高数据库的扩展性所须要的。
Amoeba并非一个代理层的Proxy程序,而是一个开发数据库代理层Proxy程序的开发框架,目前基于Amoeba所开发的Proxy程序有AmoebaForMySQL和AmoebaForAladin两个。
AmoebaForMySQL 主要是专门针对MySQL数据库的解决方案,前端应用程序请求的协议以及后端链接的数据源数据库都必须是MySQL。对于客户端的任何应用程序来 说,AmoebaForMySQL和一个MySQL数据库没有什么区别,任何使用MySQL协议的客户端请求,均可以被AmoebaForMySQL解析 并进行相应的处理。下如能够告诉咱们AmoebaForMySQL的架构信息(出自Amoeba开发者博客):
AmoebaForAladin 则是一个适用更为普遍,功能更为强大的Proxy程序。他能够同时链接不一样数据库的数据源为前端应用程序提供服务,可是仅仅接受符合MySQL协议的客户 端应用程序请求。也就是说,只要前端应用程序经过MySQL协议链接上来以后,AmoebaForAladin会自动分析Query语句,根据Query 语句中所请求的数据来自动识别出该所Query的数据源是在什么类型数据库的哪个物理主机上面。下图展现了AmoebaForAladin的架构细节 (出自Amoeba开发者博客):
咋一看,二者好像彻底同样嘛。细看以后,才会发现二者主要的区别仅在于经过MySQLProtocalAdapter处理以后,根据分析结果判断出数据源数据库,而后选择特定的JDBC驱动和相应协议链接后端数据库。
其实经过上面两个架构图你们可能也已经发现了Amoeba的特色了,他仅仅只是一个开发框架,咱们除了选择他已经提供的ForMySQL和ForAladin这两款产品以外,还能够基于自身的需求进行相应的二次开发,获得更适应咱们本身应用特色的Proxy程序。
当 对于使用MySQL数据库来讲,不管是AmoebaForMySQL仍是AmoebaForAladin均可以很好的使用。固然,考虑到任何一个系统越是 复杂,其性能确定就会有必定的损失,维护成本天然也会相对更高一些。因此,对于仅仅须要使用MySQL数据库的时候,我仍是建议使用 AmoebaForMySQL。
AmoebaForMySQL的使用很是简单,全部的配置文件都是标准的XML文件,总共有四个配置文件。分别为:
◆amoeba.xml:主配置文件,配置全部数据源以及Amoeba自身的参数设置;
◆rule.xml:配置全部Query路由规则的信息;
◆functionMap.xml:配置用于解析Query中的函数所对应的Java实现类;
◆ rullFunctionMap.xml:配置路由规则中须要使用到的特定函数的实现类;
如 果您的规则不是太复杂,基本上仅须要使用到上面四个配置文件中的前面两个就可完成全部工做。Proxy程序经常使用的功能如读写分离,负载均衡等配置都在 amoeba.xml中进行。此外,Amoeba已经支持了实现数据的垂直切分和水平切分的自动路由,路由规则能够在rule.xml进行设置。
目 前Amoeba少有欠缺的主要就是其在线管理功能以及对事务的支持了,曾经在与相关开发者的沟经过程中提出过相关的建议,但愿可以提供一个能够进行在线维 护管理的命令行管理工具,方便在线维护使用,获得的反馈是管理专门的管理模块已经归入开发日程了。另外在事务支持方面暂时仍是Amoeba没法作到的,即 使客户端应用在提交给Amoeba的请求是包含事务信息的,Amoeba也会忽略事务相关信息。固然,在通过不断完善以后,我相信事务支持确定是 Amoeba重点考虑增长的feature。
关于Amoeba更为详细的使用方法读者朋友能够经过Amoeba开发者博客(http://amoeba.sf.net)上面提供的使用手册获取,这里就再也不细述了。
★利用HiveDB实现数据切分及整合
和 前面的MySQLProxy以及Amoeba同样,HiveDB一样是一个基于Java针对MySQL数据库的提供数据切分及整合的开源框架,只是目前的 HiveDB仅仅支持数据的水平切分。主要解决大数据量下数据库的扩展性及数据的高性能访问问题,同时支持数据的冗余及基本的HA机制。
HiveDB的实现机制与MySQLProxy和Amoeba有必定的差别,他并非借助MySQL的Replication功能来实现数据的冗余,而是自行实现了数据冗余机制,而其底层主要是基于HibernateShards来实现的数据切分工做。
在 HiveDB中,经过用户自定义的各类Partitionkeys(其实就是制定数据切分规则),将数据分散到多个MySQLServer中。在访问的时 候,在运行Query请求的时候,会自动分析过滤条件,并行从多个MySQLServer中读取数据,并合并结果集返回给客户端应用程序。
单纯从功能方面来说,HiveDB可能并不如MySQLProxy和Amoeba那样强大,可是其数据切分的思路与前面两者并没有本质差别。此外,HiveDB并不只仅只是一个开源爱好者所共享的内容,而是存在商业公司支持的开源项目。
下面是HiveDB官方网站上面一章图片,描述了HiveDB如何来组织数据的基本信息,虽然不能详细的表现出太多架构方面的信息,可是也基本能够展现出其在数据切分方面独特的一面了。
★ mycat 数据整合:具体http://www.songwie.com/articlelist/11
★ 其余实现数据切分及整合的解决方案
除了上面介绍的几个数据切分及整合的总体解决方案以外,还存在不少其余一样提供了数据切分与整合的解决方案。如基于MySQLProxy的基础上作了进一步扩展的HSCALE,经过Rails构建的SpockProxy,以及基于Pathon的Pyshards等等。
无论你们选择使用哪种解决方案,整体设计思路基本上都不该该会有任何变化,那就是经过数据的垂直和水平切分,加强数据库的总体服务能力,让应用系统的总体扩展能力尽量的提高,扩展方式尽量的便捷。
只 要咱们经过中间层Proxy应用程序较好的解决了数据切分和数据源整合问题,那么数据库的线性扩展能力将很容易作到像咱们的应用程序同样方便,只须要经过 添加廉价的PCServer服务器,便可线性增长数据库集群的总体服务能力,让数据库再也不轻易成为应用系统的性能瓶颈。
这里,你们应该对数据切分与整合的实施有了必定的认识了,或许不少读者朋友都已经根据各类解决方案各自特性的优劣基本选定了适合于本身应用场景的方案,后面的工做主要就是实施准备了。
在实施数据切分方案以前,有些可能存在的问题咱们仍是须要作一些分析的。通常来讲,咱们可能遇到的问题主要会有如下几点:
◆ 引入分布式事务的问题;
◆跨节点Join的问题;
◆ 跨节点合并排序分页问题;
1. 引入分布式事务的问题
一旦数据进行切分被分别存放在多个MySQLServer中以后,无论咱们的切分规则设计的多么的完美(实际上并不存在完美的切分规则),均可能形成以前的某些事务所涉及到的数据已经不在同一个MySQLServer中了。
在 这样的场景下,若是咱们的应用程序仍然按照老的解决方案,那么势必须要引入分布式事务来解决。而在MySQL各个版本中,只有从MySQL5.0开始之后 的各个版本才开始对分布式事务提供支持,并且目前仅有Innodb提供分布式事务支持。不只如此,即便咱们恰好使用了支持分布式事务的MySQL版本,同 时也是使用的Innodb存储引擎,分布式事务自己对于系统资源的消耗就是很大的,性能自己也并非过高。并且引入分布式事务自己在异常处理方面就会带来 较多比较难控制的因素。
怎 么办?其实咱们能够能够经过一个变通的方法来解决这种问题,首先须要考虑的一件事情就是:是否数据库是惟一一个可以解决事务的地方呢?其实并非这样的, 咱们彻底能够结合数据库以及应用程序二者来共同解决。各个数据库解决本身身上的事务,而后经过应用程序来控制多个数据库上面的事务。
也就是说,只要咱们愿意,彻底能够将一个跨多个数据库的分布式事务分拆成多个仅处于单个数据库上面的小事务,并经过应用程序来总控各个小事务。固然,这样做的要求就是咱们的俄应用程序必需要有足够的健壮性,固然也会给应用程序带来一些技术难度。
2.跨节点Join的问题
上面介绍了可能引入分布式事务的问题,如今咱们再看看须要跨节点Join的问题。数据切分以后,可能会形成有些老的Join语句没法继续使用,由于Join使用的数据源可能被切分到多个MySQLServer中了。
怎 么办?这个问题从MySQL数据库角度来看,若是非得在数据库端来直接解决的话,恐怕只能经过MySQL一种特殊的存储引擎Federated来解决了。 Federated存储引擎是MySQL解决相似于Oracle的DBLink之类问题的解决方案。和OracleDBLink的主要区别在于 Federated会保存一份远端表结构的定义信息在本地。咋一看,Federated确实是解决跨节点Join很是好的解决方案。可是咱们还应该清楚一 点,那就彷佛若是远端的表结构发生了变动,本地的表定义信息是不会跟着发生相应变化的。若是在更新远端表结构的时候并无更新本地的Federated表 定义信息,就极可能形成Query运行出错,没法获得正确的结果。
对 待这类问题,我仍是推荐经过应用程序来进行处理,先在驱动表所在的MySQLServer中取出相应的驱动结果集,而后根据驱动结果集再到被驱动表所在的 MySQLServer中取出相应的数据。可能不少读者朋友会认为这样作对性能会产生必定的影响,是的,确实是会对性能有必定的负面影响,可是除了此法, 基本上没有太多其余更好的解决办法了。并且,因为数据库经过较好的扩展以后,每台MySQLServer的负载就能够获得较好的控制,单纯针对单条 Query来讲,其响应时间可能比不切分以前要提升一些,因此性能方面所带来的负面影响也并非太大。更况且,相似于这种须要跨节点Join的需求也并不 是太多,相对于整体性能而言,可能也只是很小一部分而已。因此为了总体性能的考虑,偶尔牺牲那么一点点,实际上是值得的,毕竟系统优化自己就是存在不少取舍 和平衡的过程。
3. 跨节点合并排序分页问题
一 旦进行了数据的水平切分以后,可能就并不只仅只有跨节点Join没法正常运行,有些排序分页的Query语句的数据源可能也会被切分到多个节点,这样形成 的直接后果就是这些排序分页Query没法继续正常运行。其实这和跨节点Join是一个道理,数据源存在于多个节点上,要经过一个Query来解决,就和 跨节点Join是同样的操做。一样Federated也能够部分解决,固然存在的风险也同样。
仍是一样的问题,怎么办?我一样仍然继续建议经过应用程序来解决。
如 何解决?解决的思路大致上和跨节点Join的解决相似,可是有一点和跨节点Join不太同样,Join不少时候都有一个驱动与被驱动的关系,因此Join 自己涉及到的多个表之间的数据读取通常都会存在一个顺序关系。可是排序分页就不太同样了,排序分页的数据源基本上能够说是一个表(或者一个结果集),自己 并不存在一个顺序关系,因此在从多个数据源取数据的过程是彻底能够并行的。这样,排序分页数据的取数效率咱们能够作的比跨库Join更高,因此带来的性能 损失相对的要更小,在有些状况下可能比在原来未进行数据切分的数据库中效率更高了。固然,不管是跨节点Join仍是跨节点排序分页,都会使咱们的应用服务 器消耗更多的资源,尤为是内存资源,由于咱们在读取访问以及合并结果集的这个过程须要比原来处理更多的数据。
分析到这里,可能不少读者朋友会发现,上面全部的这些问题,我给出的建议基本上都是经过应用程序来解决。你们可能内心开始犯嘀咕了,是否是由于我是DBA,因此就不少事情都扔给应用架构师和开发人员了?
其 实彻底不是这样,首先应用程序因为其特殊性,能够很是容易作到很好的扩展性,可是数据库就不同,必须借助不少其余的方式才能作到扩展,并且在这个扩展过 程中,很难避免带来有些原来在集中式数据库中能够解决但被切分开成一个数据库集群以后就成为一个难题的状况。要想让系统总体获得最大限度的扩展,咱们只能 让应用程序作更多的事情,来解决数据库集群没法较好解决的问题。
通 过数据切分技术将一个大的MySQLServer切分红多个小的MySQLServer,既解决了写入性能瓶颈问题,同时也再一次提高了整个数据库集群的 扩展性。不管是经过垂直切分,仍是水平切分,都可以让系统遇到瓶颈的可能性更小。尤为是当咱们使用垂直和水平相结合的切分方法以后,理论上将不会再遇到扩 展瓶颈了。