什么是分布式

  • 222013-10

    简单说,分布式是以缩短单个任务的执行时间来提高效率的,而集群则是经过提升单位时间内执行的任务数来提高效率。html

    例如:java

    若是一个任务由10个子任务组成,每一个子任务单独执行需1小时,则在一台服务器上执行改任务需10小时。mysql

    采用分布式方案,提供10台服务器,每台服务器只负责处理一个子任务,不考虑子任务间的依赖关系,执行完这个任务只需一个小时。(这种工做模式的一个典型表明就是Hadoop的Map/Reduce分布式计算模型)linux

    而采用集群方案,一样提供10台服务器,每台服务器都能独立处理这个任务。假设有10个任务同时到达,10个服务器将同时工做,10小后,10个任务同时完成,这样,整身来看,仍是1小时内完成一个任务!nginx

     

    如下是摘抄自网络文章:程序员

    集群概念

    1. 两大关键特性 
    集群是一组协同工做的服务实体,用以提供比单一服务实体更具扩展性与可用性的服务平台。在客户端看来,一个集群就象是一个服务实体,但事实上集群由一组服务实体组成。与单一服务实体相比较,集群提供了如下两个关键特性:web

    ·  可扩展性--集群的性能不限于单一的服务实体,新的服务实体能够动态地加入到集群,从而加强集群的性能。算法

    ·  高可用性--集群经过服务实体冗余使客户端免于轻易遇到out of service的警告。在集群中,一样的服务能够由多个服务实体提供。若是一个服务实体失败了,另外一个服务实体会接管失败的服务实体。集群提供的从一个出 错的服务实体恢复到另外一个服务实体的功能加强了应用的可用性。sql

    2. 两大能力 
    为了具备可扩展性和高可用性特色,集群的必须具有如下两大能力:shell

    ·  负载均衡--负载均衡能把任务比较均衡地分布到集群环境下的计算和网络资源。

    ·  错误恢复--因为某种缘由,执行某个任务的资源出现故障,另外一服务实体中执行同一任务的资源接着完成任务。这种因为一个实体中的资源不能工做,另外一个实体中的资源透明的继续完成任务的过程叫错误恢复。

    负载均衡和错误恢复都要求各服务实体中有执行同一任务的资源存在,并且对于同一任务的各个资源来讲,执行任务所需的信息视图(信息上下文)必须是同样的。

    3. 两大技术 
    实现集群务必要有如下两大技术:

    ·  集群地址--集群由多个服务实体组成,集群客户端经过访问集群的集群地址获取集群内部各服务实体的功能。具备单一集群地址(也叫单一影像)是集群的一个基 本特征。维护集群地址的设置被称为负载均衡器。负载均衡器内部负责管理各个服务实体的加入和退出,外部负责集群地址向内部服务实体地址的转换。有的负载均 衡器实现真正的负载均衡算法,有的只支持任务的转换。只实现任务转换的负载均衡器适用于支持ACTIVE-STANDBY的集群环境,在那里,集群中只有 一个服务实体工做,当正在工做的服务实体发生故障时,负载均衡器把后来的任务转向另一个服务实体。

    ·  内部通讯--为了能协同工做、实现负载均衡和错误恢复,集群各实体间必须时常通讯,好比负载均衡器对服务实体心跳测试信息、服务实体间任务执行上下文信息的通讯。

    具备同一个集群地址使得客户端能访问集群提供的计算服务,一个集群地址下隐藏了各个服务实体的内部地址,使得客户要求的计算服务能在各个服务实体之间分布。内部通讯是集群能正常运转的基础,它使得集群具备均衡负载和错误恢复的能力。

    集群分类

    Linux集群主要分红三大类( 高可用集群, 负载均衡集群,科学计算集群)

    高可用集群( High Availability Cluster)
    负载均衡集群(Load Balance Cluster)
    科学计算集群(High Performance Computing Cluster)
    ================================================

    具体包括:

    Linux High Availability 高可用集群                                       
    (普通两节点双机热备,多节点HA集群,RAC, shared, share-nothing集群等)

    Linux Load Balance 负载均衡集群                                      
     (LVS等....)

    Linux High Performance Computing 高性能科学计算集群     
     (Beowulf 类集群....)

    分布式存储                                                                         
    其余类linux集群              
    (如Openmosix, rendering farm 等..)

    详细介绍

    1. 高可用集群(High Availability Cluster)
    常见的就是2个节点作成的HA集群,有不少通俗的不科学的名称,好比"双机热备", "双机互备", "双机".
    高可用集群解决的是保障用户的应用程序持续对外提供服务的能力。 (请注意高可用集群既不是用来保护业务数据的,保护的是用户的业务程序对外不间断提供服务,把因软件/硬件/人为形成的故障对业务的影响下降到最小程度)。

    2. 负载均衡集群(Load Balance Cluster)

    负载均衡系统:集群中全部的节点都处于活动状态,它们分摊系统的工做负载。通常Web服务器集群、数据库集群和应用服务器集群都属于这种类型。

    负载均衡集群通常用于相应网络请求的网页服务器,数据库服务器。这种集群能够在接到请求时,检查接受请求较少,不繁忙的服务器,并把请求转到这些服务器上。从检查其余服务器状态这一点上看,负载均衡和容错集群很接近,不一样之处是数量上更多。

    3. 科学计算集群(High Performance Computing Cluster)

    高性能计算(High Perfermance Computing)集群,简称HPC集群。这类集群致力于提供单个计算机所不能提供的强大的计算能力。

    高性能计算分类  
     高吞吐计算(High-throughput Computing)
      有一类高性能计算,能够把它分红若干能够并行的子任务,并且各个子任务彼此间没有什么关联。象在家搜寻外星人( SETI@HOME  -- Search for Extraterrestrial Intelligence at Home )就是这一类型应用。这一项目是利用Internet上的闲置的计算资源来搜寻外星人。SETI项目的服务器将一组数据和数据模式发给Internet上 参加SETI的计算节点,计算节点在给定的数据上用给定的模式进行搜索,而后将搜索的结果发给服务器。服务器负责将从各个计算节点返回的数据聚集成完整的 数据。由于这种类型应用的一个共同特征是在海量数据上搜索某些模式,因此把这类计算称为高吞吐计算。所谓的Internet计算都属于这一类。按照 Flynn的分类,高吞吐计算属于SIMD(Single Instruction/Multiple Data)的范畴。

     分布计算(Distributed Computing)
      另外一类计算恰好和高吞吐计算相反,它们虽然能够给分红若干并行的子任务,可是子任务间联系很紧密,须要大量的数据交换。按照Flynn的分类,分布式的高性能计算属于MIMD(Multiple Instruction/Multiple Data)的范畴。

    4. 分布式(集群)与集群的联系与区别 
    分布式是指将不一样的业务分布在不一样的地方。 
    而集群指的是将几台服务器集中在一块儿,实现同一业务。 
    分布式中的每个节点,均可以作集群。 
    而集群并不必定就是分布式的。 
    举例:就好比新浪网,访问的人多了,他能够作一个群集,前面放一个响应服务器,后面几台服务器完成同一业务,若是有业务访问的时候,响应服务器看哪台服务器的负载不是很重,就将给哪一台去完成。 
    而分布式,从窄意上理解,也跟集群差很少, 可是它的组织比较松散,不像集群,有一个组织性,一台服务器垮了,其它的服务器能够顶上来。 
    分布式的每个节点,都完成不一样的业务,一个节点垮了,哪这个业务就不可访问了。

    发布于 2个月前, 阅读(16) | 评论(0) | 投票(0) | 收藏(0)  阅读全文...
  • 162013-10

    一致性hash和solr千万级数据分布式搜索引擎中的应用

    互联网创业中大部分人都是草根创业,这个时候没有强劲的服务器,也没有钱去买很昂贵的海量数据库。在这样严峻的条件下,一批又一批的创业者从创业中得到成功,这个和当前的开源技术、海量数据架构有着必不可分的关系。好比咱们使用mysql、nginx等开源软件,经过架构和低成本服务器也能够搭建千万级用户访问量的系统。新浪微博、淘宝网、腾讯等大型互联网公司都使用了不少开源免费系统搭建了他们的平台。因此,用什么不要紧,只要可以在合理的状况下采用合理的解决方案。

    那怎么搭建一个好的系统架构呢?这个话题太大,这里主要说一下数据分流的方式。好比咱们的数据库服务器只能存储200个数据,忽然要搞一个活动预估达到600个数据。
    能够采用两种方式:横向扩展或者纵向扩展。
    纵向扩展是升级服务器的硬件资源。可是随着机器的性能配置越高,价格越高,这个代价对于通常的小公司是承担不起的。
    横向扩展是采用多个廉价的机器提供服务。这样一个机器只能处理200个数据、3个机器就能够处理600个数据了,若是之后业务量增长还能够快速配置增长。在大多数状况都选择横向扩展的方式。以下图:
    图1

    图2

    如今有个问题了,这600个数据如何路由到对应的机器。须要考虑若是均衡分配,假设咱们600个数据都是统一的自增id数据,从1~600,分红3堆能够采用 id mod 3的方式。其实在真实环境可能不是这种id是字符串。须要把字符串转变为hashcode再进行取模。

    目前看起来是否是解决咱们的问题了,全部数据都很好的分发而且没有达到系统的负载。但若是咱们的数据须要存储、须要读取就没有这么容易了。业务增多怎么办,你们按照上面的横向扩展知道须要增长一台服务器。可是就是由于增长这一台服务器带来了一些问题。看下面这个例子,一共9个数,须要放到2台机器(一、2)上。各个机器存放为:1号机器存放一、三、五、七、9 ,2号机器存放 二、四、六、8。若是扩展一台机器3如何,数据就要发生大迁移,1号机器存放一、四、7, 2号机器存放二、五、8, 3号机器存放三、六、9。如图:

    图3
    从图中能够看出 1号机器的三、五、9迁移出去了、2好机器的四、6迁移出去了,按照新的秩序再从新分配了一遍。数据量小的话从新分配一遍代价并不大,但若是咱们拥有上亿、上T级的数据这个操做成本是至关的高,少则几个小时多则数天。而且迁移的时候原数据库机器负载比较高,那你们就有疑问了,是否是这种水平扩展的架构方式不太合理?

    —————————–华丽分割线—————————————

    一致性hash就是在这种应用背景提出来的,如今被普遍应用于分布式缓存,好比memcached。下面简单介绍下一致性hash的基本原理。最先的版本 http://dl.acm.org/citation.cfm?id=258660。国内网上有不少文章都写的比较好。如: http://blog.csdn.net/x15594/article/details/6270242

    下面简单举个例子来讲明一致性hash。

    准备:一、二、3 三台机器
    还有待分配的9个数 一、二、三、四、五、六、七、八、9
    一致性hash算法架构

    步骤
    1、构造出来 2的32次方 个虚拟节点出来,由于计算机里面是01的世界,进行划分时采用2的次方数据容易分配均衡。另 2的32次方是42亿,咱们就算有超大量的服务器也不可能超过42亿台吧,扩展和均衡性都保证了。
    一致性hash
    2、将三台机器分别取IP进行hashcode计算(这里也能够取hostname,只要可以惟一区别各个机器就能够了),而后映射到2的32次方上去。好比1号机器算出来的hashcode而且mod (2^32)为 123(这个是虚构的),2号机器算出来的值为 2300420,3号机器算出来为 90203920。这样三台机器就映射到了这个虚拟的42亿环形结构的节点上了。
    图5
    3、将数据(1-9)也用一样的方法算出hashcode并对42亿取模将其配置到环形节点上。假设这几个节点算出来的值为 1:10,2:23564,3:57,4:6984,5:5689632,6:86546845,7:122,8:3300689,9:135468。能够看出 一、三、7小于123, 二、四、9 小于 2300420 大于 123, 五、六、8 大于 2300420 小于90203920。从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个Cache节点上。若是超过2^32仍然找不到Cache节点,就会保存到第一个Cache节点上。也就是一、三、7将分配到1号机器,二、四、9将分配到2号机器,五、六、8将分配到3号机器。
    图6
    这个时候你们可能会问,我到如今没有看见一致性hash带来任何好处,比传统的取模还增长了复杂度。如今立刻来作一些关键性的处理,好比咱们增长一台机器。按照原来咱们须要把全部的数据从新分配到四台机器。一致性hash怎么作呢?如今4号机器加进来,他的hash值算出来取模后是12302012。 五、8 大于2300420 小于12302012 ,6 大于 12302012 小于90203920 。这样调整的只是把五、8从3号机器删除,4号机器中加入 五、6。
    图7
    同理,删除机器怎么作呢,假设2号机器挂掉,受影响的也只是2号机器上的数据被迁移到离它节点,上图为4号机器。
    图8
    你们应该明白一致性hash的基本原理了吧。不过这种算法仍是有缺陷,好比在机器节点比较少、数据量大的时候,数据的分布可能不是很均衡,就会致使其中一台服务器的数据比其余机器多不少。为了解决这个问题,须要引入虚拟服务器节点的机制。如咱们一共有只有三台机器,一、二、3。可是实际又不可能有这么多机器怎么解决呢?把 这些机器各自虚拟化出来3台机器,也就是 1a 1b 1c 2a 2b 2c 3a 3b 3c,这样就变成了9台机器。实际 1a 1b 1c 仍是对应1。可是实际分布到环形节点就变成了9台机器。数据分布也就可以更分散一点。如图:
    图91

    写了这么多一致性hash,这个和分布式搜索有什么半点关系?咱们如今使用solr4搭建了分布式搜索,测试了基于solrcloud的分布式平台提交20条数据竟然须要几十秒,因此就废弃了solrcloud。采用本身hack solr平台,不用zookeeper作分布式一致性管理平台,本身管理数据的分发机制。既然须要本身管理数据的分发,就须要考虑到索引的建立,索引的更新。这样咱们的一致性hash也就用上了。总体架构以下图:

    图10
    创建和更新须要维持机器的位置,可以根据数据的key找到对应的数据分发并更新。这里须要考虑的是如何高效、可靠的把数据创建、更新到索引里。
    备份服务器防止创建服务器挂掉,能够根据备份服务器快速恢复。
    读服务器主要作读写分离使用,防止写索引影响查询数据。
    集群管理服务器管理整个集群内的服务器状态、告警。

    整个集群随着业务增多还能够按照数据的类型划分,好比用户、微博等。每一个类型按照上图架构搭建,就能够知足通常性能的分布式搜索。对于solr和分布式搜索的话题后续再聊。

    扩展阅读:
    java的hashmap随着数据量的增长也会出现map调整的问题,必要的时候就初始化足够大的size以防止容量不足对已有数据进行从新hash计算。

    疫苗:Java HashMap的死循环 http://coolshell.cn/articles/9606.html
    一致性哈希算法的优化—-关于如何保正在环中增长新节点时,命中率不受影响 (原拍拍同事scott)http://scottina.iteye.com/blog/650380

    语言实现:
    http://weblogs.java.net/blog/2007/11/27/consistent-hashing java 版本的例子
    http://blog.csdn.net/mayongzhan/archive/2009/06/25/4298834.aspx PHP 版的例子
    http://www.codeproject.com/KB/recipes/lib-conhash.aspx C语言版本例子

    发布于 3个月前, 阅读(150) | 评论(1) | 投票(0) | 收藏(21)  阅读全文...
  • 162013-10

    1)首先在${tomcat目录}/conf/Catalina/localhost 建立两个solr的配置文件。

       能够命名为solr.xml(主服务器配置)内容为:

     <Context docBase="F:/apache-solr-1.4.0/dist/apache-solr-1.4.0.war" reloadable="true" >  
         <Environment name="solr/home" type="java.lang.String" value="F:/apache-solr-1.4.0/example/solr" override="true" />  
     </Context> 

    slaver_solr.xml (从服务器配置)内容为:

     <Context docBase="F:/apache-solr-1.4.0/dist/apache-solr-1.4.0.war" reloadable="true" >  
         <Environment name="solr/home" type="java.lang.String" value="F:/solr分布式/solr" override="true" />  
     </Context> 

     

    能够看到两个配置所引用的后台管理是同一个目录的,但这个不要紧,只要solr/home的不同就好了,接着看主从服务器上solr/home的配置有什么不同。主要是在solr/home/conf/solrconfig.xml上配置不同的,其它配置能够互相拷贝。

     

    主要不一样的地方为以下:

     

    从服务器的配置

     

    <requestHandler name="/replication" class="solr.ReplicationHandler" >
        <lst name="slave">

    <!--主服务器的url-->


          <str name="masterUrl">http://localhost:8080/solr/replication</str>

    <!--定时去请求主服务器,查看索引是否有改变-->
          <str name="pollInterval">00:00:60</str>
        </lst>
    </requestHandler>

     

    主服务器的配置

     


    <requestHandler name="/replication" class="solr.ReplicationHandler" >
        <lst name="master">
          <str name="replicateAfter">commit</str>
          <str name="replicateAfter">startup</str>
          <str name="confFiles">schema.xml,stopwords.txt</str>
        </lst>

    </requestHandler>

     

    大概这样的。启动 tomcat看看吧。。主服务器创建索引后,从服务器会请求将索引拷贝到从服务器中。

    发布于 3个月前, 阅读(54) | 评论(0) | 投票(0) | 收藏(0)  阅读全文...
  • 162013-04
    时间过得很快,来淘宝已经两个月了,在这两个月的时间里,本身也感觉颇深。下面就结合淘宝目前的一些底层技术框架以及本身的一些感触来讲说如何构建一个可伸缩,高性能,高可用性的分布式互联网应用。

      一应用无状态淘宝session框架

      俗话说,一个系统的伸缩性的好坏取决于应用的状态如何管理。为何这么说呢?我们试想一下,假如咱们在session中保存了大量与客户端的状态信息的话,那么当保存状态信息的server宕机的时候,咱们怎么办?一般来讲,咱们都是经过集群来解决这个问题,而一般所说的集群,不只有负载均衡,更重要的是要有失效恢复failover,好比tomcat采用的集群节点广播复制,jboss采用的配对复制等session状态复制策略,可是集群中的状态恢复也有其缺点,那就是严重影响了系统的伸缩性,系统不能经过增长更多的机器来达到良好的水平伸缩,由于集群节点间session的通讯会随着节点的增多而开销增大,所以要想作到应用自己的伸缩性,咱们须要保证应用的无状态性,这样集群中的各个节点来讲都是相同的,从而是的系统更好的水平伸缩。

      OK,上面说了无状态的重要性,那么具体如何实现无状态呢?此时一个session框架就会发挥做用了。幸运的是淘宝已经具备了此类框架。淘宝的session框架采用的是client cookie实现,主要将状态保存到了cookie里面,这样就使得应用节点自己不须要保存任何状态信息,这样在系统用户变多的时候,就能够经过增长更多的应用节点来达到水平扩展的目的.可是采用客户端cookie的方式来保存状态也会遇到限制,好比每一个cookie通常不能超过4K的大小,同时不少浏览器都限制一个站点最多保存20个cookie.淘宝cookie框架采用的是“多值cookie”,就是一个组合键对应多个cookie的值,这样不只能够防止cookie数量超过20,同时还节省了cookie存储有效信息的空间,由于默认每一个cookie都会有大约50个字节的元信息来描述cookie。

      除了淘宝目前的session框架的实现方式之外,其实集中式session管理来完成,说具体点就是多个无状态的应用节点链接一个session服务器,session服务器将session保存到缓存中,session服务器后端再配有底层持久性数据源,好比数据库,文件系统等等。

      二有效使用缓存Tair

      作互联网应用的兄弟应该都清楚,缓存对于一个互联网应用是多么的重要,从浏览器缓存,反向代理缓存,页面缓存,局部页面缓存,对象缓存等等都是缓存应用的场景。

      通常来讲缓存根据与应用程序的远近程度不一样能够分为:local cache和remote cache。通常系统中要么采用local cache,要么采用remote cache,二者混合使用的话对于local cache和remote cache的数据一致性处理会变大比较麻烦.

      在大部分状况下,咱们所说到的缓存都是读缓存,缓存还有另一个类型:写缓存.对于一些读写比不高,同时对数据安全性需求不高的数据,咱们能够将其缓存起来从而减小对底层数据库的访问,好比统计商品的访问次数,统计API的调用量等等,能够采用先写内存缓存而后延迟持久化到数据库,这样能够大大减小对数据库的写压力。

      OK,我以店铺线的系统为例,在用户浏览店铺的时候,好比店铺介绍,店铺交流区页,店铺服务条款页面,店铺试衣间页面,以及店铺内搜索界面这些界面更新不是很是频繁,所以适合放到缓存中,这样能够大大减低DB的负载。另外宝贝详情页面相对也更新比较少,所以也适合放到缓存中来减低DB负载。

      三应用拆分HSF

      首先,在说明应用拆分以前,咱们先来回顾一下一个系统从小变大的过程当中遇到的一些问题,经过这些问题咱们会发现拆分对于构建一个大型系统是如何的重要。

      系统刚上线初期,用户数并很少,全部的逻辑也许都是放在一个系统中的,全部逻辑跑到一个进程或者一个应用当中,这个时候由于比较用户少,系统访问量低,所以将所有的逻辑都放在一个应用何尝不可。可是,兄弟们都清楚,好景不长,随着系统用户的不断增长,系统的访问压力愈来愈多,同时随着系统发展,为了知足用户的需求,原有的系统须要增长新的功能进来,系统变得愈来愈复杂的时候,咱们会发现系统变得愈来愈难维护,难扩展,同时系统伸缩性和可用性也会受到影响。那么这个时候咱们如何解决这些问题呢?明智的办法就是拆分这也算是一种解耦,咱们须要将原来的系统根据必定的标准,好比业务相关性等分为不一样的子系统,不一样的系统负责不一样的功能,这样切分之后,咱们能够对单独的子系统进行扩展和维护,从而提升系统的扩展性和可维护性,同时咱们系统的水平伸缩性scale out大大的提高了,由于咱们能够有针对性的对压力大的子系统进行水平扩展而不会影响到其它的子系统,而不会像拆分之前,每次系统压力变大的时候,咱们都须要对整个大系统进行伸缩,而这样的成本是比较大的,另外通过切分,子系统与子系统之间的耦合减低了,当某个子系统暂时不可用的时候,总体系统仍是可用的,从而总体系统的可用性也大大加强了。

      所以一个大型的互联网应用,确定是要通过拆分,由于只有拆分了,系统的扩展性,维护性,伸缩性,可用性才会变的更好。可是拆分也给系统带来了问题,就是子系统之间如何通讯的问题,而具体的通讯方式有哪些呢?通常有同步通讯和异步通讯,这里咱们首先来讲下同步通讯,下面的主题“消息系统”会说到异步通讯。既然须要通讯,这个时候一个高性能的远程调用框架就显得很是总要啦,所以我们淘宝也有了本身的HSF框架。

      上面所说的都是拆分的好处,可是拆分之后必然的也会带来新的问题,除了刚才说的子系统通讯问题外,最值得关注的问题就是系统之间的依赖关系,由于系统多了,系统的依赖关系就会变得复杂,此时就须要更好的去关注拆分标准,好比可否将一些有依赖的系统进行垂直化,使得这些系统的功能尽可能的垂直,这也是目前淘宝正在作的系统垂直化,同时必定要注意系统之间的循环依赖,若是出现循环依赖必定要当心,由于这可能致使系统连锁启动失败。

      OK,既然明白了拆分的重要性,咱们看看随着淘宝的发展,淘宝自己是如何拆分系统的。

      首先咱们来看如下这个图:做者图片已没法打开,请见谅

      从上面的图能够看出淘宝系统的一个演变过程,在这个演变的过程当中,咱们所说的拆分就出现V2.2和V3.0之间。在V2.2版本中,淘宝几乎全部的逻辑都放在Denali系统中,这样致使的问题就是系统扩展和修改很是麻烦,而且更加致命的是随着淘宝业务量的增长,若是按照V2.2的架构已经没有办法支撑之后淘宝的快速发展,所以你们决定对整个系统进行拆分,最终V3.0版本的淘宝系统架构图以下:做者图片已没法打开,请见谅

      从上图能够看出V3.0版本的系统对整个系统进行了水平和垂直两个方向的拆分,水平方向上,按照功能分为交易,评价,用户,商品等系统,一样垂直方向上,划分为业务系统,核心业务系统以及以及基础服务,这样以来,各个系统均可以独立维护和独立的进行水平伸缩,好比交易系统能够在不影响其它系统的状况下独立的进行水平伸缩以及功能扩展。

      从上面能够看出,一个大型系统要想变得可维护,可扩展,可伸缩,咱们必须的对它进行拆分,拆分必然也带来系统之间如何通讯以及系统之间依赖管理等问题,关于通讯方面,淘宝目前独立开发了本身的高性能服务框架HSF,此框架主要解决了淘宝目前全部子系统之间的同步和异步通讯目前HSF主要用于同步场合,FutureTask方式的调用场景还比较少。至于系统间的依赖管理,目前淘宝还作的不够好,这应该也是咱们之后努力解决的问题。

      四数据库拆分TDDL

      在前面“应用拆分”主题中,咱们提到了一个大型互联网应用须要进行良好的拆分,而那里咱们仅仅说了”应用级别”的拆分,其实咱们的互联网应用除了应用级别的拆分之外,还有另一个很重要的层面就是存储如何拆分的。所以这个主题主要涉及到如何对存储系统,一般就是所说的RDBMS进行拆分。

      好了,肯定了这个小节的主题以后,咱们回顾一下,一个互联网应用从小变大的过程当中遇到的一些问题,经过遇到的问题来引出咱们拆分RDBMS的重要性。

      系统刚开始的时候,因系统刚上线,用户很少,那个时候,全部的数据都放在了同一个数据库中,这个时候由于用户少压力小,一个数据库彻底能够应付的了,可是随着运营那些哥们辛苦的呐喊和拼命的推广之后,忽然有一天发现,oh,god,用户数量忽然变多了起来,随之而来的就是数据库这哥们受不了,它终于在某一天你们都和惬意的时候挂掉啦。此时,我们搞技术的哥们,就去看看到底是啥缘由,咱们查了查之后,发现原来是数据库读取压力太大了,此时我们都清楚是到了读写分离的时候,这个时候咱们会配置一个server为master节点,而后配几个salve节点,这样以来经过读写分离,使得读取数据的压力分摊到了不一样的salve节点上面,系统终于又恢复了正常,开始正常运行了。可是好景仍是不长,有一天咱们发现master这哥们撑不住了,它负载老高了,汗流浃背,随时都有翘掉的风险,这个时候就须要我们垂直分区啦也就是所谓的分库,好比将商品信息,用户信息,交易信息分别存储到不一样的数据库中,同时还能够针对商品信息的库采用master,salve模式,OK,经过分库之后,各个按照功能拆分的数据库写压力被分担到了不一样的server上面,这样数据库的压力终于有恢复到正常状态。可是是否是这样,咱们就能够高枕无忧了呢?NO,这个NO,不是我说的,是前辈们经过经验总结出来的,随着用户量的不断增长,你会发现系统中的某些表会变的异常庞大,好比好友关系表,店铺的参数配置表等,这个时候不管是写入仍是读取这些表的数据,对数据库来讲都是一个很耗费精力的事情,所以此时就须要咱们进行“水平分区”了这就是俗话说的分表,或者说sharding.

      OK,上面说了一大堆,无非就是告诉你们一个事实“数据库是系统中最不容易scale out的一层”,一个大型的互联网应用必然会通过一个从单一DB server,到Master/salve,再到垂直分区分库,而后再到水平分区分表,sharding的过程,而在这个过程当中,Master/salve以及垂直分区相对比较容易,应用的影响也不是很大,可是分表会引发一些棘手的问题,好比不能跨越多个分区join查询数据,如何平衡各个shards的负载等等,这个时候就须要一个通用的DAL框架来屏蔽底层数据存储对应用逻辑的影响,使得底层数据的访问对应用透明化。

      拿淘宝目前的状况来讲,淘宝目前也正在从昂贵的高端存储小型机+ORACLE切换到MYSQL,切换到MYSQL之后,势必会遇到垂直分区分库以及水平分区Sharding的问题,所以目前淘宝根据本身的业务特色也开发了本身的TDDL框架,此框架主要解决了分库分表对应用的透明化以及异构数据库之间的数据复制

      五异步通讯Notify

      在”远程调用框架”的介绍中,咱们说了一个大型的系统为了扩展性和伸缩性方面的需求,确定是要进行拆分,可是拆分了之后,子系统之间如何通讯就成了咱们首要的问题,在”远程调用框架”小节中,咱们说了同步通讯在一个大型分布式系统中的应用,那么这一小节咱们就来讲说异步通讯.好了,既然说到了异步通讯,那么”消息中间件”就要登场了,采用异步通讯这其实也是关系到系统的伸缩性,以及最大化的对各个子系统进行解耦.

      说到异步通讯,咱们须要关注的一点是这里的异步必定是根据业务特色来的,必定是针对业务的异步,一般适合异步的场合是一些松耦合的通讯场合,而对于自己业务上关联度比较大的业务系统之间,咱们仍是要采用同步通讯比较靠谱。

      OK,那么下一步咱们说说异步能给系统带来什么样子的好处。首先咱们想一想,假如系统有A和B两个子系统构成,假如A和B是同步通讯的话,那么要想使得系统总体伸缩性提升必须同时对A和B进行伸缩,这就影响了对整个系统进行scale out.其次,同步调用还会影响到可用性,从数学推理的角度来讲,A同步调用B,若是A可用,那么B可用,逆否命题就是若是B不可用,那么A也不可用,这将大大影响到系统可用性,再次,系统之间异步通讯之后能够大大提升系统的响应时间,使得每一个请求的响应时间变短,从而提升用户体验,所以异步在提升了系统的伸缩性以及可用性的同时,也大大的加强了请求的响应时间固然了,请求的整体处理时间也许不会变少。

      下面咱们就以淘宝的业务来看看异步在淘宝的具体应用。交易系统会与不少其它的业务系统交互,若是在一次交易过程当中采用同步调用的话,这就要求要向交易成功,必须依赖的全部系统均可用,而若是采用异步通讯之后,交易系统借助于消息中间件Notify和其它的系统进行了解耦,这样以来当其它的系统不可用的时候,也不会影响到某此交易,从而提升了系统的可用性。

      最后,关于异步方面的讨论,我能够推荐你们一些资源:

      1 . J2EE meets web2.0

      2. Ebay架构特色HPTS 2009

      六非结构化数据存储 TFS,NOSQL

      在一个大型的互联网应用当中,咱们会发现并非全部的数据都是结构化的,好比一些配置文件,一个用户对应的动态,以及一次交易的快照等信息,这些信息通常不适合保存到RDBMS中,它们更符合一种Key-value的结构,另外还有一类数据,数据量很是的大,可是实时性要求不高,此时这些数据也须要经过另外的一种存储方式进行存储,另一些静态文件,好比各个商品的图片,商品描述等信息,这些信息由于比较大,放入RDBMS会引发读取性能问题,从而影响到其它的数据读取性能,所以这些信息也须要和其它信息分开存储,而通常的互联网应用系统都会选择把这些信息保存到分布式文件系统中,所以淘宝目前也开发了本身的分布式文件系统TFS,TFS目前限制了文件大小为2M,适合于一些小于2M数据的存放。

      随着互联网发展,业界从08年下半年开始逐渐流行了一个概念就是NOSQL。咱们都知道根据CAP理论,一致性,可用性和分区容错性3者不能同时知足,最多只能同时知足两个,咱们传统的关系数据采用了ACID的事务策略,而ACID的事务策略更加讲究的是一种高一致性而下降了可用性的需求,可是互联网应用每每对可用性的要求要略高于一致性的需求,这个时候咱们就须要避免采用数据的ACID事务策略,转而采用BASE事务策略,BASE事务策略是基本可用性,事务软状态以及最终一致性的缩写,经过BASE事务策略,咱们能够经过最终一致性来提高系统的可用性,这也是目前不少NOSQL产品所采用的策略,包括facebook的cassandra,apache hbase,google bigtable等,这些产品很是适合一些非结构化的数据,好比key-value形式的数据存储,而且这些产品有个很好的优势就是水平伸缩性。目前淘宝也在研究和使用一些成熟的NOSQL产品。

      七监控、预警系统

      对于大型的系统来讲,惟一可靠的就是系统的各个部分是不可靠。

      由于一个大型的分布式系统中势必会涉及到各类各样的设备,好比网络交换机,普通PC机,各类型号的网卡,硬盘,内存等等,而这些东东都在数量很是多的时候,出现错误的几率也会变大,所以咱们须要时时刻刻监控系统的状态,而监控也有粒度的粗细之分,粒度粗一点的话,咱们须要对整个应用系统进行监控,好比目前的系统网络流量是多少,内存利用率是多少,IO,CPU的负载是多少,服务的访问压力是多少,服务的响应时间是多少等这一系列的监控,而细粒度一点的话,咱们就需对好比应用中的某个功能,某个URL的访问量是多,每一个页面的PV是多少,页面天天占用的带宽是多少,页面渲染时间是多少,静态资源好比图片天天占用的带宽是多少等等进行进一步细粒度的监控。所以一个监控系统就变得必不可少了。

      前面说了一个监控系统的重要性,有了监控系统之后,更重要的是要和预警系统结合起来,好比当某个页面访问量增多的时候,系统能自动预警,某台Server的CPU和内存占用率忽然变大的时候,系统也能自动预警,当并发请求丢失严重的时候,系统也能自动预警等等,这样以来经过监控系统和预警系统的结合能够使得咱们能快速响应系统出现的问题,提升系统的稳定性和可用性。

      八配置统一管理

      一个大型的分布式应用,通常都是有不少节点构成的,若是每次一个新的节点加入都要更改其它节点的配置,或者每次删除一个节点也要更改配置的话,这样不只不利于系统的维护和管理,同时也更加容易引入错误。另外不少时候集群中的不少系统的配置都是同样的,若是不进行统一的配置管理,就须要再全部的系统上维护一份配置,这样会形成配置的管理维护很麻烦,而经过一个统一的配置管理能够使得这些问题获得很好的解决,当有新的节点加入或者删除的时候,配置管理系统能够通知各个节点更新配置,从而达到全部节点的配置一致性,这样既方便也不会出错。(编选:中国电子商务研究中心 勇全)

    发布于 9个月前, 阅读(89) | 评论(1) | 投票(0) | 收藏(1)  阅读全文...
  • 262013-03

    基于HTTP协议的Web API是时下最为流行的一种分布式服务提供方式。不管是在大型互联网应用仍是企业级架构中,咱们都见到了愈来愈多SOA或RESTful的Web API。为何Web API如此流行呢?我认为很大程度上应归功于简单有效的HTTP协议。HTTP协议是一种分布式的面向资源的网络应用层协议不管是服务器端提供Web服务,仍是客户端消费Web服务都很是简单。再加上浏览器、Javascript、AJAX、JSON以及HTML5等技术和工具的发展,互联网应用架构设计表现出了从传统的PHP、JSP、ASP.NET等服务器端动态网页向Web API + RIA(富互联网应用)过渡的趋势。Web API专一于提供业务服务,RIA专一于用户界面和交互设计,今后两个领域的分工更加明晰。在这种趋势下,Web API设计将成为服务器端程序员的必修课。然而,正如简单的Java语言并不意味着高质量的Java程序,简单的HTTP协议也不意味着高质量的Web API要想设计出高质量的Web API,还须要深刻理解分布式系统及HTTP协议的特性。

     

    幂等性定义

    本文所要探讨的正是HTTP协议涉及到的一种重要性质:幂等性(Idempotence)。在HTTP/1.1规范中幂等性的定义是:

    Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.

    从定义上看,HTTP方法的幂等性是指一次和屡次请求某一个资源应该具备一样的反作用。幂等性属于语义范畴,正如编译器只能帮助检查语法错误同样,HTTP规范也没有办法经过消息格式等语法手段来定义它,这多是它不太受到重视的缘由之一。但实际上,幂等性是分布式系统设计中十分重要概念,而HTTP的分布式本质也决定了它在HTTP中具备重要地位。

     

    分布式事务 vs 幂等设计

    为何须要幂等性呢?咱们先从一个例子提及,假设有一个从帐户取钱的远程API(能够是HTTP的,也能够不是),咱们暂时用类函数的方式记为: 

    bool withdraw(account_id, amount)

    withdraw的语义是从account_id对应的帐户中扣除amount数额的钱;若是扣除成功则返回true,帐户余额减小amount;若是扣除失败则返回false,帐户余额不变。值得注意的是:和本地环境相比,咱们不能轻易假设分布式环境的可靠性。一种典型的状况是withdraw请求已经被服务器端正确处理,但服务器端的返回结果因为网络等缘由被掉丢了,致使客户端没法得知处理结果。若是是在网页上,一些不恰当的设计可能会使用户认为上一次操做失败了,而后刷新页面,这就致使了withdraw被调用两次,帐户也被多扣了一次钱。如图1所示:

    non-idemponent

    图1

    这个问题的解决方案一是采用分布式事务,经过引入支持分布式事务的中间件来保证withdraw功能的事务性。分布式事务的优势是对于调用者很简单,复杂性都交给了中间件来管理。缺点则是一方面架构过重量级,容易被绑在特定的中间件上,不利于异构系统的集成;另外一方面分布式事务虽然能保证事务的ACID性质,而但却没法提供性能和可用性的保证。

    另外一种更轻量级的解决方案是幂等设计。咱们能够经过一些技巧把withdraw变成幂等的,好比:

    int create_ticket() 

    bool idempotent_withdraw(ticket_id, account_id, amount)

    create_ticket的语义是获取一个服务器端生成的惟一的处理号ticket_id,它将用于标识后续的操做。idempotent_withdraw和withdraw的区别在于关联了一个ticket_id,一个ticket_id表示的操做至多只会被处理一次,每次调用都将返回第一次调用时的处理结果。这样,idempotent_withdraw就符合幂等性了,客户端就能够放心地屡次调用。

    基于幂等性的解决方案中一个完整的取钱流程被分解成了两个步骤:1.调用create_ticket()获取ticket_id;2.调用idempotent_withdraw(ticket_id, account_id, amount)。虽然create_ticket不是幂等的,但在这种设计下,它对系统状态的影响能够忽略,加上idempotent_withdraw是幂等的,因此任何一步因为网络等缘由失败或超时,客户端均可以重试,直到得到结果。如图2所示:

    image

    图2

    和分布式事务相比,幂等设计的优点在于它的轻量级,容易适应异构环境,以及性能和可用性方面。在某些性能要求比较高的应用,幂等设计每每是惟一的选择。

     

    HTTP的幂等性

    HTTP协议自己是一种面向资源的应用层协议,但对HTTP协议的使用实际上存在着两种不一样的方式:一种是RESTful的,它把HTTP当成应用层协议,比较忠实地遵照了HTTP协议的各类规定;另外一种是SOA的,它并无彻底把HTTP当成应用层协议,而是把HTTP协议做为了传输层协议,而后在HTTP之上创建了本身的应用层协议。本文所讨论的HTTP幂等性主要针对RESTful风格的,不过正如上一节所看到的那样,幂等性并不属于特定的协议,它是分布式系统的一种特性;因此,不管是SOA仍是RESTful的Web API设计都应该考虑幂等性。下面将介绍HTTP GET、DELETE、PUT、POST四种主要方法的语义和幂等性。

    HTTP GET方法用于获取资源,不该有反作用,因此是幂等的。好比:GET http://www.bank.com/account/123456,不会改变资源的状态,不论调用一次仍是N次都没有反作用。请注意,这里强调的是一次和N次具备相同的反作用,而不是每次GET的结果相同。GET http://www.news.com/latest-news这个HTTP请求可能会每次获得不一样的结果,但它自己并无产生任何反作用,于是是知足幂等性的。

    HTTP DELETE方法用于删除资源,有反作用,但它应该知足幂等性。好比:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的反作用是相同的,即删掉id为4231的帖子;所以,调用者能够屡次调用或刷新页面而没必要担忧引发错误。

    比较容易混淆的是HTTP POST和PUT。POST和PUT的区别容易被简单地误认为“POST表示建立资源,PUT表示更新资源”;而实际上,两者都可用于建立资源,更为本质的差异是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的:

    The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. ...... If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header.

    The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.

    POST所对应的URI并不是建立的资源自己,而是资源的接收者。好比:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下建立一篇帖子,HTTP响应中应包含帖子的建立状态以及帖子的URI。两次相同的POST请求会在服务器端建立两份资源,它们具备不一样的URI;因此,POST方法不具有幂等性。而PUT所对应的URI是要建立或更新的资源自己。好比:PUT http://www.forum/articles/4231的语义是建立或更新ID为4231的帖子。对同一URI进行屡次PUT的反作用和一次PUT是相同的;所以,PUT方法具备幂等性。

    在介绍了几种操做的语义和幂等性以后,咱们来看看如何经过Web API的形式实现前面所提到的取款功能。很简单,用POST /tickets来实现create_ticket;用PUT /accounts/account_id/ticket_id&amount=xxx来实现idempotent_withdraw。值得注意的是严格来说amount参数不该该做为URI的一部分,真正的URI应该是/accounts/account_id/ticket_id,而amount应该放在请求的body中。这种模式能够应用于不少场合,好比:论坛网站中防止意外的重复发帖。

     

    总结

    上面简单介绍了幂等性的概念,用幂等设计取代分布式事务的方法,以及HTTP主要方法的语义和幂等性特征。其实,若是要追根溯源,幂等性是数学中的一个概念,表达的是N次变换与1次变换的结果相同,有兴趣的读者能够从Wikipedia上进一步了解。

     

    参考

    RFC 2616, Hypertext Transfer Protocol -- HTTP/1.1, Method Definitions

    The Importance of Idempotence

    stackoverflow -  PUT vs POST in REST

    发布于 9个月前, 阅读(9) | 评论(0) | 投票(0) | 收藏(0)  阅读全文...
  • 292012-11
    摘要:HBTC 2012(Hadoop&BigData Technology Conference 2012)即将召开,为了让读者能够提早了解一下目前国内各个公司在Hadoop和大数据方面的运用,CSDN于会前对演讲嘉宾进行了采访。本期采访了阿里巴巴的代志远,他给咱们提早分享了一下HBase在阿里巴巴海量数据部门的实践。

    【CSDN报道】代志远早年就任网易研究院从事MapReduce与DFS系统的自主研发,后加入支付宝数据平台负责Hadoop与HBase体系的架构设计与二次研发,支付宝流计算与分布式搜索系统的设计和研发,后成为支付宝海量计算体系架构师兼支付宝三代架构成员。现就转战于阿里巴巴集团-CDO-海量数据部门,负责创新性项目的研究和跟进,目前专一于Google第二代数据库产品MegaStore的研究和在阿里的落地。

    在即将召开的HBTC大会中,咱们有幸邀请到代志远做为咱们的演讲嘉宾,请他分享下阿里巴巴在海量数据分布式数据库领域的探索。咱们也对他提早作了邮件采访,让用户能够更快地了解阿里巴巴海量数据分布式数据库以及在Hadoop应用领域的实践。

    阿里巴巴海量数据部门: 代志远

    CSDN: Hadoop目前是大数据处理领域的王者,你认为中小企业应用Hadoop的瓶颈在哪里?

    代志远:首先由于Hadoop自己机制复杂,所依赖的参数配置颇多,而且Hadoop须要像数据库同样稳定,知足性能的运行,就须要运维人员如同DBA同样要懂网络、磁盘、内核以及其余一些硬件知识,这对于运维人员的要求是比较高的。其次Hadoop社区蓬勃发展,生态圈不断扩大,用户不断增多,规模极限也不断突破,这就促使了Hadoop的架构和代码发展很是快并且变动也比较快,正由于如此,系统在快速发展的时候容易引入不少的Bug和一些缺陷(可能由于稍稍的使用不当或比较小的问题就引发总体性能和稳定性的波动)。更重要的是,Hadoop代码复杂,并且须要与社区接轨,可以找到对Hadoop源码熟悉并能优化升级和bugfix的人才是很难的,这对于一个公司的研发来讲是个很大的挑战。最后一点是公司的认知,除了相似Cloudera、MapR之类的软件公司须要对软件技术负责,其余多数公司不管大中小都依赖于公司业务,尤为中小公司业务压力大、人员紧张,可以从业务研发人员中抽调或经过其余方式组建专有的Hadoop运维团队甚至是研发团队,从公司规划与发展上来讲是比较困难的事情。

    CSDN: Hadoop的本质是为全量而生,就是说它重吞吐量,响应时间彻底没有保障,那么对于像淘宝、天猫在“双11”活动抢购的时候,须要实时处理数据(多是毫秒级,秒级的响应),是如何进行实现的?

    代志远:Hadoop是离线计算平台,其中包括分布式文件系统(HDFS)和分布式计算(MapReduce),这自己是没法对响应时间作保证的。可是目前在Hadoop之上的生态系统愈来愈完善,其中HBase就是支持海量数据、高并发的在线数据库,应对这种场景就很是适合。HBase在此次双十一中与MySQL等在线数据库共同做为线上库使用,承担了重要的责任,并创下了并在全天高压力之下无端障的佳绩。另外非Hadoop生态圈的流式计算框架Storm、S4也一样能够为实时计算分担必定的压力。

    CSDN: 你在云计算大会时作的一场有关HBase的报告,主要讲如何用HBase替代MySQL,HBase对比MySQL的优点在哪里?

    代志远:准确来讲是HBase替换MySQL的一部分应用,这些应用天然是要符合HBase的应用场景(与MySQL对比),好比数据量大、对线性拓展有需求、对自动化运维(负载均衡)有要求并且应用模式简单。在支付宝中因其增加速度快,业务量大,形成了不少应用都是数据量庞大并且速度增加快,所以有一些应用迫切须要一个数据库可以支撑如今的业务而下降对关系型的需求,因此尝试了HBase的解决方案。

    CSDN: 阿里巴巴在部署Hadoop的过程当中有哪些比较好的经验能够跟技术人员分享?

    代志远:最重要的是要有一个完善团队,健全的流程。

    • 集群愈来愈大,要树立以集群稳定性和性能为要领的工做思路。
    • 如今进入Hadoop应用开发领域的人变多,但自己知识因其入行迟早而积累不一样,没法对集群的稳定性负责,经常会写出跑死集群的任务(数据库中SQL使用不善也常会如此)。所以要有一个较好的管理流程约束开发人员作到责任分明,以便促使应用开发不只要对本身的任务负责还要对集群负责,不断学习和检查减小故障的产生。
    • 要有一个好的运维团队,懂硬件、重流程、负责任。
    • 公司在资源和战略上应有所倾斜,重视研发人员增强在研发的投入,毕竟分布式系统的入行门槛相比应用开发的技术门槛要高,固然有好的应用架构师可以取长补短规避大多数问题也是可行的,但单一系统的稳定性仍是须要靠人来保证。

    CSDN: 请您简要介绍一下本次HBTC2012大会上的议题的内容。

    代志远:06年Google发表论文Bigtable,社区随之出现HBase,后Google 08年发表第二代数据库产品MegaStore至今未有社区同类产品出现,现今Google又出现新一代数据库理论Spanner和F1。 而最近几年随之Bigtable和NoSQL的兴起,社区产品HBase逐步走向NoSQL系统的主流产品,优点明显然而缺点也明显,大数据平台下的业务由SQL向NoSQL的迁移比较复杂而应用人员学习成本颇高,而且没法支持事务和多维索引,使得许多业务没法享用来自NoSQL系统中线性拓展能力。

    Google内部MegaStore就做为Bigtable的一个补充而出现,在Bigtable的上层支持了SQL,事务、索引、跨机房灾备,并成为大名鼎鼎的Gmail、Google App Engine、Android Market的底层存储。所以咱们决定以MegaStore为理论模型进行探索如何在HBase系统上不牺牲线性拓展能力,同时又能提供跨行事务、索引、SQL的功能。

    HBase系统故障恢复的优化实践

    其实在第四届中国云计算大会上,当时还在支付宝数据平台的架构师代志远就为你们带来了题为“HBase系统故障恢复的优化实践分享”的精彩演讲,他分析了支付宝海量数据在线处理的现状,以HBase解决方案取代传统MySQL解决方案的技术历程,并详尽分享了Region Server的宕机恢复流程(阅读全文)。

    在Hadoop的体系当中,支持实时的一条线,HBase,支持海量数据库初衷的时候,设计为了设计万一级实时数据库,HBase这个东西通过这几年的发展,已经逐渐成为目前业界当中主要的实时数据库,分布式数据库,像支付宝直接上HBase系统,就是考虑到HBase的先进架构,可以帮助支付宝完成如今不少的海量数据的存储以及在线随机读写高性能的访问和存储。

    不过在HBase的系统当中,体现它的可用性有几个风险。第一个是HBase自己在底层依赖的HDFS,加载了惟一一块数据,单台机器保证一致性,HDFS保持了冗余。第二点,恢复过程中,Failover过程很是复杂,这个时间消耗越长,做为在线系统,这种时间越长可能会影响到在线访问用户体验。第三点它依赖的HDFS,HBase做为在线数据库依赖HDFS有故障的,通过几小时恢复提供生产业务,对业务方没有直接感觉,做为在线系统若是挂掉,若是须要通过近小时恢复时间,恐怕就会直接收到自于支付宝外部的用户投诉了。HBase目前它本身的监控体系尚不完善,目前的监控力度很是得粗,只能监控到单台的Region Server的状况,看不到当前用户表有多少读写比例,看不到当前服务结点写做量多少,读出量多少。

    Region Server在恢复过程中有几个流程这个流程很复杂,流程很是很是多,以当前的系统规模,它凸显出来的问题,这几个流程是影响到它的恢复速度的关键流程。等待时间周期很是长,周期之因此比较长,是由于如今的机器发展速度很是得快,每台机器从两个G到8个G,96G,140G的大层次的机器,Java语言实现了系统当中大内存管理自己存在问题,除非革新这门语言,不然别无他法。若是说在设计的参数不合理,就可能会致使一个问题,有可能这台服务器就会中止运行,发生这么一次状况就很是可怕,几十G的内存这个过程须要几十秒甚至上分钟,一般状况下,咱们会设置到3分钟,这就意味着,为了不出现这种问题,就会同时引入新的问题,宕机以后恢复等待时间须要三分钟。第二个关键流程当中,当它感知到已经挂掉了,在线数据库协助WL数据从新作到存储当中去,以保证明时更新是同步,不然这个数据库确定要丢出去,重作数据过程中,会有一个过程,Split Hlog,跟当前数据量有关系,Edit Log数据又比较多,你们在业余时间能够进行测试,数据不以支付宝的为准,以当前数据系统大小为准。

    第三个关键流程,重作完数据以后,这部分从新上线,上线以前进行数据进行二次扫描,告诉系统,Region怎么加入到Region Server当中去,扫描也存在问题,问题可能引起到两分钟到6分钟,这也跟当前系统数据有关。第四部分,这个过程称之为再次上线的过程,这个再次上线,上线时间跟当前这台机器的Region上线有关系。支付宝面对消费记录查询,用户查不出来数据,15分钟以后才能查到,在面临在线问题上这是很是可怕的事情。

    针对Region Server这一关键流程,作了一些优化。这个优化正是提到关键流程第一点,在判断宕机超市的状况下,不强依赖于Zookeeper,支付宝又启动了监控进程Mirror Process,每一台,Region Server当中都会起到PID存不存在,这种检查并不是彻底可靠,当检查PID不存在,就有理由认为已经挂掉了,要进行可靠检查,一般DBA在线判断数据库是否可用,一般会用PIng连续服务端口,这就弥补了系动中的调用命令不可靠的事情。最后当发现服务端口不可用时,有理由认为当前进程已经死掉了,死掉了以后,那么就按照现有逻辑删除结点,这三分钟的时间就彻底省略掉了。(整理/@CSDN王鹏,审校/包研)

    11月30日-12月1日,北京新云南皇冠假日酒店,业内将迎来国内大数据领域最纯粹的技术盛会——HBTC 2012(Hadoop&BigData Technology Conference 2012)。Hadoop及云计算生态系统的力量齐聚北京,欢迎热爱开源的朋友们加入!报名网址参见HBTC 2012

    发布于 1年前, 阅读(112) | 评论(0) | 投票(0) | 收藏(2)  阅读全文...
  • 292012-11

    在前面三篇文章中,介绍了关于分布式系统中数据一致性的问题,这一篇主要介绍CAP定理以及本身对CAP定理的了解。

    CAP定理是2000年,由 Eric Brewer 提出来的

    Brewer认为在分布式的环境下设计和部署系统时,有3个核心的需求,以一种特殊的关系存在。这里的分布式系统说的是在物理上分布的系统,好比咱们常见的web系统。

    这3个核心的需求是:ConsistencyAvailabilityPartition Tolerance,赋予了该理论另一个名字 - CAP

    Consistency:一致性,这个和数据库ACID的一致性相似,但这里关注的全部数据节点上的数据一致性和正确性,而数据库的ACID关注的是在在一个事务内,对数据的一些约束。

    Availability:可用性,关注的在某个结点的数据是否可用,能够认为某一个节点的系统是否可用,通讯故障除外。

    Partition Tolerance:分区容忍性,是否能够对数据进行分区。这是考虑到性能和可伸缩性。

    为何不能彻底保证这个三点了,我的以为主要是由于一旦进行分区了,就说明了必须节点之间必须进行通讯,涉及到通讯,就没法确保在有限的时间内完成指定的行文,若是要求两个操做之间要完整的进行,由于涉及到通讯,确定存在某一个时刻只完成一部分的业务操做,在通讯完成的这一段时间内,数据就是不一致性的。若是要求保证一致性,那么就必须在通讯完成这一段时间内保护数据,使得任何访问这些数据的操做不可用。

    若是想保证一致性和可用性,那么数据就不可以分区。一个简单的理解就是全部的数据就必须存放在一个数据库里面,不能进行数据库拆分。这个对于大数据量,高并发的互联网应用来讲,是不可接受的。

     

    咱们能够拿一个简单的例子来讲明:假设一个购物系统,卖家A和卖家B作了一笔交易100元,交易成功了,买家把钱给卖家。

    这里面存在两张表的数据:Trade表Account表 ,涉及到三条数据Trade(100),Account A ,Account B

    假设 trade表和account表在一个数据库,那么只须要使用数据库的事务,就能够保证一致性,同时不会影响可用性。可是随着交易量愈来愈大,咱们能够考虑按照业务分库,把交易库和account库单独分开,这样就涉及到trade库和account库进行通讯,也就是存在了分区,那么咱们就不可能同时保证可用性和一致性。

    咱们假设初始状态

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,I)

    account(accountNo,balance) = account(A,300)

    account(accountNo,balance) = account(B,10)

    在理想状况下,咱们指望的状态是

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)

    account(accountNo,balance) = account(A,200)

    account(accountNo,balance) = account(B,110)

     

    可是考虑到一些异常状况

    假设在trade(20121001,S)更新完成以前,账户A进行扣款以后,账户A进行了另一笔300款钱的交易,把钱消费了,那么就存在一个状态

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)

    account(accountNo,balance) = account(A,0)

    account(accountNo,balance) = account(B,10)

    产生了数据不一致的状态

     

    因为这个涉及到资金上的问题,对资金要求比较高,咱们必须保证一致性,那么怎么办,只能在进行trade(A,B,20121001)交易的时候,对于任何A的后续交易请求trade(A,X,X),必须等到A完成以后,才可以进行处理,也就是说在进行trade(A,B,20121001)的时候,Account(A)的数据是不可用的。

     

    任何架构师在设计分布式的系统的时候,都必须在这三者之间进行取舍。首先就是是否选择分区,因为在一个数据分区内,根据数据库的ACID特性,是能够保证一致性的,不会存在可用性和一致性的问题,惟一须要考虑的就是性能问题。对于可用性和一致性,大多数应用就必须保证可用性,毕竟是互联网应用,牺牲了可用性,至关于间接的影响了用户体验,而惟一能够考虑就是一致性了。

     

    牺牲一致性

    对于牺牲一致性的状况最多的就是缓存和数据库的数据同步问题,咱们把缓存看作一个数据分区节点,数据库看做另一个节点,这两个节点之间的数据在任什么时候刻都没法保证一致性的。在web2.0这样的业务,开心网来举例子,访问一个用户的信息的时候,能够先访问缓存的数据,可是若是用户修改了本身的一些信息,首先修改的是数据库,而后在通知缓存进行更新,这段期间内就会致使的数据不一致,用户可能访问的是一个过时的缓存,而不是最新的数据。可是因为这些业务对一致性的要求比较高,不会带来太大的影响。

     

    异常错误检测和补偿

    还有一种牺牲一致性的方法就是经过一种错误补偿机制来进行,能够拿上面购物的例子来讲,假设咱们把业务逻辑顺序调整一下,先扣买家钱,而后更新交易状态,在把钱打给卖家

    咱们假设初始状态

    account(accountNo,balance) = account(A,300)

    account(accountNo,balance) = account(B,10)

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,I)

     

    那么有可能出现

    account(accountNo,balance) = account(A,200)

    trade(buyer,seller,tradeNo,status) = trade(A,B,20121001,S)

    account(accountNo,balance) = account(B,10)

     

    那么就出现了A扣款成功,交易状态也成功了,可是钱没有打给B,这个时候能够经过一个时候的异常恢复机制,把钱打给B,最终的状况保证了一致性,在必定时间内数据多是不一致的,可是不会影响太大。

     

    两阶段提交协议

    固然,还有一种方式就是我另一篇文章里面《X/Open DTP-分布式事务模型》里面说的,可是再第一阶段和第二阶段之间,数据也可不能是一致性的,也可能出现一样的状况致使异常。并且DTP的分布式事务模型 限制太多,例如必须有实现其功能的相关的容器支持,而且资源管理器也必须实现了XA规范。限制比较多。

     

    国外有的架构师有两种方案去解决CAP的限制,可是也是比较适合特定的业务,而没有通用的解决方案,

    探知分区->分区内操做->过后补偿

    就是上面介绍的异常检测恢复机制,这种机制其实仍是有限制,

    首先对于分区检测操做,不一样的业务涉及到的分区操做可能不同

    分区内操做限制:不一样的业务对应的约束不一致

    过后补偿:因为业务约束不同,补偿方式也不同。

    因此这只能做为一种思想,不能作一个通用的解决方案

     

     

    转载自:http://www.cnblogs.com/aigongsi/archive/2012/10/15/2721366.html

    发布于 1年前, 阅读(69) | 评论(0) | 投票(0) | 收藏(0)  阅读全文...
  • 292012-11
    关于分布式系统的数据一致性问题(三)

    在个人博文里面 关于分布式系统的数据一致性问题(二) 里面主要介绍了数据分布的状况下保证一致性的状况,在第二篇文章里面,我这里提出了三个问题

    1. 订单系统调用支付系统支付订单,支付成功,可是返回给订单系统数据超时,订单仍是I(初始状态),可是此时会员账户余额100,会员确定会立刻找京东骂京东,为啥不给老子发货,我都付钱了
    2. 订单系统调用支付系统成功,状态也已经更新成功,可是通知仓库发货失败,这个时候订单是P(已支付)状态,此时会员账户余额是100,可是仓库不会发货。会员也要骂京东。
    3. 订单系统调用支付系统成功,状态也已经更新成功,而后通知仓库发货,仓库告诉订单系统,没有货了。这个时候数据状态和第二种状况同样。

     

    重点分析解决了第一个的问题以及相应的方案,发如今数据分布的环境下,很难绝对的保证数据一致性(任何一段区间),可是有办法经过一种补偿机制,最终保证数据的一致性。

     

    在下面在分析一下第二个问题

    • 订单系统调用支付系统成功,状态也已经更新成功,可是通知仓库发货失败,这个时候订单是P(已支付)状态,此时会员账户余额是100,可是仓库不会发货。会员也要骂京东。

    经过在上一篇文章里面分析过,这个相对来讲是比较简单的,我能够采起重试机制,若是发现通知仓库发货失败,就一致重试,

    这里面有两种方式:

    1 异步方式:经过相似MQ(消息通知)的机制,这个是异步的通知

    2 同步调用:相似于远程过程调用

    对于同步的调用的方式,比较简单,咱们可以及时获取结果,对于异步的通知,就必须采用请求,应答的方式进行,这一点在(关于分布式系统的数据一致性问题(一))里面有介绍。这里面就再也不阐述。

     

    来看看第三个问题

    • 订单系统调用支付系统成功,状态也已经更新成功,而后通知仓库发货,仓库告诉订单系统,没有货了。这个时候数据状态和第二种状况同样。

    我以为这是一个颇有意思的问题,咱们仍是考虑几种解决的方案

    1 在会员下单的时刻,就告诉仓库,我要你把货物留下来,

    2 在会员支付订单时候,在支付以前检查仓库有没有货,若是没有货,就告知会员木有货物了

    3 若是会员支付成功,这个时候没有货了,就会退款给用户或者等待有货的时候在发货

     

    正常状况,京东的仓库通常都是有货的,因此影响到的会员不多,可是在秒杀和营销的时候,这个时候就不必定了,咱们考虑假设仓库有10台iphone

    若是采用第一种方案,

    1 在会员下单的时候,至关于库存就-1,那么用户恶意拍下来,没有去支付,就影响到了其余用户的购买。京东能够设置一个订单超时时间,若是这段时间内没有支付,就自动取消订单

    2 在会员支付以前,检查仓库有货,这种方案了,对于用户体验很差,可是对于京东比较好,至少我东西都卖出去了。那些没有及时付款的用户,只能投诉了京东无端取消订单

    3 第三种方案,这个方案体验更很差,并且用户感受受到京东欺诈,可是对于京东来讲,比第二种方案更有益,毕竟我还能够多卖出一点东西。

     

    我的以为,京东应该会采用第二种或者第三种方式来处理这类状况,我在微博上搜索了 “京东 无端取消订单”,发现果然和我预料的处理方式。不过至于这里的无端取消是否是技术上的缘由我不知道,若是真的是技术上的缘由,我以为京东能够采用不一样的处理方案。对于秒杀和促销商品,能够考虑第一种方案,大多数人都会直接付款,毕竟便宜啊,若是用户抢不到便宜的东西,抱怨固然很大了。这样能够照顾大多数用户的体验。对于通常的订单,能够采用第二种或者第三种方式,这种状况下,发生付款以后仓库没有货的状况会比较少,而且就算发生了,用户也会以为无所谓,大不了退钱吗,这样就能够实现本身的利益最大化而最低程度的减小用户体验。

     

    而铁道部在这个问题上,采用的是第一种方案,为何和京东不同,就是由于用户体验,若是用户把票都买了,你告诉我木有票了,旅客会杀人的。哈哈,不过铁道部不担忧票卖不出去,第一种方案对他影响没有什么。

     

    说了这么多,就是说 分布式环境下(数据分布)要任什么时候刻保证数据一致性是不可能的,只能采起妥协的方案来保证数据最终一致性。这个也就是著名的CAP定理。

     

    转载自:http://www.cnblogs.com/aigongsi/archive/2012/09/25/2701396.html


    发布于 1年前, 阅读(36) | 评论(0) | 投票(0) | 收藏(0)  阅读全文...
  • 292012-11

    分布式系统的数据一致性问题(一)里面,简单的介绍了分布式数据的同步问题,上面的问题比较抽象,在目前的互联网应用中还不多见,此次在经过一个比较常见的例子,让你们更深刻的了解一下分布式系统设计中关于数据一致性的问题

     

    此次咱们拿咱们常用的功能来考虑吧,最近网购比较热门,就以京东为例的,咱们来看看京东的一个简单的购物流程

     

    用户在京东上下了一个订单,发现本身在京东的帐户里面有余额,而后使用余额支付,支付成功以后,订单状态修改成支付成功,而后通知仓库发货。假设订单系统,支付系统,仓库系统是三个独立的应用,是独立部署的,系统之间经过远程服务调用。

    订单的有三个状态:I:初始 P:已支付 W:已出库,订单金额100, 会员账户余额200

    若是整个流程比较顺利,正常状况下,订单的状态会变为I->P->W,会员账户余额100,订单出库。

     

    可是若是流程不顺利了?考虑如下几种状况

    1:订单系统调用支付系统支付订单,支付成功,可是返回给订单系统数据超时,订单仍是I(初始状态),可是此时会员账户余额100,会员确定会立刻找京东骂京东,为啥不给老子发货,我都付钱了

    2:订单系统调用支付系统成功,状态也已经更新成功,可是通知仓库发货失败,这个时候订单是P(已支付)状态,此时会员账户余额是100,可是仓库不会发货。会员也要骂京东。

    3:订单系统调用支付系统成功,状态也已经更新成功,而后通知仓库发货,仓库告诉订单系统,没有货了。这个时候数据状态和第二种状况同样。

     

    对于问题一,咱们来分析一下解决方案,能想到的解决方案以下

    1 假设调用支付系统支付订单的时候先不扣钱,订单状态更新完成以后,在通知支付系统你扣钱

    若是采用这种设计方案,那么在同一时刻,这个用户,又支付了另一笔订单,订单价格200,顺利完成了整个订单支付流程,因为当前订单的状态已经变成了支付成功,可是实际用户已经没有钱支付了,这笔订单的状态就不一致了。即便用户在同一个时刻没有进行另外的订单支付行为,通知支付系统扣钱这个动做也有可能完不成,由于也有可能失败,反而增长了系统的复杂性。

     

    2 订单系统自动发起重试,多重试几回,例如三次,直到扣款成功为止。

    这个看起来也是不错的考虑,可是和解决方案同样,解决不了问题,还会带来新的问题,假设订单系统第一次调用支付系统成功,可是没有办法收到应答,订单系统又发起调用,完了,重复支付,一次订单支付了200。

    假设支付系统正在发布,你重试多少次都同样,都会失败。这个时候用户在等待,你怎么处理?

     

    3 在第二种方案的基础上,咱们先解决订单的重复支付行为,咱们须要在支付系统上对订单号进行控制,一笔订单若是已经支付成功,不能在进行支付。返回重复支付标识。那么订单系统根据返回的标识,更新订单状态。

    接下来解决重试问题,咱们假设应用上重试三次,若是三次都失败,先返回给用户提示支付结果未知。假设这个时候用户从新发起支付,订单系统调用支付系统,发现订单已经支付,那么继续下面的流程。若是会员没有发起支付,系统定时(一分钟一次)去核对订单状态,若是发现已经被支付,则继续后续的流程。

     

    这种方案,用户体验很是差,告诉用户支付结果未知,用户必定会骂你,你丫咋回事情,我明明支付了,你告诉我未知。假设告诉用户支付失败,万一实际是成功的咋办。你告诉用户支付成功,万一支付失败咋办。

     

    4 第三种方案可以解决订单和支付数据的一致性问题,可是用户体验很是差。固然这种状况比较多是少数,能够牺牲这一部分的用户体验,咱们还有没有更好的解决方案,既能照顾用户体验,又可以保证资金的安全性。

    咱们再回来看看第一种方案,咱们先不扣钱,可是有木有办法让这一部分钱不让用户使用,对了,咱们先把这一部分钱冻结起来,订单系统先调用支付系统成功的时候,支付系统先不扣钱,而是先把钱冻结起来,不让用户给其余订单支付,而后等订单系统把订单状态更新为支付成功的时候,再通知支付系统,你扣钱吧,这个时候支付系统扣钱,完成后续的操做。

     

    看起来这个方案不错,咱们仔细在分析一下流程,这个方案还存在什么问题,假设订单系统在调用支付系统冻结的时候,支付系统冻结成功,可是订单系统超时,这个时候返回给用户,告知用户支付失败,若是用户再次支付这笔订单,那么因为支付系统进行控制,告诉订单系统冻结成功,订单系统更新状态,而后通知支付系统,扣钱吧。若是这个时候通知失败,木有问题,反正钱都已是冻结的了,用户不能用,我只要定时扫描订单和支付状态,进行扣钱而已。

     

    那么若是变态的用户从新拍下来一笔订单,100块钱,对新的订单进行支付,这个时候因为先前那一笔订单的钱被冻结了,这个时候用户余额剩余100,冻结100,发现可用的余额足够,那就直接在对用户扣钱。这个时候余额剩余0,冻结100。先前那一笔怎么办,一个办法就是定时扫描,发现订单状态是初始的话,就对用户的支付余额进行解冻处理。这个时候用户的余额变成100,订单数据和支付数据又一致了。假设原先用户余额只有100,被冻结了,用户从新下单,支付的时候就失败了啊,的确会发生这一种状况,因此要尽量的保证在第一次订单结果不明确的状况,尽早解冻用户余额,好比10秒以内。可是无论如何快速,总有数据不一致的时刻,这个是没有办法避免的。

     

    第二种状况和第三种状况如何处理,下次在分析吧。

    因为互联网目前愈来愈强调分布式架构,若是是交易类系统,面临的将会是分布式事务上的挑战。固然目前有不少开源的分布式事务产品,例如java JPA,可是这种解决方案的成本是很是高的,并且实现起来很是复杂,效率也比较低下。对于极端的状况:例如发布,故障的时候都是没有办法保证强一致性的。

     

    转载自:http://www.cnblogs.com/aigongsi/archive/2012/09/22/2698055.html

    发布于 1年前, 阅读(41) | 评论(0) | 投票(0) | 收藏(1)  阅读全文...
  • 292012-11
    关于分布式系统的数据一致性问题(一)

     

    先把问题简单化处理,假设A增长一条记录Message_A,发送到M,B增长一条记录 MESSAGE_B发送到M,都是经过MQ服务器进行转发,那么M系统接收到条消息,增长两条数据,那么M在把增长的消息群发给A,B,A和B找到本身缺失的数据,更新数据库。这样就完成了一个数据的同步。

     

    从正常状况下来看,都没有问题,逻辑彻底合理,可是请考虑如下三个问题

    1 如何保证A->M的消息,M必定接收到了,一样,如何保证M->A的消息,M必定接收到了

    2 若是数据须要一致性更新,好比A发送了三条消息给M,M要么所有保存,要么所有不保存,不可以只保存其中的几条记录。咱们假设更新的数据是一条条发送的。

    3 假设同时A发送了多条更新请求,如何保证顺序性要求?

     

    这两个问题就是分布式环境下数据一致性的问题

    对于第一个问题,比较好解决,咱们先看看一个tcp/ip协议连接创建的过程

    咱们的思路能够从这个上面出发,在简化一下,就一个请求,一个应答。

    简单的通讯模型是这样的

    A->M : 你收到个人一条消息没有,消息的ID是12345

    M->A:  我收到了你的一条消息数据,消息数据是ID;12345

    这样就一个请求,一个应答,就完成了一次可靠性的传输。若是A一致没有收到M的应答,就不断的重试。这个时候M就必须保证幂等性。不能重复的处理消息。那么最极端的状况是,怎么也收不到M的应答,这个时候是系统故障。本身检查一下吧。

    这么设计就要求,A在发送消息的时候持久化这个消息的数据内容,而后不断的重试,一旦接收到M的应答,就删除这条消息。一样,M端也是同样的。不要相信MQ的持久化机制,不是很靠谱的。

    那么M给A发送消息也采起相似的原理就能够了。

     

    下面在看看第二个问题,如何保持数据的一致性更新,这个仍是能够参考TCP/IP的协议。

    首先A发送一条消息给M:我要发送一批消息数据给你,批次号是10000,数据是5条。

    M发送一条消息给A:ok,我准备好了,批次号是10000,发送方你A

    接着A发送5条消息给M,消息ID分别为1,2,3,4,5 ,批次号是10000,

    紧接着,A发送一个信息给M:我已经完成5小消息的发送,你要提交数据更新了

     

    接下来可能发送两种状况

    1 那么M发送消息给A:ok,我收到了5条消息,开始提交数据

    2 那么M也能够发送给A:我收到了5条消息,可是还缺乏,请你从新发送,那么A就继续发送,直到A收到M成功的应答。

    整个过程至关复杂。这个也就是数据一旦分布了,带来最大的问题就是数据一致性的问题。这个成本很是高。

     

    对于第三个问题,这个就比较复杂了

    这个最核心的问题就是消息的顺序性,咱们只能在每一个消息发一个消息的序列号,可是仍是没有最好解决这个问题的办法。由于消息接收方不知道顺序。由于即便给他了序列号,也没有办法告诉他,这个应该什么时候处理。最好的办法是在第二种方式的基础做为一个批次来更新。

     

    这个只是以最简单的例子来讲明一下分布式系统的要保证数据一致性是一件代价很大的事情。固然有的博主会说,这个何须这么复杂,直接数据库同步不就能够了。这个例子固然是没有问题的,万一这个几个库的模型都不同,我发送消息要处理的事情不同的。怎么办?

     

    转载自:http://www.cnblogs.com/aigongsi/archive/2012/09/21/2696773.html

  • 相关文章
    相关标签/搜索