1,水平拆分的介绍
一般来说,简单的水平切分主要是将某个访问极其平凡的表再按照某个字段的某种规则来分散到多个表之中,每个表中包含一部分数据。
简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中。当然,为了能够比较容易的判定各行数据被切分到哪个数据库中了,切分总是都需要按照某种特定的规则来进行的。
如根据某个数字类型字段基于特定数目取模,某个时间类型字段的范围,或者是某个字符类型字段的hash 值。如果整个系统中大部分核心表都可以通过某个字段来进行关联,那这个字段自然是一个进行水平分区的上上之选了,当然,非常特殊无法使用就只能另选其他了。
水平拆分的优点:
◆表关联基本能够在数据库端全部完成;
◆不会存在某些超大型数据量和高负载的表遇到瓶颈的问题;
◆应用程序端整体架构改动相对较少;
◆事务处理相对简单;
◆只要切分规则能够定义好,基本上较难遇到扩展性限制;
水平切分的缺点:
◆切分规则相对更为复杂,很难抽象出一个能够满足整个数据库的切分规则;
◆后期数据的维护难度有所增加,人为手工定位数据更困难;
◆应用系统各模块耦合度较高,可能会对后面数据的迁移拆分造成一定的困难。
一般来说,像现在互联网非常火爆的互联网公司,特别是电商和游戏业务,基本上大部分数据都能够通过会员用户信息关联上,可能很多核心表都非常适合通过会员ID 来进行数据的水平切分。 而像论坛社区讨论系统,就更容易切分了,非常容易按照论坛编号来进行数据的水平切分。
切分之后基本上不会出现各个库之间的交互。
所以,对于我们的示例数据库来说,大部分的表都可以根据用户ID 来进行水平的切分。
不同用户相关的数据进行切分之后存放在不同的数据库中。如将所有用户ID 通过5取模然后分别存放于两个不同的数据库中。每个和用户ID 关联上的表都可以这样切分。这样, 基本上每个用户相关的数据,都在同一个数据库中,即使是需要关联,也可以非常简单的关
联上。
比如全国划分为10大片区,江浙沪算一哥,齐鲁算一个,两广算一个,两湖算一个,中原算一个,西南算一个,内蒙一个,东北一个,西北一个,华北一个,东南一个。
在业务量比较大的华北、东南、江浙沪、两广片区的服务器可以分配较多的服务器资源,比如cpu、io、网络等等可以用比较好的高端配置。
在业务量正常的西北、齐鲁、两湖、东北的服务器可以分配中高端的服务器资源。
在业务量比较少的,西南、内蒙、中原的服务器可以稍微一般服务器即可。
当然这些资源划分不能对外明示,我们在做内部规划的时候考虑好就可以了,免得被人诟病说有所偏颇不重视之类的。
PS:这种划分不是定性的,根据业务可以随时将业务好的片区的资源升级。
如下图所示:
在实施数据切分方案之前,有些可能存在的问题我们还是需要做一些分析的。一般来说,
我们可能遇到的问题主要会有以下几点:
◆引入分布式事务的问题;
◆跨节点Join 的问题;
◆跨节点合并排序分页问题;
一旦数据进行切分被分别存放在多个MySQL Server 中之后,不管我们的切分规则设计的多么的完美(实际上并不存在完美的切分规则),都可能造成之前的某些事务所涉及到的数据已经不在同一个MySQL Server 中了。
在这样的场景下,如果我们的应用程序仍然按照老的解决方案,那么势必需要引入分布式事务来解决。而在MySQL 各个版本中,只有从MySQL 5.0 开始以后的各个版本才开始对分布式事务提供支持,而且目前仅有Innodb 提供分布式事务支持。不仅如此,即使我们刚好使用了支持分布式事务的MySQL 版本,同时也是使用的Innodb 存储引擎,分布式事务本身对于系统资源的消耗就是很大的,性能本身也并不是太高。而且引入分布式事务本身在异常处理方面就会带来较多比较难控制的因素。
怎么办?其实我们可以可以通过一个变通的方法来解决这种问题,首先需要考虑的一件事情就是:是否数据库是唯一一个能够解决事务的地方呢?其实并不是这样的,我们完全可以结合数据库以及应用程序两者来共同解决。各个数据库解决自己身上的事务,然后通过应用程序来控制多个数据库上面的事务。
也就是说,只要我们愿意,完全可以将一个跨多个数据库的分布式事务分拆成多个仅处于单个数据库上面的小事务,并通过应用程序来总控各个小事务。当然,这样作的要求就是我们的俄应用程序必须要有足够的健壮性,当然也会给应用程序带来一些技术难度。