mysql数据库切分
前言
通过MySQLReplication功能所实现的扩展总是会受到数据库大小的限制。一旦数据库过于庞大,尤其是当写入过于频繁,非常难由一台主机支撑的时候,我们还是会面临到扩展瓶颈。这时候,我们就必须许找其它技术手段来解决这个瓶颈,那就是我们这一章所要介绍恶的数据切分技术。
何谓数据切分
可能非常多读者朋友在网上或者杂志上面都已经多次见到关于数据切分的相关文章了,仅仅只是在有些文章中称之为数据的Sharding。事实上无论是称之为数据的Sharding还是数据的切分,其概念都是一样的。
简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。数据的切分同一时候还能够提高系统的总体可用性,由于单台设备Crash之后。仅仅有总体数据的某部分不可用,而不是全部的数据。
数据的切分(Sharding)依据其切分规则的类型。能够分为两种切分模式。
一种是依照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这样的切能够称之为数据的垂直(纵向)切分。另外一种则是依据表中的数据的逻辑关系,将同一个表中的数据依照某种条件拆分到多台数据库(主机)上面。这样的切分称之为数据的水平(横向)切分。
垂直切分的最大特点就是规则简单,实施也更为方便,尤其适合各业务之间的耦合度非常低。相互影响非常小,业务逻辑非常清晰的系统。在这样的系统中,能够非常easy做到将不同业务模块所使用的表分拆到不同的数据库中。依据不同的表来进行拆分。对应用程序的影响也更小,拆分规则也会比較简单清晰。
水平切分于垂直切分相比。相对来说略微复杂一些。由于要将同一个表中的不同数据拆分到不同的数据库中,对于应用程序来说,拆分规则本身就较依据表名来拆分更为复杂,后期的数据维护也会更为复杂一些。
当我们某个(或者某些)表的数据量和訪问量特别的大,通过垂直切分将其放在独立的设备上后仍然无法满足性能要求,这时候我们就必须将垂直切分和水平切分相结合。先垂直切分,然后再水平切分。才干解决这样的超大型表的性能问题。
以下我们就针对垂直、水平以及组合切分这三种数据切分方式的架构实现及切分后数据的整合进行对应的分析。
数据的垂直切分
我们先来看一下,数据的垂直切分究竟是怎样一个切分法的。数据的垂直切分。也能够称之为纵向切分。将数据库想象成为由非常多个一大块一大块的“数据块”(表)组成。我们垂直的将这些“数据块”切开,然后将他们分散到多台数据库主机上面。这样的切分方法就是一个垂直(纵向)的数据切分。
一个架构设计较好的应用系统。其总体功能肯定是由非常多个功能模块所组成的。而每一个功能模块所须要的数据对应到数据库中就是一个或者多个表。
而在架构设计中,各个功能模块相互之间的交互点越统一越少,系统的耦合度就越低,系统各个模块的维护性以及扩展性也就越好。这样的系统。实现数据的垂直切分也就越easy。
当我们的功能模块越清晰,耦合度越低,数据垂直切分的规则定义也就越easy。全然能够依据功能模块来进行数据的切分,不同功能模块的数据存放于不同的数据库主机中,能够非常easy就避免掉跨数据库的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信息,相同能够做到非常easy分拆。
所以。我们第一步能够将数据库依照功能模块相关的表进行一次垂直拆分。每一个模块所涉及的表单独到一个数据库中,模块与模块之间的表关联都在应用系统端通过藉口来处理。例如以下图所看到的:
通过这样的垂直切分之后。之前仅仅能通过一个数据库来提供的服务。就被分拆成四个数据库来提供服务,服务能力自然是添加几倍了。
垂直切分的长处
◆ 数据库的拆分简单明了,拆分规则明白;
◆ 应用程序模块清晰明白,整合easy。
◆ 数据维护方便易行,easy定位。
垂直切分的缺点
◆ 部分表关联无法在数据库级别完毕。须要在程序中完毕。
◆ 对于訪问极其频繁且数据量超大的表仍然存在性能平静,不一定能满足要求。
◆ 事务处理相对更为复杂;
◆ 切分达到一定程度之后,扩展性会遇到限制;
◆ 过读切分可能会带来系统过渡复杂而难以维护。
针对于垂直切分可能遇到数据切分及事务问题,在数据库层面实在是非常难找到一个较好的处理方案。实际应用案例中,数据库的垂直切分大多是与应用系统的模块相对应,同一个模块的数据源存放于同一个数据库中,能够解决模块内部的数据关联问题。而模块与模块之间,则通过应用程序以服务接口方式来相互提供所须要的数据。
尽管这样做在数据库的总体操作次数方面确实会有所添加,可是在系统总体扩展性以及架构模块化方面,都是故意的。可能在某些操作的单次响应时间会稍有添加。可是系统的总体性能非常可能反而会有一定的提升。而扩展瓶颈问题。就仅仅能依靠下一节将要介绍的数据水平切分架构来攻克了。
数据的水平切分
上面一节分析介绍了数据的垂直切分,这一节再分析一下数据的水平切分。数据的垂直切分基本上能够简单的理解为依照表依照模块来切分数据,而水平切分就不再是依照表或者是功能模块来切分了。一般来说,简单的水平切分主要是将某个訪问极其平庸的表再依照某个字段的某种规则来分散到多个表之中。每一个表中包括一部分数据。
简单来说。我们能够将数据的水平切分理解为是依照数据行的切分。就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其它的数据库中。当然,为了能够比較easy的判定各行数据被切分到哪个数据库中了,切分总是都须要依照某种特定的规则来进行的。
如依据某个数字类型字段基于特定数目取模,某个时间类型字段的范围。或者是某个字符类型字段的hash值。假设整个系统中大部分核心表都能够通过某个字段来进行关联。那这个字段自然是一个进行水平分区的上上之选了,当然,非常特殊无法使用就仅仅能另选其它了。
一般来说,像如今互联网非常火爆的Web2.0类型的站点。基本上大部分数据都能够通过会员用户信息关联上,可能非常多核心表都非常适合通过会员ID来进行数据的水平切分。
而像论坛社区讨论系统。就更easy切分了,非常easy依照论坛编号来进行数据的水平切分。
切分之后基本上不会出现各个库之间的交互。
如我们的演示样例系统。全部数据都是和用户关联的。那么我们就能够依据用户来进行水平拆分,将不同用户的数据切分到不同的数据库中。当然,唯一有点差别的是用户模块中的groups