zoukankan      html  css  js  c++  java
  • 数据库Sharding的基本思想和切分策略

    转自:http://blog.csdn.net/bluishglc/article/details/6161475


    本文着重介绍sharding的基本思想和理论上的切分策略。关于更加仔细的实施策略和參考事例请參考我的还有一篇博文:数据库分库分表(sharding)系列(一) 拆分实施策略和演示样例演示 


    一、基本思想

          Sharding的基本思想就要把一个数据库切分成多个部分放到不同的数据库(server)上,从而缓解单一数据库的性能问题。

    不太严格的讲。对于海量数据的数据库,假设是由于表多而数据多,这时候适合使用垂直切分,即把关系紧密(比方同一模块)的表切分出来放在一个server上。假设表并不多。但每张表的数据很多。这时候适合水平切分,即把表的数据按某种规则(比方按ID散列)切分到多个数据库(server)上。

    当然。现实中很多其它是这两种情况混杂在一起,这时候须要依据实际情况做出选择。也可能会综合使用垂直与水平切分。从而将原有数据库切分成类似矩阵一样能够无限扩充的数据库(server)阵列。以下分别具体地介绍一下垂直切分和水平切分.

          垂直切分的最大特点就是规则简单,实施也更为方便,尤其适合各业务之间的耦合度非
    常低,相互影响非常小,业务逻辑非常清晰的系统。在这样的系统中,能够非常easy做到将不同业
    务模块所使用的表分拆到不同的数据库中。依据不同的表来进行拆分,相应用程序的影响也
    更小。拆分规则也会比較简单清晰。(这也就是所谓的”share nothing”)。



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



          让我们从普遍的情况来考虑数据的切分:一方面,一个库的全部表通常不可能由某一张表全部串联起来,这句话暗含的意思是,水平切分差点儿都是针对一小搓一小搓(实际上就是垂直切分出来的块)关系紧密的表进行的,而不可能是针对全部表进行的。还有一方面,一些负载很高的系统,即使只不过单个表都无法通过单台数据库主机来承担其负载,这意味着单单是垂直切分也不能全然解决问明。因此多数系统会将垂直切分和水平切分联合使用,先对系统做垂直切分,再针对每一小搓表的情况选择性地做水平切分。

    从而将整个数据库切分成一个分布式矩阵。

     

    二、切分策略

          如前面所提到的,切分是按先垂直切分再水平切分的步骤进行的。垂直切分的结果正好为水平切分做好了铺垫。垂直切分的思路就是分析表间的聚合关系,把关系紧密的表放在一起。

    多数情况下可能是同一个模块,或者是同一“聚集”。这里的“聚集”正是领域驱动设计里所说的聚集。

    在垂直切分出的表聚集内,找出“根元素”(这里的“根元素”就是领域驱动设计里的“聚合根”),按“根元素”进行水平切分。也就是从“根元素”開始。把全部和它直接与间接关联的数据放入一个shard里。

    这样出现跨shard关联的可能性就非常的小。应用程序就不必打断既有的表间关联。比方:对于社交站点。差点儿全部数据终于都会关联到某个用户上,基于用户进行切分就是最好的选择。再比方论坛系统,用户和论坛两个模块应该在垂直切分时被分在了两个shard里,对于论坛模块来说,Forum显然是聚合根,因此按Forum进行水平切分,把Forum里全部的帖子和回帖都随Forum放在一个shard里是非常自然的。



          对于共享数据数据,假设是仅仅读的字典表,每一个shard里维护一份应该是一个不错的选择。这样不必打断关联关系。假设是一般数据间的跨节点的关联,就必须打断。


          须要特别说明的是:当同一时候进行垂直和水平切分时。切分策略会发生一些微妙的变化。比方:在仅仅考虑垂直切分的时候,被划分到一起的表之间能够保持随意的关联关系,因此你能够按“功能模块”划分表格,可是一旦引入水平切分之后,表间关联关系就会受到非常大的制约,通常仅仅能同意一个主表(以该表ID进行散列的表)和其多个次表之间保留关联关系,也就是说:当同一时候进行垂直和水平切分时,在垂直方向上的切分将不再以“功能模块”进行划分,而是须要更加细粒度的垂直切分,而这个粒度与领域驱动设计中的“聚合”概念不谋而合。甚至能够说是全然一致,每一个shard的主表正是一个聚合中的聚合根!

    这样切分下来你会发现数据库分被切分地过于分散了(shard的数量会比較多,可是shard里的表却不多),为了避免管理过多的数据源,充分利用每一个数据库server的资源。能够考虑将业务上相近,而且具有相近数据增长速率(主表数据量在同一数量级上)的两个或多个shard放到同一个数据源里。每一个shard依旧是独立的,它们有各自的主表。并使用各自主表ID进行散列,不同的仅仅是它们的散列取模(即节点数量)必需是一致的。(

    本文着重介绍sharding的基本思想和理论上的切分策略,关于更加仔细的实施策略和參考事例请參考我的还有一篇博文:数据库分库分表(sharding)系列(一) 拆分实施策略和演示样例演示 



    1.事务问题:
    解决事务问题眼下有两种可行的方案:分布式事务和通过应用程序与数据库共同控制实现事务以下对两套方案进行一个简单的对照。
    方案一:使用分布式事务
        长处:交由数据库管理,简单有效
        缺点:性能代价高。特别是shard越来越多时
    方案二:由应用程序和数据库共同控制
         原理:将一个跨多个数据库的分布式事务分拆成多个仅处
               于单个数据库上面的小事务,并通过应用程序来总控
               各个小事务。
         长处:性能上有优势
         缺点:须要应用程序在事务控制上做灵活设计。假设使用   
               了spring的事务管理,修改起来会面临一定的困难。
    2.跨节点Join的问题
          仅仅要是进行切分。跨节点Join的问题是不可避免的。可是良好的设计和切分却能够降低此类情况的发生。

    解决这一问题的普遍做法是分两次查询实现。在第一次查询的结果集中找出关联数据的id,依据这些id发起第二次请求得到关联数据。

    3.跨节点的count,order by,group by以及聚合函数问题
          这些是一类问题,由于它们都须要基于所有数据集合进行计算。多数的代理都不会自己主动处理合并工作。解决方式:与解决跨节点join问题的类似。分别在各个节点上得到结果后在应用程序端进行合并。

    和join不同的是每一个结点的查询能够并行运行。因此非常多时候它的速度要比单一大表快非常多。

    但假设结果集非常大,相应用程序内存的消耗是一个问题。


    參考资料:

    《MySQL性能调优与架构设计》


    注:本文图片摘自《MySQL性能调优与架构设计》一 书



    相关阅读:

    数据库分库分表(sharding)系列(五) 一种支持自由规划无须数据迁移和改动路由代码的Sharding扩容方案

    数据库分库分表(sharding)系列(四) 多数据源的事务处理

    数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量

    数据库分库分表(sharding)系列(二) 全局主键生成策略

    数据库分库分表(sharding)系列(一) 拆分实施策略和演示样例演示

    关于垂直切分Vertical Sharding的粒度

    数据库Sharding的基本思想和切分策略

  • 相关阅读:
    QT 主窗口和子窗口相互切换示例
    《漫画线性代数》读书笔记 通读小结
    “网购懊悔权”为何与“机动车撞人负全责”一样扯淡?
    第十六周oj刷题——Problem J: 填空题:静态成员---计算学生个数
    HDU 1269 迷宫城堡(强连通)
    HashSet的排序
    android:改动PagerTabStrip中的背景颜色,标题字体的样式、颜色和图标以及指示条的颜色
    Spring中的FactoryBean
    免费APP在线測试工具以及其用法
    freemarker的TemplateExceptionHandler使用
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/7217193.html
Copyright © 2011-2022 走看看