五千年(敝帚自珍)

主题:【半原创】Flickr 网站架构研究(1) -- 西电鲁丁

共:💬69 🌺366
分页树展主题 · 全看首页 上页
/ 5
下页 末页
                • 家园 谢谢,那memcache的hash table效率如何?
                  • 家园 这个没有考察过了

                    memcache看了一下简介

                    Free & open source, high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.

                    Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.

                    那么就是说memcache全部是in-memory 操作,那么hash的开销是C,全部都是mem的话,对小数据量来说,这个速度就超快了。但因为全部都是memory,所以必须要多台机器来cache。这个如何管理distributed cache是个很大的课题,没有考察过,不好说了。

              • 家园 新鲜的提法,长见识

                没有实际试过,事实上,lucene代替squid都没有想过,值得好好琢磨一下。

    • 家园 几个疑问

      1.

      服务器的硬件配置:

      - 6-disk 15K RPM RAID-10.

      - 2U boxes.

      RAID 放在何处?2U boxes在何处?能不能在上图中标一下?

      2.

      Storage Manager

      - 运行私有的,适用于海量文件存储的Flickr File System

      为什么需要重新发明一套Flickr FS,它与NFS之类有什么区别?

      3.

      “Dual Tree"架构是”Master-Master"和“Master-Slave"的有效结合,双Master 避免了“单点故障”,Master-Slave又提高了读取速度,因为用户表的操作90%以上是读。

      只见到Master-Master,但是没有见到Master-Slave。猜想一下,如果Master是照片的元数据,那么Slave应该是照片本身,而照片是存在NetApp + Flickr FS里的。猜想正确吗?

      总体感觉,这个架构的针对性非常强。如果flickr的业务发生重大变化,这套架构似乎就得动大手术了。

      • 家园 不好意思,图都不是原创,从PPT里COPY来的

        1。 这个RAID-10根据我的理解应该是服务器的内置SCSI硬盘;2U是指刀片服务器的厚度,1U等于4.45厘米,2U就是8.9厘米,大型机房大都用这种标准机架。

        2。这个会在这个系列的后续里介绍,正在积累资料,不过关于Flickr FS的资料很难找。

        3。照片的元数据是在Shard里,照片本身是存在NetApp,Flickr FS根据我现在的理解是一个分布式文件系统中间件。

        总体感觉,这个架构的针对性非常强。如果flickr的业务发生重大变化,这套架构似乎就得动大手术了

        ,最近我所看到的是Flickr新增了Video共享功能,网上评论说自从被Yahoo收购后Flickr的进取心好像差了许多,可能和Yahoo自身的经营状况有关,Flickr是被包括在Yahoo向微软出售的优质资产里的,虽然交易没成,另外Flickr的两位创始人夫妇也先后离开了Yahoo,有传言说他们可能会创办一家社交游戏网站。

        架构的变化不好说,如果有重大改变,也许会另起炉灶,技术的发展使几年前不可能的事情变成了可能,如果重新设计,应该能有更多的选择。

        • 家园 解释得很清楚

          1. 关于服务器的硬件配置,是我先前理解错误。经兄台解释,恍然大悟。

          2.

          照片的元数据是在Shard里,照片本身是存在NetApp,Flickr FS根据我现在的理解是一个分布式文件系统中间件。

          这个猜测很靠谱。同意。

          多谢!

      • 家园 关于Master-Master和Master-Slave

        读了第二篇,发现先前的理解出错了。Master也好,Slave也好,读写的对象都是元数据。

        再次看看结构图。是不是可以这样理解,

        1. 在“Dual tree central DB”那个框中,描绘了双Master以及Slaves,只不过没有具体把各个Master与它所管辖的Slaves,用连线串在一起。

        2. "Master-master shards" 这三个框没有画完整。最好画成“Shards”,每一个shard的框中,不仅有两个Masters,还有所属的Slaves。

        另外,又想到一个问题。

        Memcached Cluster

        - 中间层缓存服务器,用于缓存数据库的SQL查询结果等。

        当数据库中的相关数据更新以后,Memcached 如何随即更新?会不会也像Master向Slaves同步那样,当Memcached cluster规模大了以后,就各个Memcached node,无法及时保持一致?

        • 家园 老兄是认真看了。呵呵

          1。这个架构图是从Cal Henderson的PPT里直接拷过来的,版权不是我的

          2。如果我的理解没错的话,在Shard里,只有一对Master-Master,没有Slave。我想这是因为Shard已经切分得足够小,虽然大多数操作可能还是读,但已经没必要加Slaves,如果业务增加的话,会再次切分。

          关于Memcached集群,文中没有提到是Memcached没有冗余和HA,每个数据根据hash key的值,只存在一个memcached的服务器的内存里,没有复制,因而一旦这个服务器垮掉了,memcached client端会重新计算hash key的值,应用逻辑每次要判断如果数据不在memcached里,会从数据库里再取,同时一旦更新也要同步更新memcached和数据库,这也是为什么Flickr要写一个write-through cache层的原因。

          具体memcached的细节请参见外链出处,不好意思,篇幅有限,很多东西没有说清楚,有时间我会再修改的。

    • 家园 做大做小

      在IT领域想做出一点成就,首先要认准方向。

      什么方向容易出成果?要么做大,要么做小。

      像云计算类似的技术,就是“大”的技术。上万台servers的集群,能不能协调作战,充分发挥能力,这就是做大的功夫。

      Yahoo网站的开通,使大家认识到了大型网站的技术难度。但是直到Amazon和Ebay发轫以后,大家才看到大型网站的技术方向。Google,Flickr,Facebook等等后起的大型网站,把做大的技术又大大推进了一步。

      研究Flickr的架构,与Google的技术横向比较,是一个苦活,但是惟其艰苦,越发彰显其价值。

      这个系列写得好,值得反复阅读,细细体会。过几天,我写篇读后感,一来与鲁丁兄交换想法,二来表达对兄台与大家分享这么有意义的文章的感激。

      • 家园 谢谢邓兄参与讨论,花谢!

        Flickr(服务器规模几百台),Facebook(上万台),Google(几十万台)应该是比较典型的大型网站,比起后两者,Flickr只能算小弟弟,所以研究起来也是相对最”容易“的。文章的主要信息来源包括我曾经在河里推荐的 "http://highscalability.com/"和Cal Henderson 的书”Building Scalable Web Sites“,一些细节是我自己的推测和其他网站资源的参考和印证,不一定完全正确,但正如我前面所说,主要是抛砖引玉,希望引得各位大牛参与讨论,可以共同学习,提高。

    • 家园 好文

      本来潜水上了个花,后来觉得还是出声支持比较好。

    • 家园 【半原创】Flickr 网站架构研究(2)

      数据库最初的扩展-Replication

      也许有人不相信,不过Flickr确实是从一台服务器起步的,即Apache/PHP和MySQL是运行在同一台服务器上的,很快MySQL服务器就独立了出来,成了双服务器架构。随着用户和访问量的快速增长,MySQL数据库开始承受越来越大的压力,成为应用瓶颈,导致网站应用响应速度变慢,MySQL的扩展问题就摆在了Flickr的技术团队面前。

      不幸的是,在当时,他们的选择并不多。一般来说,数据库的扩展无外是两条路,Scale-Up和Scale-Out,所谓Scale-Up,简单的说就是在同一台机器内增加CPU,内存等硬件来增加数据库系统的处理能力,一般不需要修改应用程序;而Scale-Out,就是我们通常所说的数据库集群方式,即通过增加运行数据库服务器的数量来提高系统整体的能力,而应用程序则一般需要进行相应的修改。在常见的商业数据库中,Oracle具有很强的Scale-Up的能力,很早就能够支持几十个甚至数百个CPU,运行大型关键业务应用;而微软的SQL SERVER,早期受Wintel架构所限,以Scale-Out著称,但自从几年前突破了Wintel体系架构8路CPU的的限制,Scale-Up的能力一路突飞猛进,最近更是发布了SQL 2008在Windows 2008 R2版运行256个CPU核心(core)的测试结果,开始挑战Oracle的高端市场。而MySQL,直到今年4月,在最终采纳了GOOGLE公司贡献的SMP性能增强的代码后,发布了MySQL5.4后,才开始支持16路CPU的X86系统和64路CPU的CMT系统(基于Sun UltraSPARC 的系统)。

      从另一方面来说,Scale-Up受软硬件体系的限制,不可能无限增加CPU和内存,相反Scale-Out却是可以"几乎"无限的扩展,以Google为例,2006年Google一共有超过45万台服务器(谁能告诉我现在他们有多少?!);而且大型SMP服务器的价格远远超过普通的双路服务器,对于很多刚刚起步或是业务增长很难预测的网站来说,不可能也没必要一次性投资购买大型的硬件设备,因而虽然Scale-Out会随着服务器数量的增多而带来管理,部署和维护的成本急剧上升,但确是大多数大型网站当然也包括Flickr的唯一选择。

       经过统计,Flickr的技术人员发现,查询即SELECT语句的数量要远远大于添加,更新和

      删除的数量,比例达到了大约13:1甚至更多,所以他们采用了“Master-Slave”的复制模式,即所有的“写”操作都在发生在“Master",然后”异步“复制到一台或多台“Slave"上,而所有的”读“操作都转到”Slave"上运行,这样随着“读”交易量的增加,只需增加Slave服务器就可以了。

      点看全图

      外链图片需谨慎,可能会被源头改

      让我们来看一下应用系统应该如何修改来适应这样的架构,除了”读/写“分离外,对于”读“操作最基本的要求是:1)应用程序能够在多个”Slave“上进行负载均分;2)当一个或多个”slave"出现故障时,应用程序能自动尝试下一个“slave”,如果全部“Slave"失效,则返回错误。Flickr曾经考虑过的方案是在Web应用和”Slave“群之间加入一个硬件或软件的”Load Balancer“,如下图

      点看全图

      外链图片需谨慎,可能会被源头改

      这样的好处是应用所需的改动最小,因为对于应用来说,所有的读操作都是通过一个虚拟的Slave来进行,添加和删除“Slave"服务器对应用透明,Load Balancer 实现对各个Slave服务器状态的监控并将出现故障的Slave从可用节点列表里删除,并可以实现一些复杂的负载分担策略,比如新买的服务器处理能力要高过Slave群中其他的老机器,那么我们可以给这个机器多分配一些负载以最有效的利用资源。一个简单的利用Apache proxy_balancer_module的例子如下:

      。。。。。。。。。。。。。。

      LoadModule proxy_module modules/mod_proxy.so

      LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

      LoadModule proxy_http_module modules/mod_proxy_http.so

      。。。。。。。。。。。。。。。。。。。。

      <Proxy balancer://mycluster>

      BalancerMember "http://slave1:8008/App" loadfactor=4

      BalancerMember "http://slave2:8008/App" loadfactor=3

      BalancerMember "http://slave3:8008/App" loadfactor=3

      ....................

      ///slave load ratio 4:3:3.

      最终,Flickr采用了一种非常“轻量”但有效的“简易”PHP实现,基本的代码只有10几行,

      function db_connect($hosts, $user, $pass){

      shuffle($hosts); //shuffle()是PHP函数,作用是将数组中每个元素的顺序随机打乱。

      foreach($hosts as $host){

      debug("Trying to connect to $host...");

      $dbh = @mysql_connect($host, $user, $pass, 1);

      if ($dbh){

      debug("Connected to $host!");

      return $dbh;

      }

      debug("Failed to connect to $host!");

      }

      debug("Failed to connect to all hosts in list - giving up!");

      return 0;

      }

      在上述代码中,如果需要对特定的Slave赋予更高的负载,只要在$hosts中多出现一次或多次就可以了。这段代码只要稍稍改进,就可以实现更复杂的功能,如当connect失败时自动将host从hosts列表中去除等。

      “Master”-"Slave"模式的缺点是它并没有对于“写'操作提供扩展能力,而且存在单点故障,即一旦Master故障,整个网站将丧失“更新”的能力。解决的办法采用“Master"-"Master"模式,即两台服务器互为”Master“-"Slave",这样不仅”读/写“能力扩展了一倍,而且有效避免了”单点故障“,结合已有的“Master"-"Slave",整个数据库的架构就变成了下面的”双树“结构,

      点看全图
      外链图片需谨慎,可能会被源头改

      “双树”架构并没有支撑太久的时间,大概6个月后,随着用户的激增,系统再一次达到了极限,不仅”写”操作成为了瓶颈,而且“异步复制"也由于”Slave“服务器过于繁忙而出现了严重的滞后而造成读数据的不一致。那么,能不能在现有架构加以解决,比如说增加新的”Master“服务器和考虑采用”同步复制“呢?答案是否定的,在Master超过两台的设置中,只能采用”闭环链“的方式进行复制,在大数据量的生产环境中,很容易造成在任意时刻没有一个Master或Slave节点是具有全部最新数据的(有点类似于”人一次也不能踏进同一条河“?),这样很难保障数据的一致性,而且一旦其中一个Master出现故障,将中断整个复制链;而对于”同步复制“,当然这是消除”复制滞后“的最好办法,不过在当时MySQL的同步复制还远没有成熟到可以运用在投产环境中。

      Flickr网站的架构,需要一次大的变化来解决长期持续扩展的问题。

      关键词(Tags): #Flickr#网站架构#信息技术元宝推荐:铁手, 通宝推:池塘中的雨滴,
      • 家园 【原创】Flickr 网站架构研究(3)

        Shard - 大型网站数据库扩展的终极武器?

         2005年7月,另一位大牛(MySQL 2005、2006年度 "Application of the Year Award"获得者)Dathan Pattishall加入了Flickr团队。一个星期之内,Dathan解决了Flickr数据库40%的问题,更重要的是,他为Flickr引进了Shard架构,从而使Flickr网站具备了真正“线性”Scale-Out的增长能力,并一直沿用至今,取得了巨大的成功。

         Shard主要是为了解决传统数据库Master/Slave模式下单一Master数据库的“写”瓶颈而出现的,简单的说Shard就是将一个大表分割成多个小表,每个小表存储在不同机器的数据库上,从而将负载分散到多个机器并行处理而极大的提高整个系统的“写”扩展能力。相比传统方式,由于每个数据库都相对较小,不仅读写操作更快,甚至可以将整个小数据库缓存到内存中,而且每个小数据库的备份,恢复也变得相对容易,同时由于分散了风险,单个小数据库的故障不会影响其他的数据库,使整个系统的可靠性也得到了显著的提高。

         对于大多数网站来说,以用户为单位进行Shard分割是最合适不过的,常见的分割方法有按地域(比如邮编),按Key值(比如Hash用户ID),这些方法可以简单的通过应用配置文件或算法来实现,一般不需要另外的数据库,缺点是一旦业务增加,需要再次分割Shard时要修改现有的应用算法和重新计算所有的Shard KEY值;而最为灵活的做法是以“目录”服务为基础的分割,即在Shard之前加一个中央数据库(Global Lookup Cluster),应用要先根据用户主键值查询中央数据库,获得用户数据所在的Shard,随后的操作再转向Shard所在数据库,例如下图:

        点看全图
        外链图片需谨慎,可能会被源头改

         而应用的主要修改在于要添加一个Lookup访问层,例如将以下的代码

        string connectionString = @"Driver={MySQL};SERVER=dbserver;DATABASE=CustomerDB;";

        OdbcConnection conn = new OdbcConnection(connectionString);

        conn.Open();

         变为

        string connectionString = GetDatabaseFor(customerId);

        OdbcConnection conn = new OdbcConnection(connectionString);

        conn.Open();

         GetDatabaseFor()函数完成根据用户ID获取Shard connectionString的作用。

        对应我们前面所提到过的Flickr架构

        点看全图
        外链图片需谨慎,可能会被源头改

         Dual Tree Central Database就是中央数据库,存放用户表,记录的信息是用户主键以及此用户对以的数据库Shard区;而Master-Master Shards就是一个个的Shard用户数据库,存储实际的用户数据和照片的元数据(Meta Data)。

         Flickr Shard的设计我们在Flickr 网站架构研究(1)中已经总结过了,在此不再赘述。我们在此谈一下Shard架构的主要问题和Flickr的解决办法:1)Shard只适用于不需要join操作的表,因为跨Shard join操作的开销太大,解决的办法是将一个用户的所有数据全部存放在同一个Shard里,对于一些传统方式下需要跨Shard查询的数据,只能采取冗余的方法,比如Shard1的用户A对Shard2的用户B的照片进行了评论,那么这条评论将同时存放在Shard1和Shard2中。这样就存在一个数据一致性的问题,常规的做法是用数据库事务(Transaction)、”两阶段提交“(2 phase commit)来解决,但做过两阶段提交(2PC)应用的都知道,2PC的效率相对较差,而且实际上也不能100%保证数据的完整性和一致性;另外,一旦由于其中一个Shard故障而提交失败回滚,用户只能放弃或再试一遍,用户体验较差。Flickr对于数据一致性的解决方案是Queue(Flickr用PHP开发了一个强大的Queue系统,将所有可以异步的任务都用Queue来实现,每天处理高达1千万以上的任务。),事实上当用户A对用户B的照片进行评论时,他并不关心这条评论什么时候出现在用户B的界面上,即将这条评论添加到用户B的交易是可以异步的,允许一定的迟延,通过Queue处理,既保证了数据的一致性,又缩短了用户端的相应时间,提高了系统性能。2)Shard的另一个主要问题Rebalancing,既当现有Shard的负载达到一定的阀值,如何将现有数据再次分割,Flickr目前的方式依然是手工的,既人工来确定哪些用户需要迁移,然后运行一个后台程序进行数据迁移,迁移的过程用户账户将被锁住。(据说Google做到了完全自动的Rebalancing,本着”萨大“坑里不再挖坑的原则,如果有机会的话,留到下一个系列再研究吧)

        Memcached的应用和争论

         大家应该已经注意到,Flickr为中央数据库配置了Memcached作为数据库缓存,接下来的问题是,为什么用Memcached?为什么Shard不需要Memcached?Memcached和Master,Slave的关系怎样?笔者将试图回答这些问题供大家参考,网上的相关争论很多,有些问题尚未有定论。

         Memecached是一个高性能的,分布式的,开源的内存对象缓存系统,顾名思义,它的主要目的是将经常读取的对象放入内存以提高整个系统,尤其是数据库的扩展能力。Memcached的主要结构是两个Hash Table,Server端的HashTable以key-value pair的方式存放对象值,而Client端的HashTable的则决定某一对象存放在哪一个Memcached Server.举个例子说,后台有3个Memecached Server,A、B、C,Client1需要将一个对象名为”userid123456“,值为“鲁丁"的存入,经过Client1的Hash计算,"userid123456"的值应该放入Memcached ServerB, 而这之后,Client2需要读取"userid123456"的值,经过同样的Hash计算,得出"userid123456"的值如果存在的话应该在Memcached ServerB,并从中取出。最妙的是Server之间彼此是完全独立的,完全不知道对方的存在,没有一个类似与Master或Admin Server的存在,增加和减少Server只需在Client端"注册"并重新Hash就可以了。

         Memcached作为数据库缓存的作用主要在于减轻甚至消除高负载数据库情况下频繁读取所带来的Disk I/O瓶颈,相对于数据库自身的缓存来说,具有以下优点:1)Memecached的缓存是分布式的,而数据库的缓存只限于本机;2)Memcached缓存的是对象,可以是经过复杂运算和查询的最终结果,并且不限于数据,可以是任何小于1MB的对象,比如html文件等;而数据库缓存是以"row"为单位的,一旦"row"中的任何数据更新,整个“row"将进行可能是对应用来说不必要的更新;3)Memcached的存取是轻量的,而数据库的则相对较重,在低负载的情况下,一对一的比较,Memcached的性能未必能超过数据库,而在高负载的情况下则优势明显。

         Memcached并不适用于更新频繁的数据,因为频繁更新的数据导致大量的Memcached更新和较低的缓冲命中率,这可能也是为什么Shard没有集成它的原因;Memcached更多的是扩展了数据库的”读“操作,这一点上它和Slave的作用有重叠,以至于有人争论说应该让"Relication"回到它最初的目的”Online Backup"数据库上,而通过Memcached来提供数据库的“读”扩展。(当然也有人说,考虑到Memcached的对应用带来的复杂性,还是慎用。)

         然而,在体系架构中增加Memecached并不是没有代价的,现有的应用要做适当的修改来同步Memcached和数据库中的数据,同时Memcached不提供任何冗余和“failover”功能,这些复杂的控制都需要应用来实现。基本的应用逻辑如下:

          对于读操作,

           $data = memcached_fetch( $id );

           return $data if $data

           $data = db_fetch( $id );

           memcached_store( $id, $data );

           return $data;

          对于写操作

          db_store( $id, $data );

          memcached_store( $id, $data );

          我们看到在每一次数据更新都需要更新Memcached,而且数据库或Memcached任何一点写错误应用就可能取得“过期”的数据而得到错误的结果,如何保证数据库和Memcached的同步呢?

        复制滞后和同步问题的解决

         我们知道复制滞后的主要原因是数据库负载过大而造成异步复制的延迟,Shard架构有效的分散了系统负载,从而大大减轻了这一现象,但是并不能从根本上消除,解决这一问题还是要靠良好的应用设计。

         当用户访问并更新Shard数据时,Flickr采用了将用户“粘”到某一机器的做法,

            $id = intval(substr($user_id, -10));

            $id % $count_of_hosts_in_shard

         即同一用户每次登录的所有操作其实都是在Shard中的一个Master上运行的,这样即使复制到Slave,也就是另一台Master的时候有延时,也不会对用户有影响,除非是用户刚刚更新,尚未复制而这台Master就出现故障了,不过这种几率应该很小吧。

         对于Central Database的复制滞后和同步问题,Flickr采用了一种复杂的“Write Through Cache"的机制来处理:

        点看全图
        外链图片需谨慎,可能会被源头改

        "Write Through Cache"就是将所有的数据库”写“操作都先写入”Cache",然后由Cache统一去更新数据库的各个Node,“Write Through Cache"维护每一个Node的更新状态,当有读请求时,即将请求转向状态为”已同步“的Node,这样即避免了复制滞后和Memcached的同步问题,但缺点是其实现极为复杂,“Write Throug Cache"层的代码需要考虑和实现所有”journal","Transaction“,“failover”,和“recovery"这些数据库已经实现的功能,另外还要考虑自身的"failover"问题。我没有找到有关具体实现的说明,只能猜测这一部分的处理可能也是直接利用或是实现了类似于Flickr的Queue系统吧。

         Flickr 网站架构研究的数据库部分到此结束,后面的重点将转向海量文件管理部分。

        元宝推荐:铁手,
        • 家园 《Flickr网站架构研究》读书笔记

          阅读了Flickr网站架构研究前三节,把自己对数据库使用的理解总结一下。这方面没有啥实际经验,总结得也很浅,有什么问题大家多多拍砖。

          数据库使用的总原则是在不影响数据库其他方面性能(如数据一致性)的前提下,尽可能提高数据库服务器集群的响应能力,应对更大的访问量。

          由于每台服务器的响应能力是相对固定的,因此基本方法是通过增加服务器数量来应对高并发。

          架设服务器集群有两个大致的思路。一个是以数据库服务器为单位,通过增加保存相同数据的服务器的数量来分摊压力,不考虑服务器上数据的性质。另一个是以数据为单位,通过分拆数据,在不同服务器上保存不同用途的数据来分摊压力。第一种思路对应master-master、master-slave这样的方案。第二种思路比较灵活,需要根据业务特点来选择拆分方法。拆分完毕后可以再利用第一种思路增加每个数据节点的响应能力。

          数据拆分从Flickr的经验看有这么几种:

          1.读、写拆分。一般来说,读的数量远大于写,因此可以通过增加备份数据库,分担读请求。

          2.根据业务分拆数据。例如Flickr中有专门保存用户主键和shard信息的数据库,有用户数据和照片元信息的数据库。

          3.根据用户拆分数据。同一用户的数据一般集中在一处,但不同用户的数据可以分别放在不同的机器上。这样通过增加机器数就可以应对更大用户量的访问。

          数据拆分比较灵活,和业务特点关系密切,需要根据实际情况来设计。

          还有一些和数据库应用相关的内容这里没有提,比如cache的应用,通过异步操作来降低数据库的压力等,都和数据库的设计有密切关系。

          暂时就想到这么多啦

分页树展主题 · 全看首页 上页
/ 5
下页 末页


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河