一:基本思想java
Sharding的基本思想就要把一个数据库切分红多个部分放到不一样的数据库(server)上,从而缓解单一数据库的性能问题。不太严格的讲,对于海量数据的数据库,若是是由于表多而数据多,这时候适合使用垂直切分,即把关系紧密(好比同一模块)的表切分出来放在一个server上。若是表并很少,但每张表的数据很是多,这时候适合水平切分,即把表的数据按某种规则(好比按ID散列)切分到多个数据库(server)上。固然,现实中更可能是这两种状况混杂在一块儿,这时候须要根据实际状况作出选择,也可能会综合使用垂直与水平切分,从而将原有数据库切分红相似矩阵同样能够无限扩充的数据库(server)阵列。下面分别详细地介绍一下垂直切分和水平切分.
垂直切分的最大特色就是规则简单,实施也更为方便,尤为适合各业务之间的耦合度很是低,相互影响很小,业务逻辑很是清晰的系统。在这种系统中,能够很容易作到将不一样业务模块所使用的表分拆到不一样的数据库中。根据不一样的表来进行拆分,对应用程序的影响也更小,拆分规则也会比较简单清晰。(这也就是所谓的”share nothing”)。mysql
水平切分于垂直切分相比,相对来讲稍微复杂一些。由于要将同一个表中的不一样数据拆
分到不一样的数据库中,对于应用程序来讲,拆分规则自己就较根据表名来拆分更为复杂,后
期的数据维护也会更为复杂一些。spring
让咱们从广泛的状况来考虑数据的切分:一方面,一个库的全部表一般不可能由某一张表所有串联起来,这句话暗含的意思是,水平切分几乎都是针对一小搓一小搓(实际上就是垂直切分出来的块)关系紧密的表进行的,而不多是针对全部表进行的。另外一方面,一些负载很是高的系统,即便仅仅只是单个表都没法经过单台数据库主机来承担其负载,这意味着单单是垂直切分也不能彻底解决问明。所以多数系统会将垂直切分和水平切分联合使用,先对系统作垂直切分,再针对每一小搓表的状况选择性地作水平切分。从而将整个数据库切分红一个分布式矩阵。sql
2、切分策略数据库
如前面所提到的,切分是按先垂直切分再水平切分的步骤进行的。垂直切分的结果正好为水平切分作好了铺垫。垂直切分的思路就是分析表间的聚合关系,把关系紧密的表放在一块儿。多数状况下多是同一个模块,或者是同一“汇集”。这里的“汇集”正是领域驱动设计里所说的汇集。在垂直切分出的表汇集内,找出“根元素”(这里的“根元素”就是领域驱动设计里的“聚合根”),按“根元素”进行水平切分,也就是从“根元素”开始,把全部和它直接与间接关联的数据放入一个shard里。这样出现跨shard关联的可能性就很是的小。应用程序就没必要打断既有的表间关联。好比:对于社交网站,几乎全部数据最终都会关联到某个用户上,基于用户进行切分就是最好的选择。再好比论坛系统,用户和论坛两个模块应该在垂直切分时被分在了两个shard里,对于论坛模块来讲,Forum显然是聚合根,所以按Forum进行水平切分,把Forum里全部的帖子和回帖都随Forum放在一个shard里是很天然的。
对于共享数据数据,若是是只读的字典表,每一个shard里维护一份应该是一个不错的选择,这样没必要打断关联关系。若是是通常数据间的跨节点的关联,就必须打断。服务器
须要特别说明的是:当同时进行垂直和水平切分时,切分策略会发生一些微妙的变化。好比:在只考虑垂直切分的时候,被划分到一块儿的表之间能够保持任意的关联关系,所以你能够按“功能模块”划分表格,可是一旦引入水平切分以后,表间关联关系就会受到很大的制约,一般只能容许一个主表(以该表ID进行散列的表)和其多个次表之间保留关联关系,也就是说:当同时进行垂直和水平切分时,在垂直方向上的切分将再也不以“功能模块”进行划分,而是须要更加细粒度的垂直切分,而这个粒度与领域驱动设计中的“聚合”概念不谋而合,甚至能够说是彻底一致,每一个shard的主表正是一个聚合中的聚合根!这样切分下来你会发现数据库分被切分地过于分散了(shard的数量会比较多,可是shard里的表却很少),为了不管理过多的数据源,充分利用每个数据库服务器的资源,能够考虑将业务上相近,而且具备相近数据增加速率(主表数据量在同一数量级上)的两个或多个shard放到同一个数据源里,每一个shard依然是独立的,它们有各自的主表,并使用各自主表ID进行散列,不一样的只是它们的散列取模(即节点数量)必需是一致的。(架构
本文着重介绍sharding的基本思想和理论上的切分策略,关于更加细致的实施策略和参考事例请参考个人另外一篇博文:数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示 分布式
)函数
1.事务问题:
解决事务问题目前有两种可行的方案:分布式事务和经过应用程序与数据库共同控制实现事务下面对两套方案进行一个简单的对比。
方案一:使用分布式事务
优势:交由数据库管理,简单有效
缺点:性能代价高,特别是shard愈来愈多时
方案二:由应用程序和数据库共同控制
原理:将一个跨多个数据库的分布式事务分拆成多个仅处
于单个数据库上面的小事务,并经过应用程序来总控
各个小事务。
优势:性能上有优点
缺点:须要应用程序在事务控制上作灵活设计。若是使用
了spring的事务管理,改动起来会面临必定的困难。
2.跨节点Join的问题
只要是进行切分,跨节点Join的问题是不可避免的。可是良好的设计和切分却能够减小此类状况的发生。解决这一问题的广泛作法是分两次查询实现。在第一次查询的结果集中找出关联数据的id,根据这些id发起第二次请求获得关联数据。
3.跨节点的count,order by,group by以及聚合函数问题
这些是一类问题,由于它们都须要基于所有数据集合进行计算。多数的代理都不会自动处理合并工做。解决方案:与解决跨节点join问题的相似,分别在各个节点上获得结果后在应用程序端进行合并。和join不一样的是每一个结点的查询能够并行执行,所以不少时候它的速度要比单一大表快不少。但若是结果集很大,对应用程序内存的消耗是一个问题。性能
参考资料: