<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>DBA Notes</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/" />
    <link rel="self" type="application/atom+xml" href="http://www.dbanotes.net/atom.xml" />
   <id>tag:www.dbanotes.net,2012://1</id>
    <link rel="service.post" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1" title="DBA Notes" />
    <updated>2011-12-07T08:32:11Z</updated>
    <subtitle>SELECT blog FROM Fenng.Thoughts 
 WHERE subject IN (&apos;Startup&apos;, &apos;Database&apos;, &apos;Web Arch&apos;, &apos;UNIX&apos;, &apos;Web 2.0&apos;, &apos;OPENSOURCE&apos;) ; 

     
        Weblog
                 JobsDigg
CNOUG
                 Delicious
Twitter
                                  Articles
                 About
               </subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 5.06</generator>
 

<entry>
    <title>Instagram 架构分析笔记</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/instagram.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1498" title="Instagram 架构分析笔记" />
    <id>tag:www.dbanotes.net,2011://1.1498</id>
    
    <published>2011-12-07T07:11:44Z</published>
    <updated>2011-12-07T08:32:11Z</updated>
    
    <summary>Instagram 团队上个月才迎来第 7 名员工，是的，7个人的团队。作为 iPhone 上最火爆的图片类工具，instagram 用户数量已经超过 1400 万，图片数量超过 1.5 亿张。不得不说，这真他妈是个业界奇迹。

几天前，只有三个人的 Instagram 工程师团队发布了一篇文章：What Powers Instagram: Hundreds of Instances, Dozens of Technologies，披露了 Instagram 架构的一些信息，足够勾起大多数人的好奇心。读罢做点笔记，各种线索还是有一定参考价值的。能打开原文的建议直接读原文。



Instagram 开发团队奉行的三个核心原则：


	Keep it very simple (极简主义) 
	Don&apos;t re-invent the wheel (不重复发明轮子) 
	Go with proven and solid technologies when you can(能用就用靠谱的技术)


OS/主机
操作系统的选择，在Amazon EC2上跑 Ubuntu Linux 11.04 (Natty Narwhal) ，这个版本经过验证在 EC2 上够稳定。因为只有三名工程师，只有三名工程师，所以自己部署机器到 IDC 是不靠谱的事情。幸好有亚马逊。

负载均衡
此前曾用过两台 Nginx 做 DNS 轮询承载前端请求，这样做会有副作用，现在已经迁移到Amazon的ELB(Elastic Load Balancer)，起了三个 Nginx 实例，在 ELB 层停掉了 SSL , 以缓解 CPU 压力。DNS 服务使用 Amazon Route53 服务。 

应用服务器
启用了 25 个  Django 实例，运行在 High-CPU Extra-Large 类型的服务器实例上，之所以用 High-CPU Extra-Large 实例是因为应用请求是 CPU 密集型而非 IO 密集型。

使用 Gunicorn 作为 WSGI 服务器。过去曾用过 Apache 下的 mod_wsgi 模块，不过发现 Gunicorn 更容易配置并且节省 CPU 资源。使用 Fabric 加速部署。

数据存储

用户信息、图片元数据、标签等大部分数据存储在 PostgreSQL 中。主要的 Shard 数据库集群有 12个节点。

实践中发现 Amazon 的网络磁盘系统单位时间内寻道能力不行，所以有必要将数据尽量放到内存中。创建了软 RAID 以提升 IO 能力，使用的 Mdadm 工具进行 RAID 管理。

管理内存中的数据，vmtouch 这个小工具值得推荐。

PostgreSQL 设置为 Master-Replica 方式，流复制模式。利用 EBS 的快照进行数据库备份。使用 XFS 文件系统，以便和快照服务充分配合。 使用 repmgr 这个小工具做 PostgreSQL 复制管理器器。

连接池管理，用了 Pgbouncer。Christophe Pettus 的文章包含了不少 PostgreSQL 数据库的信息。

TB 级别的海量图片存储在 Amazon S3 上，CDN 采用的也是 Amazon 的服务，CloudFront。

Instagram 也是 Redis 的重度用户，Feed 以及 Session 信息都用 Redis 处理，Redis 也是以 Master-Replica 方式部署。在 Replica 节点上进行数据备份。

使用了 Apache Solr 承担  Geo-search API 的工作，Solr 简单的 JSON 接口也不错。

缓存使用了 6 个 Memcached 实例，库使用  pylibmc 和 libmemcached。亚马逊也提供缓存服务－Elastic Cache service ，Instagram 也有尝试，不过不便宜。

任务队列/发布通知

队列服务使用  Gearman ，通知系统则使用 pyapns 来实现。

监控

前面提及的服务器实例数量加起来，的确有100多个，有效的监控是相当有必要的。使用  Munin 作为主要监控工具 , 也写了不少定制插件，外部监控用 Pingdom 的服务。通知服务使用  PagerDuty。

对于 Python 的错误报告，使用 Disqus 团队开源的  Sentry 来处理。

几个感想

0）轻装上阵说起来容易，做起来非常难。这也是 Instagram 团队目前最令人着迷的地方；

1）Python 社区已经足够成熟，各个环节上都已经有不错的解决方案了。

2）如果要问我最大的一个感慨，我要说：Amazon 真是一家伟大的公司，甚至比 Google 还伟大。

--EOF--</summary>
    <author>
        <name>Fenng</name>
        <uri>http://www.dbanotes.net</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<p><a href="http://instagr.am">Instagram</a> 团队上个月才迎来第 7 名员工，是的，7个人的团队。作为 iPhone 上最火爆的图片类工具，instagram 用户数量已经超过 1400 万，图片数量超过 1.5 亿张。不得不说，这真他妈是个业界奇迹。</p>

<p>几天前，只有三个人的 Instagram 工程师团队发布了一篇文章：<a href="http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances-dozens-of">What Powers Instagram: Hundreds of Instances, Dozens of Technologies</a>，披露了 Instagram 架构的一些信息，足够勾起大多数人的好奇心。读罢做点笔记，各种线索还是有一定参考价值的。能打开原文的建议直接读原文。</p>

<p><img alt="Instragram.png" src="http://www.dbanotes.net/Images/Instragram.png" width="302" height="84" class="mt-image-none" style="" /></p>

<p>Instagram 开发团队<strong>奉行</strong>的三个核心原则：</p>

<ul>
	<li>Keep it very simple (极简主义) </li>
	<li>Don't re-invent the wheel (不重复发明轮子) </li>
	<li>Go with proven and solid technologies when you can(能用就用靠谱的技术)</li>
</ul>

<p><strong>OS/主机</strong><br />
<p>操作系统的选择，在Amazon EC2上跑 Ubuntu Linux 11.04 (Natty Narwhal) ，这个版本经过验证在 EC2 上够稳定。因为只有三名工程师，只有三名工程师，所以自己部署机器到 IDC 是不靠谱的事情。幸好有亚马逊。</p></p>

<p><strong>负载均衡</strong><br />
<p>此前曾用过两台 Nginx 做 DNS 轮询承载前端请求，这样做会有副作用，现在已经迁移到Amazon的ELB(Elastic Load Balancer)，起了三个 Nginx 实例，在 ELB 层停掉了 SSL , 以缓解 CPU 压力。DNS 服务使用 Amazon Route53 服务。 </p></p>

<p><strong>应用服务器</strong><br />
<p>启用了 25 个  Django 实例，运行在 High-CPU Extra-Large 类型的服务器实例上，之所以用 High-CPU Extra-Large 实例是因为应用请求是 CPU 密集型而非 IO 密集型。</p></p>

<p>使用 <a href="http://gunicorn.org/">Gunicorn</a> 作为 WSGI 服务器。过去曾用过 Apache 下的 mod_wsgi 模块，不过发现 Gunicorn 更容易配置并且节省 CPU 资源。使用 <a href="http://fabric.readthedocs.org/en/1.3.3/index.html">Fabric</a> 加速部署。</p>

<p><strong>数据存储</strong></p>

<p>用户信息、图片元数据、标签等大部分数据存储在 PostgreSQL 中。主要的 Shard 数据库集群有 12个节点。</p>

<p>实践中发现 Amazon 的网络磁盘系统单位时间内寻道能力不行，所以有必要将数据尽量放到内存中。创建了软 RAID 以提升 IO 能力，使用的 <a href="http://en.wikipedia.org/wiki/Mdadm">Mdadm</a> 工具进行 RAID 管理。</p>

<p>管理内存中的数据，<a href="http://hoytech.com/vmtouch/vmtouch.c">vmtouch</a> 这个小工具值得推荐。</p>

<p>PostgreSQL 设置为 Master-Replica 方式，流复制模式。利用 EBS 的快照进行数据库备份。使用 XFS 文件系统，以便和快照服务充分配合。 使用 <a href="https://github.com/greg2ndQuadrant/repmgr">repmgr</a> 这个小工具做 PostgreSQL 复制管理器器。</p>

<p>连接池管理，用了 <a href="http://pgfoundry.org/projects/pgbouncer/">Pgbouncer</a>。<a href="http://thebuild.com/blog/">Christophe Pettus</a> 的文章包含了不少 <a href="http://thebuild.com/blog/">PostgreSQL</a> 数据库的信息。</p>

<p>TB 级别的海量图片存储在 Amazon S3 上，CDN 采用的也是 Amazon 的服务，CloudFront。</p>

<p>Instagram 也是 Redis 的重度用户，Feed 以及 Session 信息都用 Redis 处理，Redis 也是以 Master-Replica 方式部署。在 Replica 节点上进行数据备份。</p>

<p>使用了 Apache Solr 承担  Geo-search API 的工作，Solr 简单的 JSON 接口也不错。</p>

<p>缓存使用了 6 个 Memcached 实例，库使用  pylibmc 和 libmemcached。亚马逊也提供缓存服务－Elastic Cache service ，Instagram 也有尝试，不过不便宜。</p>

<p><strong>任务队列/发布通知</strong></p>

<p>队列服务使用  <a href="http://gearman.org/">Gearman</a> ，通知系统则使用<a href="https://github.com/samuraisam/pyapns"> pyapns</a> 来实现。</p>

<p><strong>监控</strong></p>

<p>前面提及的服务器实例数量加起来，的确有100多个，有效的监控是相当有必要的。使用  Munin 作为主要监控工具 , 也写了不少定制插件，外部监控用 <a href="http://pingdom.com/">Pingdom</a> 的服务。通知服务使用  <a href="http://www.pagerduty.com/">PagerDuty</a>。</p>

<p>对于 Python 的错误报告，使用 Disqus 团队开源的  <a href="http://pypi.python.org/pypi/django-sentry">Sentry</a> 来处理。</p>

<p><strong>几个感想</strong></p>

<p>0）轻装上阵说起来容易，做起来非常难。这也是 Instagram 团队目前最令人着迷的地方；</p>

<p>1）Python 社区已经足够成熟，各个环节上都已经有不错的解决方案了。</p>

<p>2）如果要问我最大的一个感慨，我要说：<strong>Amazon 真是一家伟大的公司，甚至比 Google 还伟大</strong>。</p>

<p>--EOF--</p>]]>
        
    </content>
</entry>

<entry>
    <title>Quora 用了哪些技术 ?</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/quora_tech.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1475" title="Quora 用了哪些技术 ?" />
    <id>tag:www.dbanotes.net,2011://1.1475</id>
    
    <published>2011-03-08T10:31:38Z</published>
    <updated>2011-03-08T12:26:11Z</updated>
    
    <summary>很多团队都在学习、研究 Quora 。前段时间看到这篇 Quora&apos;s Technology Examined ，阐述了 Quora 的技术架构，有一些值得关注的信息，记录并分享一下。

使用云计算服务

Quora 大量使用 Amazon EC2 与 S3 服务；操作系统部署的是 Ubuntu Linux，易于部署和管理；静态内容用 Cloudfront.服务分发，图片先传到 EC2 服务器，使用 Pyhon S3 API 处理后后传到 S3。

从开始就使用云计算服务的的好处是节省了大量人工维护硬件服务器的成本，当然这个做法在咱这片土地上不太可行。


（refer: Copyright )

Web 层与 CMS 

HAProxy 作为前端负载均衡服务器，反向代理服务器是 Nginx，Nginx 后面则是 Pylons (Pylons + Paste) , 承担动态 Web 请求。 

Webnode2 与 LiveNode 这两个内部系统承担创建、管理内容的重任，Webnode2 生成 HTML、CSS 与 JavaScript ，并且与 LiveNode 轻度耦合。LiveNode 的作用用以显示 Web 页面内容。用 Python、C++ 与 JavaScript 写的。特别提到用到了 jQuery 与 Cython。LiveNode 有可能开源。 

为什么用 Python?

前面已经提到了一些 Python 相关的技术组件。有意思的是从 Facebook 出来的团队居然用 Python 作为主要开发语言。Quora 对此有所解释: Facebook 选择 PHP 也并非是最佳选择，而是有历史原因。Quora 技术团队在考察了多个语言之后选择的 Python ，当然理由有一大堆，总体看来，并非很激进。 

通信处理

后端通信使用的是 Facebook 开源出来的 Thrift，除了开发接口简单之外，可能更为熟悉也是一个因素吧 :) Comet 服务器使用的是 Tornado，用以处理 Long polling 以及 Push 更新(不知道知乎用的什么?)，Tornado 是前 FriendFeed 技术团队开源的产品。 

实时搜索

因为 Sphinx 不能满足实时性方面的要求，Quora 启用了自己开发的搜索引擎，只使用了 Thrift 与 Python Unicode 库，此外没有用别的。Quora 的搜索比较特别，因为要对输入内容做关联并且要做有效提示，所以需要提供更好的前缀索引(Prefix indexing)功能。

Quora 搜索的实现还是挺有技术含量的，对后端的查询请求压力也不小(或许当前的并发请求量还没那么大)。对这个场景，做相关开发的朋友不妨仔细研究一下。如果大体框架类似，那么决定最后生出的因素很可能是那些细节。 

数据持久层

大量使用 MySQL 作为存储方案，Memcached 作 Cache 层。没有使用当前比较火爆的 NoSQL 相关产品。Quora 这样做有自己的理由，用户量级没有达到百万的 SNS 站点完全没必要用 NoSQL 的东西。或许以后 Quora 也会启用。 

创始人查理·奇弗（Charlie Cheever）与亚当·德安杰洛（Adam D&apos;Angelo）之前都在 Facebook ，所以，Quora 的技术还真有不少 Facebook 的基因。Quora 的团队规模并不大，做技术的估计十余人而已，这么紧凑的团队利用了这么多的技术与产品，可见很多人都是多面手了。这是国内技术团队需要向国外同行学习的地方。 

--EOF--

这只是一篇概要性的描述，如果要知道一些更为细节的东西，请看 Quora 上的相关评论，上文中已经给出相关链接。</summary>
    <author>
        <name>Fenng</name>
        <uri>http://www.dbanotes.net</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<p>很多团队都在学习、研究 Quora 。前段时间看到这篇 <a href="http://www.philwhln.com/quoras-technology-examined">Quora's Technology Examined</a> ，阐述了 Quora 的技术架构，有一些值得关注的信息，记录并分享一下。</p>

<p><strong>使用云计算服务</strong></p>

<p>Quora 大量使用 Amazon EC2 与 S3 服务；操作系统部署的是 Ubuntu Linux，易于部署和管理；静态内容用 Cloudfront.服务分发，图片先传到 EC2 服务器，使用 Pyhon S3 API 处理后后传到 S3。</p>

<p>从开始就使用云计算服务的的好处是节省了大量人工维护硬件服务器的成本，当然这个做法在咱这片土地上不太可行。</p>

<p><img alt="Quora_China_chat.png.scaled500.png" src="http://www.dbanotes.net/Images/Quora_China_chat.png.scaled500.png" width="500" height="271" class="mt-image-none" style="" /><br />
（refer: <a href="http://www.quoratown.com/56-quora-china.html">Copyright </a>)</p>

<p><strong>Web 层与 CMS </strong></p>

<p>HAProxy 作为前端负载均衡服务器，反向代理服务器是 Nginx，Nginx 后面则是 Pylons (<a href="http://spacepants.org/blog/pylons-paste-stack">Pylons + Paste</a>) , 承担动态 Web 请求。 </p>

<p>Webnode2 与 LiveNode 这两个内部系统承担创建、管理内容的重任，Webnode2 生成 HTML、CSS 与 JavaScript ，并且与 LiveNode 轻度耦合。LiveNode 的作用用以显示 Web 页面内容。用 Python、C++ 与 JavaScript 写的。特别提到用到了 jQuery 与 Cython。LiveNode 有可能开源。</p> 

<p><strong>为什么用 Python?</strong></p>

<p>前面已经提到了一些 Python 相关的技术组件。有意思的是从 Facebook 出来的团队居然用 Python 作为主要开发语言。Quora 对此有所<a href="http://www.quora.com/Why-did-Quora-choose-Python-for-its-development">解释</a>: Facebook 选择 PHP 也并非是最佳选择，而是有历史原因。Quora 技术团队在考察了多个语言之后选择的 Python ，当然理由有一大堆，总体看来，并非很激进。</p> 

<p><strong>通信处理</strong></p>

<p>后端通信使用的是 Facebook 开源出来的 <a href="http://incubator.apache.org/thrift/">Thrift</a>，除了开发接口简单之外，可能更为熟悉也是一个因素吧 :) <a href="http://en.wikipedia.org/wiki/Comet_%28programming%29">Comet</a> 服务器使用的是 <a href="http://www.tornadoweb.org/">Tornado</a>，用以处理 Long polling 以及 Push 更新(不知道<a href="http://www.zhihu.com/">知乎</a>用的什么?)，Tornado 是前 FriendFeed 技术团队开源的产品。</p> 

<p><strong>实时搜索</strong></p>

<p>因为 <a href="http://sphinxsearch.com/">Sphinx</a> 不能满足实时性方面的要求，Quora 启用了自己开发的搜索引擎，只使用了 Thrift 与 Python Unicode 库，此外没有用别的。Quora 的搜索比较特别，因为要对输入内容做关联并且要做有效提示，所以需要提供更好的前缀索引(Prefix indexing)功能。</p>

<p>Quora 搜索的实现还是挺有技术含量的，对后端的查询请求压力也不小(或许当前的并发请求量还没那么大)。对这个场景，做相关开发的朋友不妨仔细研究一下。如果大体框架类似，那么决定最后生出的因素很可能是那些细节。</p> 

<p><strong>数据持久层</strong></p>

<p>大量使用 MySQL 作为存储方案，Memcached 作 Cache 层。没有使用当前比较火爆的 NoSQL 相关产品。Quora 这样做有自己的<a href="http://www.quora.com/When-Adam-DAngelo-says-partition-your-data-at-the-application-level-what-exactly-does-he-mean">理由</a>，用户量级没有达到百万的 SNS 站点完全没必要用 NoSQL 的东西。或许以后 Quora 也会启用。</p> 

<p>创始人查理·奇弗（Charlie Cheever）与亚当·德安杰洛（Adam D'Angelo）之前都在 Facebook ，所以，Quora 的技术还真有不少 Facebook 的基因。Quora 的团队规模并不大，做技术的估计十余人而已，这么紧凑的团队利用了这么多的技术与产品，可见很多人都是多面手了。这是国内技术团队需要向国外同行学习的地方。</p> 

<p>--EOF--</p>

<p>这只是一篇概要性的描述，如果要知道一些更为细节的东西，请看 Quora 上的相关评论，上文中已经给出相关链接。</p>]]>
        
    </content>
</entry>

<entry>
    <title>Facebook 如何发布代码 (How Facebook Ships Code 译文)</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/facebook_how_facebook_ships_code.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1471" title="Facebook 如何发布代码 (How Facebook Ships Code 译文)" />
    <id>tag:www.dbanotes.net,2011://1.1471</id>
    
    <published>2011-02-10T12:09:55Z</published>
    <updated>2011-02-11T03:57:08Z</updated>
    
    <summary>按：这篇 How Facebook Ships Code 提供了大量的细节信息，之前已经有朋友提供了一个翻译版本，阅读之后发现有些许错误，并且原文有更新，所以基于前面的翻译版本我重新翻译了一个(完整的)版本。一并谢过。希望这个版本对大家也有所参考。

我对 Facebook 的运作方式着迷。这是个非常独特的环境，很难被复制（这个方式并不适合所有的公司，即使有些公司尝试过这么做）。下面这些笔记来自我和Facebook的许多朋友的交谈，关于他们开发、运维与软件发布等方面。

好像很多人都对 Facebook 感兴趣... 这家公司的工程师驱动文化(Developer-driven culture)已经被公众大加研究，并且其它其它公司也在探求是否/如何实现工程师驱动文化。Facebook 的内部流程实在够神秘，当然，工程师团队也会发布一些关于新功能以及部分内部系统公开备忘，不过这些大多数是&quot;说明&quot;类的文章(What)，而非讲述&quot;机制&quot;(How)... 所以，外部人员很难明白 Facebook 的创新以及如何比其它公司做到更有效的对服务进行优化。我作为外部人员尝试深入理解 Facebook 的运作，汇集了几个月来的这些观察信息。出于对信息来源的隐私保护，我去掉了特定功能/产品的名字。我又等了6个月以后才发布这些记录，所以，有些信息肯定过时了。我希望发布这些信息会有助于了解 Facebook 的管理机制如何在组织中进行决策的推行而非逐步陷入混轮...很难说这与 Facebook 的成败或是 Facebook 的产品协作相关。我相信很多面向消费者的互联网公司会从 Facebook 这个案例受益。

*非常*感谢那些帮助我整理这篇文章的 Facebook 内部的朋友们。也要感谢项 epriest 和 fryfrog 这样的朋友，他们协助我进行对本文进行校正、编辑。

记录：


	截止到2010年6月，Facebook有将近2000名员工，10个月前只有大约1100人，一年之间差不多翻了一番! 



	工程部和运维部是两个最大的部门，每个大概都有 400-500人。这两个部门人数大约占了公司的一半。



	产品经理(PM)与工程师的比例大约为1-7到1-10。



	每个工程师入职时，都要接受 4 到 6 周的 &quot;Boot Camp&quot; 培训，通过修复Bug 和听更资深的工程师的课程来熟悉 Facebook 系统。每次 Boot Camp 大约有 10% 的人无法完成课程而被淘汰。



	培训结束后，每个工程师都可以访问线上的数据库【标准课程&quot;能力越大，责任越大&quot; ( &quot;with great power comes great responsibility&quot;) 对此有阐释，另有一份明晰的&quot;不可触犯的天条&quot;，比如共享用户的隐私数据】。



	[修改, 感谢 fryfrog] &quot;Facebook 有非常牢靠的安全保障，以免有人（你可以想象内部有人有这个权限的）不小心/故意做了些糟糕的的事。如果你已经&quot;成为&quot;了需要别人支持的人，事由将被记录，并且有谨慎的审计。这里不允许钻空子。



	任何工程师都可以修改Facebook的代码库，签入(Check-in)代码。
	浓厚的工程师驱动文化。&quot;产品经理基本可以被忽略&quot;，这是Facebook一名员工的话。工程师可以修改流程的细节，重新安排工作任务，随时植入自己的想法。[评论] &quot;本文的作者是一个产品经理，所以这个论断引起里我的注意。你看完整篇文章后会发现，很显然，Facebook 的文化实际上是拥抱产品经理的实践的，所以，不是产品经理的角色被忽略，而是，这家公司的文化看上去是想让&quot;每个人&quot;感受到对产品的责任&quot;。

在每月的跨部门会议上，由工程师来汇报工作进度，市场部和产品经理会出席会议，也可以做些简短的发言，但如果长篇大论的话，将如实反馈给他们的主管，&quot;产品人员在上次会议说的太多&quot;。他们确实想让工程师来主导产品的开发，对自己的产品负责。



	项目需要的资源都是自发征集的：

	某个产品经理把工程师们召集起来，让他们对自己的想法产生兴趣。
	工程师们决定开发那些让他们感兴趣的特性。
        工程师跟他们的经理说：&quot;我下周想开发这5个新特性&quot;。
	经理会让工程师独立开发，可能有时会让他优先完成一些特性。
	工程师独立完成所有的特性 -- 前端 JavaScript/后端数据库，等等所有相关的部分。如果需要得到设计人员的帮助，需要先让设计人员对你的想法产生兴趣(专职的设计师很少)。请架构师帮忙也是如此。但总体来说，工程师要独立完成所有的任务。

 

	对于某个特性是否值得开发的争执，通常是这么解决的：花一个星期的时间实现，并在小部分用户中(如1%的内华达的用户)进行测试。



	工程师通常乐衷致力于架构、扩展性以及解决&quot;难题&quot;，那样能获得声望和尊敬。他们很难对前端项目或用户界面产生太大的兴趣。这跟其他业务为导向的公司可能正好相反，那些公司人人都想做客户能直接接触到的东西，然后会指着某个特定的用户体验说，&quot;那是我做的&quot;。在 Facebook，后端的东西，比如 News Feed 算法、广告投放算法、Memcache 优化等等，是工程师真正倾慕的项目。



	News Feed 因为太重要了，扎克会亲自审查任何变动。这是个特例。



	[更正, 感谢 epriest ]&quot;所有的代码变更都要经过强制性的代码审查（比如一个或者多个工程师）。我相信这篇文章只是说 扎克并不自己审查每一个变更&quot;。




	[更正, 感谢 fryfrog ]&quot;所有的修改至少要被一个人审查，而且这个系统可以让任何人很方便地审核其他人的代码，即使你没有邀请他。提交未经审查的代码，将被视为恶意行为&quot;。



	工程师负责测试、Bug 修复以及启动对自己项目的维护。有单元测试和集成测试的框架可用，但很少使用。


	[更正, 感谢 fryfrog ] &quot;补充一下，我们是有 QA 的，只是没有正式的 QA 组而已。每个办公室或通过VPN连接的员工会使用下一版的 Facebook，这个版本的 Facebook 会经常更新，通常比公开的早 1-12 小时。所有的员工被强烈建议提交 Bug，而且通常会很快被修复&quot;。



	回复：很奇怪只有很少的 QA 或自动测试 -- &quot;大部分工程师都能写出基本没有bug的代码，只是在其他公司他们不需要这么做。如果有 QA 部门，他们只要把代码写完，扔给他们就行了&quot; [编辑：请注意这是很主观的，我选择包括这部分内容是因为这和那些其它公司的标准开发实践完全相反]



	回复：很奇怪，缺少产品经理的影响和控制 -- 产品经理是很独立的和自由的。产生影响力的关键是与工程师和工程师的管理者搞好关系。需要大致了解技术，不要提一些愚蠢的想法。



	默认情况下，所有提交的代码每打包一次（周二）。



	只要多一分努力，终于一天会发生改变。



	星期二的代码发布，需要所有提交过代码的工程师在场。

  

	发布开始前，工程师必须在一个特定的 IRC 频道上候命，否则将会被公开问责。



	运维团队通过逐步滚动的方式进行代码发布：


Facebook 有大约 60000 台服务器。
有9个代码发布级别。
[更正 感谢 eriest] &quot;九个级别并非同轴的(concentric)。有三个同轴的阶段(p1=内部发布, p2=小范围外部发布, p3=完整的外部发布)，其余六个阶段是辅助层，比如内部工具、视频上传主机等等&quot;。
	最小的级别只有6台服务器。
	比如，星期二的代码发布会先发布到 6 台服务器上（第一级），运维组会观测这 6 台服务器，保证代码正常工作，然后再提交到下一级。
	如果发布出现了问题（如报错等等），那么就停止下一级的部署，提交出错代码的工程师负责修复问题，然后从头继续发布。
	所以一次发布可能会经历几次重复：1-2-3-修复，回到 1， 1-2-3-4-5-修复， 回到1， 1-2-3-4-5-6-7-8-9。



	运维团队受过严格训练，很受尊敬，而且极具有业务意识。他们的工作指标不止包括分析错误日志，负载和内存使用状态等等，还包括用户行为。比如，如果一个新的发布导致一定比例的用户对 Facebook 功能进行声讨，运维团队将查看相关指标，可能基于他们的调查停掉该次发布。



	在发布过程中，运维组使用基于 IRC 的通知系统，可以通过 Facebook、Email、IRC、IM SMS 通知每一个工程师，如果需要他们注意的话。对运维组不做回应会被公开问责。



	代码一旦发布到第9级，并且稳定运行，本周的发布宣告结束 。



	如果一个特性没有按时完成，也没什么大不了的(除非外部依赖严重)，下次完成时一并发布即可。



	如果被 SVN-blamed(应该指没按照规范提交代码会受到的惩罚)、公开问责(Public shamed, 示众？还是通告批评？）或工作经常疏忽就很可能被开除。&quot;这是一个高效的文化&quot;。不够高效或者不够聪明的员工会被剔除。管理层会在 6 个月的时间里观察你表现，&quot;你不能适应这种文化，只能说再见&quot;。每一级都是这个待遇，即使是 C 级别和 VP 级别，如果不够高效，也会被开除。



	[更正, 感谢 epriest ] &quot;人们不会因为导致 Bug 而被解雇，只有在发布他们的代码时导致问题，而他们恰恰又不在场（也找不到其他可以替代的人）&quot;。



	[更正, 感谢 epriest] &quot;被问责不会导致解雇。我们特别尊重别人，原谅别人。大部分高级工程师都或多或少犯过一些严重的错误，包括我。但没有人因此被解雇&quot;。



	[更正, 感谢 fryfrog] &quot;我也没有遇到过因为上面提到过的犯错而被解雇。我知道有人不小心将整个网站宕掉过。一旦有人犯错，他们会竭尽全力修复问题，也让其他人得到了教训。就我来看，这种公然蒙羞与被解雇的恐惧相比更为奏效&quot;。


分析 Facebook 的研发文化如何随着时间演化是件非常有趣的事。特别是当公司发展壮大到数千员工的时候，这种文化是否还能够延续？

你觉得如何？在你公司里，&quot;开发者驱动(developer-driven)文化&quot; 将会可行么？


译者后记：很多时候是管中窥豹也是非常有趣的，而且，应该细致一点儿。另外，或许我们更应该关注为什么 Facebook 能够形成这样的文化。你说呢？

译者后记续：Facebook 能形成工程师主导的文化，应该和 Facebook 的产品形态有很大关系。毕竟 Facebook 人人都会用 Facebook ... 换言之，如果是 Amazon / eBay 这样面向商业的用户的公司，业务逻辑会让工程师陷入五里雾中。

--EOF--

延伸阅读：Hacker News: What I Learned from Zuckerberg&apos;s Mistakes
</summary>
    <author>
        <name>Fenng</name>
        <uri>http://www.dbanotes.net</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<blockquote><p>按：这篇 <a href="http://framethink.wordpress.com/2011/01/17/how-facebook-ships-code/">How Facebook Ships Code</a> 提供了大量的细节信息，之前已经有朋友提供了一个<a href="http://blog.leezhong.com/translate/2011/01/18/how-facebook-ships-code.html">翻译版本</a>，阅读之后发现有些许错误，并且原文有更新，所以基于前面的翻译版本我重新翻译了一个(完整的)版本。一并谢过。希望这个版本对大家也有所参考。</p></blockquote>

<p>我对 Facebook 的运作方式着迷。这是个非常独特的环境，很难被复制（这个方式并不适合所有的公司，即使有些公司尝试过这么做）。下面这些笔记来自我和Facebook的许多朋友的交谈，关于他们开发、运维与软件发布等方面。</p>

<p>好像很多人都对 Facebook 感兴趣... 这家公司的工程师驱动文化(Developer-driven culture)已经被公众<a href="http://goo.gl/fLuNF">大加研究</a>，并且其它其它公司也在<a href="http://blogs.forrester.com/tom_grant/11-01-17-product_management_you_get_what_you_pay_for?cm_mmc=RSS-_-IT-_-942-_-blog_1887">探求是否/如何实现工程师驱动文化</a>。Facebook 的内部流程实在够神秘，当然，工程师团队也会发布一些关于新功能以及部分内部系统<a href="http://www.facebook.com/notes.php?id=9445547199">公开备忘</a>，不过这些大多数是"说明"类的文章(What)，而非讲述"机制"(How)... 所以，外部人员很难明白 Facebook 的创新以及如何比其它公司做到更有效的对服务进行优化。我作为外部人员尝试深入理解 Facebook 的运作，汇集了几个月来的这些观察信息。出于对信息来源的隐私保护，我去掉了特定功能/产品的名字。我又等了6个月以后才发布这些记录，所以，有些信息肯定过时了。我希望发布这些信息会有助于了解 Facebook 的管理机制如何在组织中进行决策的推行而非逐步陷入混轮...很难说这与 Facebook 的成败或是 Facebook 的产品协作相关。我相信很多面向消费者的互联网公司会从 Facebook 这个案例受益。</p>

<p>*非常*感谢那些帮助我整理这篇文章的 Facebook 内部的朋友们。也要感谢项 <a href="http://www.reddit.com/user/epriest">epriest</a> 和<a href="http://www.reddit.com/user/fryfrog"> fryfrog</a> 这样的朋友，他们协助我进行对本文进行校正、编辑。</p>

<p>记录：</p>

<ul>
	<li>截止到2010年6月，Facebook有将近2000名员工，10个月前只有大约1100人，一年之间差不多翻了一番! </li>
</ul>

<ul>
	<li>工程部和运维部是两个最大的部门，每个大概都有 400-500人。这两个部门人数大约占了公司的一半。</li>
</ul>

<ul>
	<li>产品经理(PM)与工程师的比例大约为1-7到1-10。</li>
</ul>

<ul>
	<li>每个工程师入职时，都要接受 4 到 6 周的 "Boot Camp" 培训，通过修复Bug 和听更资深的工程师的课程来熟悉 Facebook 系统。每次 Boot Camp 大约有 10% 的人无法完成课程而被淘汰。</li>
</ul>

<ul>
	<li>培训结束后，每个工程师都可以访问线上的数据库【标准课程"能力越大，责任越大" ( "with great power comes great responsibility") 对此有阐释，另有一份明晰的"不可触犯的天条"，比如共享用户的隐私数据】。</li>
</ul>

<ul>
	<li>[修改, 感谢 fryfrog] "Facebook 有非常牢靠的安全保障，以免有人（你可以想象内部有人有这个权限的）不小心/故意做了些糟糕的的事。如果你已经"成为"了需要别人支持的人，事由将被记录，并且有谨慎的审计。这里不允许钻空子。</li>
</ul>

<ul>
	<li>任何工程师都可以修改Facebook的代码库，签入(Check-in)代码。</li>
	<li>浓厚的工程师驱动文化。"产品经理基本可以被忽略"，这是Facebook一名员工的话。工程师可以修改流程的细节，重新安排工作任务，随时植入自己的想法。[评论] "本文的作者是一个产品经理，所以这个论断引起里我的注意。你看完整篇文章后会发现，很显然，Facebook 的文化实际上是拥抱产品经理的实践的，所以，不是产品经理的角色被忽略，而是，这家公司的文化看上去是想让"每个人"感受到对产品的责任"。</li></ul>
<ul>
<li>在每月的跨部门会议上，由工程师来汇报工作进度，市场部和产品经理会出席会议，也可以做些简短的发言，但如果长篇大论的话，将如实反馈给他们的主管，"产品人员在上次会议说的太多"。他们确实想让工程师来主导产品的开发，对自己的产品负责。</li>
</ul>

<ul>
	<li>项目需要的资源都是自发征集的：</li>
</ul><blockquote><ul>
	<li>某个产品经理把工程师们召集起来，让他们对自己的想法产生兴趣。</li>
	<li>工程师们决定开发那些让他们感兴趣的特性。</li>
        <li>工程师跟他们的经理说："我下周想开发这5个新特性"。</li>
	<li>经理会让工程师独立开发，可能有时会让他优先完成一些特性。</li>
	<li>工程师独立完成所有的特性 -- 前端 JavaScript/后端数据库，等等所有相关的部分。如果需要得到设计人员的帮助，需要先让设计人员对你的想法产生兴趣(专职的设计师很少)。请架构师帮忙也是如此。但总体来说，工程师要独立完成所有的任务。</li>
</ul></blockquote>
 
<ul>
	<li>对于某个特性是否值得开发的争执，通常是这么解决的：花一个星期的时间实现，并在小部分用户中(如1%的内华达的用户)进行测试。</li>
</ul>

<ul>
	<li>工程师通常乐衷致力于架构、扩展性以及解决"难题"，那样能获得声望和尊敬。他们很难对前端项目或用户界面产生太大的兴趣。这跟其他业务为导向的公司可能正好相反，那些公司人人都想做客户能直接接触到的东西，然后会指着某个特定的用户体验说，"那是我做的"。在 Facebook，后端的东西，比如 News Feed 算法、广告投放算法、Memcache 优化等等，是工程师真正倾慕的项目。</li>
</ul>

<ul>
	<li>News Feed 因为太重要了，扎克会亲自审查任何变动。这是个特例。</li>
</ul>

<ul>
	<li>[更正, 感谢 epriest ]"所有的代码变更都要经过强制性的代码审查（比如一个或者多个工程师）。我相信这篇文章只是说 扎克并不自己审查每一个变更"。</li>

</ul>

<ul>
	<li>[更正, 感谢 fryfrog ]"所有的修改至少要被一个人审查，而且这个系统可以让任何人很方便地审核其他人的代码，即使你没有邀请他。提交未经审查的代码，将被视为恶意行为"。</li>
</ul>

<ul>
	<li>工程师负责测试、Bug 修复以及启动对自己项目的维护。有单元测试和集成测试的框架可用，但很少使用。</li>
</ul>
<ul>
	<li>[更正, 感谢 fryfrog ] "补充一下，我们是有 QA 的，只是没有正式的 QA 组而已。每个办公室或通过VPN连接的员工会使用下一版的 Facebook，这个版本的 Facebook 会经常更新，通常比公开的早 1-12 小时。所有的员工被强烈建议提交 Bug，而且通常会很快被修复"。</li>
</ul>

<ul>
	<li>回复：很奇怪只有很少的 QA 或自动测试 -- "大部分工程师都能写出基本没有bug的代码，只是在其他公司他们不需要这么做。如果有 QA 部门，他们只要把代码写完，扔给他们就行了" [编辑：请注意这是很主观的，我选择包括这部分内容是因为这和那些其它公司的标准开发实践完全相反]</li>
</ul>

<ul>
	<li>回复：很奇怪，缺少产品经理的影响和控制 -- 产品经理是很独立的和自由的。产生影响力的关键是与工程师和工程师的管理者搞好关系。需要大致了解技术，不要提一些愚蠢的想法。</li>
</ul>

<ul>
	<li>默认情况下，所有提交的代码每打包一次（周二）。</li>
</ul>

<ul>
	<li>只要多一分努力，终于一天会发生改变。</li>

</ul>
<ul>
	<li>星期二的代码发布，需要所有提交过代码的工程师在场。</li>
</ul>
  
<ul>
	<li>发布开始前，工程师必须在一个特定的 IRC 频道上候命，否则将会被公开问责。</li>
</ul>

<ul>
	<li>运维团队通过逐步滚动的方式进行代码发布：</li>
</ul>

<blockquote><ul><li>Facebook 有大约 60000 台服务器。</li>
<li>有9个代码发布级别。</li>
<li>[更正 感谢 eriest] "九个级别并非同轴的(concentric)。有三个同轴的阶段(p1=内部发布, p2=小范围外部发布, p3=完整的外部发布)，其余六个阶段是辅助层，比如内部工具、视频上传主机等等"。</li>
	<li>最小的级别只有6台服务器。</li>
	<li>比如，星期二的代码发布会先发布到 6 台服务器上（第一级），运维组会观测这 6 台服务器，保证代码正常工作，然后再提交到下一级。</li>
	<li>如果发布出现了问题（如报错等等），那么就停止下一级的部署，提交出错代码的工程师负责修复问题，然后从头继续发布。</li>
	<li>所以一次发布可能会经历几次重复：1-2-3-修复，回到 1， 1-2-3-4-5-修复， 回到1， 1-2-3-4-5-6-7-8-9。</li>
</ul></blockquote>

<ul>
	<li>运维团队受过严格训练，很受尊敬，而且极具有业务意识。他们的工作指标不止包括分析错误日志，负载和内存使用状态等等，还包括用户行为。比如，如果一个新的发布导致一定比例的用户对 Facebook 功能进行声讨，运维团队将查看相关指标，可能基于他们的调查停掉该次发布。</li>
</ul>

<ul>
	<li>在发布过程中，运维组使用基于 IRC 的通知系统，可以通过 Facebook、Email、IRC、IM SMS 通知每一个工程师，如果需要他们注意的话。对运维组不做回应会被公开问责。</li>
</ul>

<ul>
	<li>代码一旦发布到第9级，并且稳定运行，本周的发布宣告结束 。</li>
</ul>

<ul>
	<li>如果一个特性没有按时完成，也没什么大不了的(除非外部依赖严重)，下次完成时一并发布即可。</li>
</ul>

<ul>
	<li>如果被 SVN-blamed(应该指没按照规范提交代码会受到的惩罚)、公开问责(Public shamed, 示众？还是通告批评？）或工作经常疏忽就很可能被开除。"这是一个高效的文化"。不够高效或者不够聪明的员工会被剔除。管理层会在 6 个月的时间里观察你表现，"你不能适应这种文化，只能说再见"。每一级都是这个待遇，即使是 C 级别和 VP 级别，如果不够高效，也会被开除。</li>
</ul>

<ul>
	<li>[更正, 感谢 epriest ] "人们不会因为导致 Bug 而被解雇，只有在发布他们的代码时导致问题，而他们恰恰又不在场（也找不到其他可以替代的人）"。</li>
</ul>

<ul>
	<li>[更正, 感谢 epriest] "被问责<strong>不会</strong>导致解雇。我们特别尊重别人，原谅别人。大部分高级工程师都或多或少犯过一些严重的错误，包括我。但没有人因此被解雇"。</li>
</ul>

<ul>
	<li>[更正, 感谢 fryfrog] "我也没有遇到过因为上面提到过的犯错而被解雇。我知道有人不小心将整个网站宕掉过。一旦有人犯错，他们会竭尽全力修复问题，也让其他人得到了教训。就我来看，这种公然蒙羞与被解雇的恐惧相比更为奏效"。</li>
</ul>

<p>分析 Facebook 的研发文化如何随着时间演化是件非常有趣的事。特别是当公司发展壮大到数千员工的时候，这种文化是否还能够延续？</p>

<p>你觉得如何？在你公司里，"开发者驱动(developer-driven)文化" 将会可行么？</p>
<br />

<p>译者后记：很多时候是管中窥豹也是非常有趣的，而且，应该细致一点儿。另外，或许我们更应该关注为什么 Facebook 能够形成这样的文化。你说呢？</p>

<p>译者后记续：Facebook 能形成工程师主导的文化，应该和 Facebook 的产品形态有很大关系。毕竟 Facebook 人人都会用 Facebook ... 换言之，如果是 Amazon / eBay 这样面向商业的用户的公司，业务逻辑会让工程师陷入五里雾中。</p>

<p>--EOF--</p>

<p>延伸阅读：<a href="http://news.ycombinator.com/item?id=2005938">Hacker News: What I Learned from Zuckerberg's Mistakes</a><br />
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Foursquare 长达 11 小时的宕机</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/foursquare_outage.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1455" title="Foursquare 长达 11 小时的宕机" />
    <id>tag:www.dbanotes.net,2010://1.1455</id>
    
    <published>2010-10-08T04:37:03Z</published>
    <updated>2010-10-10T05:56:37Z</updated>
    
    <summary>今天是个值得庆贺的日子

前几天 Foursquare 经历了长达 11 个小时的宕机，没错，11 个小时。网站官方的解释是 Shard 负载不均匀造成后续的连锁反应。很多人都知道 Foursquare 在线的 DB 是 MongoDB，今天又看到 10gen (MongoDB的开发与支持团队)的 Eliot Horowitz 在得到 Foursquare 许可后，通过邮件组详细介绍了宕机的过程：Foursquare outage post mortem，不用说，也有为 MongoDB 辟谣的意味在里面。

读罢 10gen 团队的介绍（或者说解释）之后，发现这是一个很好的研究样本。值得分享。

为了提高响应速度，Foursquare 使用 MongoDB 存储 Check-in 的数据已经有一段时间了。这部分数据的数据库起初跑在一个 66GB 内存的 Amazon EC2 单实例上（全部在内存里），两个月前，出于对容量增长的考虑，迁移到两台 Shard 集群上。每个 Shard 机器都是 66GB 内存，为了冗余，每个 Shard 都有复制到 Slave 实例。迁移的目标是所有的 Check-in 数据都保存在内存中。数据根据 ID 分成 200 个 Shard 分片，两台机器各占一半，也就说联机数据在每台机器上各使用 33GB 的内存。两个月相安无事。

问题来了，因为 Shard 算法导致的数据分散不均衡，其中一台(Shard0)数据增长到 67GB(另外一台 50GB)，超过了 66GB 的限制，读写部分分散到磁盘上，性能急剧下降。从而，网站宕机。

首先尝试增加第三台 Shard 机器，上线后开始迁移，读取从三台进行，Shard0 的数据迁移到 5% 的时候，但是写操作还是让 Shard0 宕机了。这个时候发现Shard0 存在数据碎片(data fragmentation)，即使数据迁移走，还是会占用原来的内存。每个Check-in 文档大约占用 300 字节，而 MongoDB 是 4KB 的页(Page)，也就说十几个文档会填满一个页，而迁移 5% 反而造成了页更加稀疏，并不是将页全部删除。

这个时候已经到了第二天，随着网站全面宕机，技术团队开始用 MongoDB 的 repairDatabase() 功能来对数据库进行压缩，因为数据库太大和 EBS 慢，也因为 repairDatabase() 不能充分利用多核CPU 的能力，这个过程耗费了 4 个小时。之后这 5% 的内存空间终于释放出来，系统重新上线。

随着 Shard0 修复，第三台成功上线，进而添加了更多的 Shard 服务器，现在数据已经更加的均衡，通过在Slave上运行 repairDatabase()，然后将其切换到 Master ，每台 Shard 内存占用缩减到 20GB左右。整个故障时间已经延续了 11 小时之多。

产生问题的主要原因就是系统过载，前面介绍每台 Shard 承载原来 50% 的压力，到了问题发生的时候，单台 Shard 的负载已经超过 Shard 之前的系统负载，这时候已经积重难返了，在容量的临界点增加新系统资源，必然导致更多的停机时间。暴露了 Foursquare 团队在容量规划方面的不足之处，或许也因为业务增长太快了吧。另外，内存碎片化的问题在没有宕机之前，技术团队应该没考虑过这个问题，如果文档的大小超过 4K，碎片化问题就不严重了，这是特定应用场景造成的特定问题。10Gen 现在已经着手研究如何进在线压缩(online compaction)。再次，Shard 键值的顺序和插入顺序是不同的，这造成了迁移数据的时候 Chunk 的迁移不是连续的。

这个过程给我们的启示是：最近 NoSQL 已经成为一个热词，类似 MongoDB 这样的新事物当然值得尝试，但是不能冒进，因为驾驭起来并非易事。仅仅能够使用是不够的，系统没出问题一切都好，一旦出了异常，有足够的技术力量(设想一下 Foursquare 得不到 10gen 团队的支持会如何?) 支持么？在极端情况下如何控制？ 如果回答不了这个问题，那么还应该暂缓。最好的办法就是...&quot;等待&quot;。

给我的另一个感慨是 Amazon 在云计算领域已经真的成为一个赢家，而且越来越得到 Web 2.0 Startup的信赖。前面说的 66GB 内存，应该指的是EC2 的 &quot;High-Memory Double Extra Large Instance&quot;，可提供的最大内存是 68.4 GB 。CPU 和内存能力都是可以接受的，存储方面的性能似乎还有点不足，也就是其中的 EBS ，指的是 Amazon Elastic Block storage。 

--EOF--</summary>
    <author>
        <name>Fenng</name>
        <uri>http://www.dbanotes.net</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<pre>今天是个值得庆贺的日子</pre>

<p>前几天 <a href="http://foursquare.com/">Foursquare</a> 经历了长达 11 个小时的宕机，没错，11 个小时。网站官方的<a href="http://blog.foursquare.com/2010/10/05/so-that-was-a-bummer/">解释</a>是 Shard 负载不均匀造成后续的连锁反应。很多人都知道 Foursquare 在线的 DB 是 <a href="http://www.mongodb.org/">MongoDB</a>，今天又看到 <a href="http://www.10gen.com/">10gen</a> (MongoDB的开发与支持团队)的 Eliot Horowitz 在得到 Foursquare 许可后，通过邮件组详细介绍了宕机的过程：<a href="http://groups.google.com/group/mongodb-user/browse_thread/thread/528a94f287e9d77e#">Foursquare outage post mortem</a>，不用说，也有为 MongoDB 辟谣的意味在里面。</p>

<p>读罢 10gen 团队的介绍（或者说解释）之后，发现这是一个很好的研究样本。值得分享。</p>

<p>为了提高响应速度，Foursquare 使用 MongoDB 存储 Check-in 的数据已经有一段时间了。这部分数据的数据库起初跑在一个 66GB 内存的 Amazon EC2 单实例上（全部在内存里），两个月前，出于对容量增长的考虑，迁移到两台 Shard 集群上。每个 Shard 机器都是 66GB 内存，为了冗余，每个 Shard 都有复制到 Slave 实例。迁移的目标是所有的 Check-in 数据都保存在内存中。数据根据 ID 分成 200 个 Shard 分片，两台机器各占一半，也就说联机数据在每台机器上各使用 33GB 的内存。两个月相安无事。</p>

<p>问题来了，因为 Shard 算法导致的数据分散不均衡，其中一台(Shard0)数据增长到 67GB(另外一台 50GB)，超过了 66GB 的限制，读写部分分散到磁盘上，性能急剧下降。从而，网站宕机。</p>

<p>首先尝试增加第三台 Shard 机器，上线后开始迁移，读取从三台进行，Shard0 的数据迁移到 5% 的时候，但是写操作还是让 Shard0 宕机了。这个时候发现Shard0 存在数据碎片(data fragmentation)，即使数据迁移走，还是会占用原来的内存。每个Check-in 文档大约占用 300 字节，而 MongoDB 是 4KB 的页(Page)，也就说十几个文档会填满一个页，而迁移 5% 反而造成了页更加稀疏，并不是将页全部删除。</p>

<p>这个时候已经到了第二天，随着网站全面宕机，技术团队开始用 MongoDB 的 repairDatabase() 功能来对数据库进行压缩，因为数据库太大和 EBS 慢，也因为 repairDatabase() 不能充分利用多核CPU 的能力，这个过程耗费了 4 个小时。之后这 5% 的内存空间终于释放出来，系统重新上线。</p>

<p>随着 Shard0 修复，第三台成功上线，进而添加了更多的 Shard 服务器，现在数据已经更加的均衡，通过在Slave上运行 repairDatabase()，然后将其切换到 Master ，每台 Shard 内存占用缩减到 20GB左右。整个故障时间已经延续了 11 小时之多。</p>

<p>产生问题的主要原因就是系统过载，前面介绍每台 Shard 承载原来 50% 的压力，到了问题发生的时候，单台 Shard 的负载已经超过 Shard 之前的系统负载，这时候已经积重难返了，在容量的临界点增加新系统资源，必然导致更多的停机时间。暴露了 Foursquare 团队在<strong>容量规划</strong>方面的不足之处，或许也因为业务增长太快了吧。另外，内存碎片化的问题在没有宕机之前，技术团队应该没考虑过这个问题，如果文档的大小超过 4K，碎片化问题就不严重了，这是特定应用场景造成的特定问题。10Gen 现在已经着手研究如何进在线压缩(online compaction)。再次，Shard 键值的顺序和插入顺序是不同的，这造成了迁移数据的时候 Chunk 的迁移不是连续的。</p>

<p>这个过程给我们的启示是：最近 NoSQL 已经成为一个热词，类似 MongoDB 这样的新事物当然值得尝试，但是不能冒进，因为驾驭起来并非易事。仅仅能够使用是不够的，系统没出问题一切都好，一旦出了异常，有足够的技术力量(设想一下 Foursquare 得不到 10gen 团队的支持会如何?) 支持么？<strong>在极端情况下如何控制？</strong> 如果回答不了这个问题，那么还应该暂缓。最好的办法就是..."等待"。</p>

<p>给我的另一个感慨是 Amazon 在云计算领域已经真的成为一个赢家，而且越来越得到 Web 2.0 Startup的信赖。前面说的 66GB 内存，应该指的是EC2 的 "High-Memory Double Extra Large Instance"，可提供的最大内存是 68.4 GB 。CPU 和内存能力都是可以接受的，存储方面的性能似乎还有点不足，也就是其中的 EBS ，指的是 Amazon Elastic Block storage。 </p>

<p>--EOF--</p>]]>
        
    </content>
</entry>

<entry>
    <title>从 C10K 到 C500K</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/c10k_c500k.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1454" title="从 C10K 到 C500K" />
    <id>tag:www.dbanotes.net,2010://1.1454</id>
    
    <published>2010-09-30T04:39:43Z</published>
    <updated>2010-09-30T07:06:54Z</updated>
    
    <summary>还在谈 C10K 的问题？这个已经过时了，现在大家已经开始说 C500K 。

国外的 Urban Airship 公司的工程师在其官方网志上发文章介绍他们在产品环境中做到 50 万并发客户端，Java + Pure NIO 的实现，最近又有文章介绍针对 Linux Kernel 调优的经验：Linux Kernel Tuning for C500k 。并且指出了&quot;单个 IP 最大并发数量上限为64K&quot;  只是一个误解。

硬件环境？操作系统为 Ubuntu(Lucid)，租用 Amazon 的 EC2 ，使用 EC2 Large instances，64 位操作系统，每个 7.5 GB 内存。

当然，Urban Airship 是做手机消息 Push 服务的（Android Push 架构），所以，如果你也要做到这样的并发，还要看你的应用场景是否合适。去年了解到曾在新浪、腾讯任职的杨建已经做到超过 20 万的 HTTP 并发(现在可能已经突破这个限制了)，非常的惊人。我非常想知道现在各个公司在这方面的实践数据。

--EOF--

另外参考：A Million-user Comet Application with Mochiweb

更新：杨建同学发来消息，去年已经单击突破 46.5万 Connections, 两块网卡, 1.5G 输出。10万请求处理每秒，每个响应 2k 左右。据说当时遇到一个坎一直没能过 50 万，不过这个坎三个月前已经过了，现在过 60 应该没悬念，四核双 CPU 机器。据杨建说，&quot;按现在 4 Core * 4CPU 的机器，我觉得可以冲刺 80~100万，前提需要4块网卡(千兆)&quot;。可见，把事情做到极致是没有极限的。

</summary>
    <author>
        <name>Fenng</name>
        <uri>http://www.dbanotes.net</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<p>还在谈 <a href="http://www.kegel.com/c10k.html">C10K</a> 的问题？这个已经过时了，现在大家已经开始说 <a href="http://blog.urbanairship.com/blog/2010/08/24/c500k-in-action-at-urban-airship/">C500K</a> 。</p>

<p>国外的 <a href="http://urbanairship.com/">Urban Airship</a> 公司的工程师在其官方网志上发文章介绍他们在产品环境中做到 50 万并发客户端，Java + Pure NIO 的实现，最近又有文章介绍针对 Linux Kernel 调优的经验：<a href="http://blog.urbanairship.com/blog/2010/09/29/linux-kernel-tuning-for-c500k/">Linux Kernel Tuning for C500k</a> 。并且指出了"单个 IP 最大并发数量上限为64K"  只是一个误解。</p>

<p>硬件环境？操作系统为 Ubuntu(Lucid)，租用 Amazon 的 EC2 ，使用 EC2 Large instances，64 位操作系统，每个 7.5 GB 内存。</p>

<p>当然，Urban Airship 是做手机消息 Push 服务的（Android Push 架构），所以，如果你也要做到这样的并发，还要看你的应用场景是否合适。去年了解到曾在新浪、腾讯任职的<a href="http://blog.sina.com.cn/u/1181509184">杨建</a>已经做到超过 20 万的 HTTP 并发(现在可能已经突破这个限制了)，非常的惊人。我非常想知道现在各个公司在这方面的实践数据。</p>

<p>--EOF--</p>

<p>另外参考：<a href="http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-1">A Million-user Comet Application with Mochiweb</a></p>

<p>更新：杨建同学发来消息，去年已经单击突破 46.5万 Connections, 两块网卡, 1.5G 输出。10万请求处理每秒，每个响应 2k 左右。据说当时遇到一个坎一直没能过 50 万，不过这个坎三个月前已经过了，现在过 60 应该没悬念，四核双 CPU 机器。据杨建说，"按现在 4 Core * 4CPU 的机器，我觉得可以冲刺 80~100万，前提需要4块网卡(千兆)"。可见，把事情做到极致是没有极限的。</p>]]>
        
    </content>
</entry>

<entry>
    <title>Get Architecture Done -《分布式Java应用：基础与实践》</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/get_architecture_done.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1435" title="Get Architecture Done -《分布式Java应用：基础与实践》" />
    <id>tag:www.dbanotes.net,2010://1.1435</id>
    
    <published>2010-06-29T04:36:15Z</published>
    <updated>2010-06-29T06:20:51Z</updated>
    
    <summary>按：承蒙林昊( @Bluedavy )看得起，嘱托我为他的大作《分布式Java应用：基础与实践》写序，倍感荣幸之余也颇有压力。读完本书的绝大部分章节后，这相信这会是我今年要向朋友们推荐的关于架构的图书。毕竟我在阿里系工作有年，对几家子公司的技术还算有所了解，内容有没有料还是可以一目了然的分辨的出来的。下文是推荐序。


　　
提起诸如&quot;高性能&quot;、&quot;高可用&quot;、&quot;大规模并发&quot;、&quot;可扩展性&quot;这些词汇，我相信多数技术人的心情都是激动而稍有点复杂的，当然，也或许是不屑一顾。毕竟不是谁都有机会面对这些富有挑战的技术场景，也不是每个架构师在面对这些挑战之前都能做好技术上的准备。那些意外故障总是不期而至，疲于奔命的解决问题的场景回顾起来对架构师来说犹如一场噩梦。
　　
本书阐述当一个面向数以亿计用户的网站经过几年高速发展，技术团队不得不面临大规模、高并发、高扩展性等挑战带来的技术困境的时候，一个出色的架构师经过多年一线实践后累积的经过时间考验的解决方案以及宝贵的实战经验。在这本书里，你会看到作者在解决一些关乎Web应用问题的指导原则、实践方法、多重工具的综合运用以及作者本人的感悟。要强调的是，本书讲述的内容是一个Web应用从小到大过程中遇到的棘手问题的解决之道，并非宏观解析，亦非屠龙之技。无论您面对的站点是大是小，皆会有参考作用，毕竟大站点会越来越复杂，而小站点总有一天也将变大。
　　
如今到计算机书店里走一下，会发现Java架构相关的技术图书业已不少，但仍有理由相信本书内容填补了在Java架构实战方面的空白。在互联网应用大行其道的今天，有些名义上主题为Java架构的图书，要么单从Java本身阐述，缺乏整体应用的大局观；要么是高屋建瓴，从编程思想的高度坐而论道，缺乏实践性；要么是闭门造车之作，缺乏验证性。本书作者林昊多年来致力于推动OSGi在国内的发展，不乏理论技术功底，而后加盟淘宝网 (Taobao.com)的几年间奋战在架构一线，爬摸滚打积累了丰富的实践心得。所以，本书是一本不折不扣的&quot;理论结合实践&quot;之作。
　　
考虑国内的技术图书出版环境以及必须尽力迎合读者的预期，写书本身是一件费力不讨好的事情，但将知识传递给更多人无疑是让人快乐的。现在，经过作者近两年的梳理与总结，这本书即将出版，相信您在研读本书之后有所收获并运用到您所面对的Web应用上，也期待将来有更多朋友能够分享架构实践经验，不亦快哉！

--EOF--
　　 </summary>
    <author>
        <name>Fenng</name>
        <uri>http://www.dbanotes.net</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<p>按：承蒙林昊( @<a href="http://www.twitter.com/bluedavy">Bluedavy</a> )看得起，嘱托我为他的大作<a href="http://book.douban.com/subject/4848587/">《分布式Java应用：基础与实践》</a>写序，倍感荣幸之余也颇有压力。读完本书的绝大部分章节后，这相信这会是我今年要向朋友们推荐的关于架构的图书。毕竟我在阿里系工作有年，对几家子公司的技术还算有所了解，内容有没有料还是可以一目了然的分辨的出来的。下文是推荐序。</p>

<hr />
　　
<p>提起诸如"高性能"、"高可用"、"大规模并发"、"可扩展性"这些词汇，我相信多数技术人的心情都是激动而稍有点复杂的，当然，也或许是不屑一顾。毕竟不是谁都有机会面对这些富有挑战的技术场景，也不是每个架构师在面对这些挑战之前都能做好技术上的准备。那些意外故障总是不期而至，疲于奔命的解决问题的场景回顾起来对架构师来说犹如一场噩梦。</p>
　　
<p>本书阐述当一个面向数以亿计用户的网站经过几年高速发展，技术团队不得不面临大规模、高并发、高扩展性等挑战带来的技术困境的时候，一个出色的架构师经过多年一线实践后累积的经过时间考验的解决方案以及宝贵的实战经验。在这本书里，你会看到作者在解决一些关乎Web应用问题的指导原则、实践方法、多重工具的综合运用以及作者本人的感悟。要强调的是，本书讲述的内容是一个Web应用从小到大过程中遇到的棘手问题的解决之道，并非宏观解析，亦非屠龙之技。无论您面对的站点是大是小，皆会有参考作用，毕竟大站点会越来越复杂，而小站点总有一天也将变大。</p>
　　
<p>如今到计算机书店里走一下，会发现Java架构相关的技术图书业已不少，但仍有理由相信本书内容填补了在Java架构实战方面的空白。在互联网应用大行其道的今天，有些名义上主题为Java架构的图书，要么单从Java本身阐述，缺乏整体应用的大局观；要么是高屋建瓴，从编程思想的高度坐而论道，缺乏实践性；要么是闭门造车之作，缺乏验证性。本书作者林昊多年来致力于推动<a href="http://www.osgi.org/">OSGi</a>在国内的发展，不乏理论技术功底，而后加盟<a href="http://www.taobao.com/">淘宝网</a> (Taobao.com)的几年间奋战在架构一线，爬摸滚打积累了丰富的实践心得。所以，本书是一本不折不扣的"<strong>理论结合实践</strong>"之作。</p>
　　
<p>考虑国内的技术图书出版环境以及必须尽力迎合读者的预期，写书本身是一件费力不讨好的事情，但将知识传递给更多人无疑是让人快乐的。现在，经过作者近两年的梳理与总结，这本书即将出版，相信您在研读本书之后有所收获并运用到您所面对的Web应用上，也期待将来有更多朋友能够分享架构实践经验，不亦快哉！</p>

<p>--EOF--<br />
　　 </p>]]>
        
    </content>
</entry>

<entry>
    <title>探索Google App Engine背后的奥秘(6)- 总结</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/google_app_engine-summary.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1434" title="探索Google App Engine背后的奥秘(6)- 总结" />
    <id>tag:www.dbanotes.net,2010://1.1434</id>
    
    <published>2010-06-15T18:48:43Z</published>
    <updated>2010-06-16T05:57:27Z</updated>
    
    <summary>按：此为客座博文系列。投稿人吴朱华曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。

本篇是本系列的最终章，将总结一下App Engine在使用方面的注意点，最佳实践和适用场景，最后会谈一下我对App Engine的一些期望。 

注意点

执行速度偏慢：由于其分布式的设计，所以在速度方面不是最优的，比如普通的Memcache能在几毫秒完成操作，而App Engine的Memcache则大概需要50(毫)秒才能完成操作。 
私有API：其API有很多都是私有，特别是在其服务方面，虽然Google提供了很不错的文档，但是在学习和移植等方面，成本都很高。 
执行会出现失败的情况：根据很多人的实际经验，App Engine会不定时出现执行失败的情况，特别是Datastore和URLFetch这两部分，虽然Google已经将Datastore方面出现错误的几率从原先的0.4降至现在的0.1，但是失败的情况是很难避免的。 
有时会停机：虽然总体而言，停机并不频繁，但是在今年初出现长达136分钟故障导致部分用户的应用无法正常运行，其发生原因来自于其备份数据中心出现了问题。 
无法选择合适的数据中心：比如，你应用所面对的用户主要在欧洲，但是你应用所属App Engine服务器却很有可能是被部署在一个美国的数据中心内，虽然你的应用很有可能在将来移动至欧洲某个数据中心，但是你却无法控制整个过程。 
有时会处理请求超时：虽然能平均在100至200ms之间完成海量的请求，但是有时会出现处理请求超时的情况。 
不支持裸域名：只支持类似CNAME的子域名。 


最佳实践

适应App Engine的数据模型：因为其数据模型，并不是传统的关系模式，而且在性能方面表现也和关系型数据库差别很大，所以如果想要用好非常关键的Datastore，那么理解和适应其数据模型是不可或缺的。 
对应用进行切分：由于App Engine对每个应用都有一定资源限制，而且为了让应用更SOA化和更模块化，可以对一个应用切分多个子应用，比如，可以分成一个用于前端的Web应用和多个用于REST服务的后台应用。 
极可能多地利用Memcache，这样不仅能减少昂贵的Datastore操作，而且能减轻Datastore的压力。 
在上面提到过，由于App Engine在执行某些操作时会出现失败的情况，比如Datastore方面，所以要在设计和实现这两方面做好相应的异常处理工作。 
由于Datastore不是关系型数据库，导致在执行常见的求总数操作时显的有点&quot;捉襟见肘&quot;，所以最好使用Google推荐的Sharded Counters技术来计算总数。 
由于Blobstore还只是刚走出试验期而已，而且其他模块对静态文件（比如图片等）支持不佳，比如Datastore只支持1MB以内的对象，同时每个应用只能最多上传一千个文件，而且速度不是最优，所以推荐使用其他专业的云存储，比如Amazon的S3或者Google马上就要推出的Google Storage等。 
尽量使用批处理方式，不论是在使用Datastore还是发送邮件等。 
不要手动创建Index：因为App Engine会自动根据你在代码中查询来创建相关的Index。 


适用场景

现在而言，App Engne主要适用于下面这三个场景：


Web Hosting：这是最常见的场景，在App Engine上已经部署了数以十万计的小型网站（其中有很多主要为了学习目的），而且还部署了一些突发流量很大的网站，其中最著名的例子就是美国白宫的&quot;Open For Questions&quot;这个站点，主要用于让美国人民给奥巴马总统提问的，这个站点在短短的几个小时内处理接近百万级别的流量。 
REST服务：这也是在App Engine平台上很常见的场景，最出名的例子就是BuddyPoke，BuddyPoke的客户端就是一个Flash应用，在用户的浏览器上运行，而它的服务器端则是以REST服务的形式放置在App Engine上，每当Flash客户端需要读取和存储数据的时候，它都会发请求给后端的REST服务，来让其执行相关的Datastore操作。 
依赖Google服务的应用：比如应用能够通过App Engine的Email服务来发送大规模的电子邮件。 


未来的期望

更稳定的表现，更少的超时异常和更快的反应速度，特别是在Datastore和Memcached这两方面。 
支持对数据中心的选择，虽然现在App Engine会根据应用的用户群的所在地来调整应用所在的数据中心，但由于整个过程对开发者而言是不可控的，所以希望能在创建应用的时候，能让用户自己选择合适的数据中心。 
SLA，如果App Engine能像S3那样设定一些SLA条款，这样将使用户更放心地在App Engine上部署应用。 
新的语言：比如PHP，但是如果在现有的App Engine架构上添加一门新的语言，整个工作量会非常大的，因为App Engine有接近一半的模块是语言特定的，比如应用服务器和开发环境等，所以短期内我认为不太可能支持新的语言。 


总体而言，Google App Engine是Google大战略中一个不可分割的一部分，因为Google希望能通过App Engine来降低Web应用开发的难度，只要难度降低了，那么Web应用替代客户端应用的整体速度将会加快，如果出现这样的情况的话，那么将会对Google今后的发展非常有利。

本系列文章结束。

参考资料：


Google&apos;s Dr. Kai-Fu Lee on Cloud Computing
The Cost of Latency 
Google App Engine Blog
Bigtable: A Distributed Storage System for Structured Data
From Spark Plug to Drive Train: Life of an App Engine Request
Google Megastore
Google App Engine官方文档
Google Architecture
Google App Engine - a first look
Google Chose Jetty for App Engine
Google App Engine is Down - Backup Data Center Having Problems
面向虚拟基础设施的云服务，第 2 部分: Platform as a Service (PaaS) 和 AppScale
传Google正在开发新的服务器文件系统
Google File System
Designs, Lessons and Advice from Building Large Distributed Systems
The Chubby lock service for loosely-coupled distributed systems
Google&apos;s Will Power and Data Center Efficiency
MapReduce
MapReduce的论文
Protocol Buffer 简介
Google data centers snub Africa, Oz, and anything near Wyoming Or do they?
Google揭秘服务器创新技术 内置电池替换UPS
开源数据库 Sharding 技术（Share Nothing） 
Google File System II: Dawn of the Multiplying Master Nodes
Transactions Across Datacenters
探秘Google全球数据中心与中国机房
揭开Google数据中心五大神话
俄勒冈州的Google数据中心耗电惊人
Google App Engine For Java - Microblogging Case Study
Under the covers of the App Engine Datastore
Google Megastore
Megastore/Bigtable Replication的文章


--EOF--
</summary>
    <author>
        <name>ikewu</name>
        <uri>http://peopleyun.com/</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<blockquote>按：此为客座博文系列。投稿人<a href="http://peopleyun.com/">吴朱华</a>曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。</blockquote>

<p>本篇是本系列的最终章，将总结一下App Engine在使用方面的注意点，最佳实践和适用场景，最后会谈一下我对App Engine的一些期望。 </p>

<h1>注意点</h1>
<ul>
<li>执行速度偏慢：由于其分布式的设计，所以在速度方面不是最优的，比如普通的Memcache能在几毫秒完成操作，而App Engine的Memcache则大概需要50(毫)秒才能完成操作。 </li>
<li>私有API：其API有很多都是私有，特别是在其服务方面，虽然Google提供了很不错的文档，但是在学习和移植等方面，成本都很高。 </li>
<li>执行会出现失败的情况：根据很多人的实际经验，App Engine会不定时出现执行失败的情况，特别是Datastore和URLFetch这两部分，虽然Google已经将Datastore方面出现错误的几率从原先的0.4降至现在的0.1，但是失败的情况是很难避免的。 </li>
<li>有时会停机：虽然总体而言，停机并不频繁，但是在今年初出现长达136分钟故障导致部分用户的应用无法正常运行，其发生原因来自于其备份数据中心出现了问题。 </li>
<li>无法选择合适的数据中心：比如，你应用所面对的用户主要在欧洲，但是你应用所属App Engine服务器却很有可能是被部署在一个美国的数据中心内，虽然你的应用很有可能在将来移动至欧洲某个数据中心，但是你却无法控制整个过程。 </li>
<li>有时会处理请求超时：虽然能平均在100至200ms之间完成海量的请求，但是有时会出现处理请求超时的情况。 </li>
<li>不支持裸域名：只支持类似CNAME的子域名。 </li>
</ul>

<h1>最佳实践</h1>
<ul>
<li>适应App Engine的数据模型：因为其数据模型，并不是传统的关系模式，而且在性能方面表现也和关系型数据库差别很大，所以如果想要用好非常关键的Datastore，那么理解和适应其数据模型是不可或缺的。 </li>
<li>对应用进行切分：由于App Engine对每个应用都有一定资源限制，而且为了让应用更SOA化和更模块化，可以对一个应用切分多个子应用，比如，可以分成一个用于前端的Web应用和多个用于REST服务的后台应用。 </li>
<li>极可能多地利用Memcache，这样不仅能减少昂贵的Datastore操作，而且能减轻Datastore的压力。 </li>
<li>在上面提到过，由于App Engine在执行某些操作时会出现失败的情况，比如Datastore方面，所以要在设计和实现这两方面做好相应的异常处理工作。 </li>
<li>由于Datastore不是关系型数据库，导致在执行常见的求总数操作时显的有点"捉襟见肘"，所以最好使用Google推荐的<a href="http://code.google.com/appengine/articles/sharding_counters.html">Sharded Counters</a>技术来计算总数。 </li>
<li>由于Blobstore还只是刚走出试验期而已，而且其他模块对静态文件（比如图片等）支持不佳，比如Datastore只支持1MB以内的对象，同时每个应用只能最多上传一千个文件，而且速度不是最优，所以推荐使用其他专业的云存储，比如Amazon的S3或者Google马上就要推出的Google Storage等。 </li>
<li>尽量使用批处理方式，不论是在使用Datastore还是发送邮件等。 </li>
<li>不要手动创建Index：因为App Engine会自动根据你在代码中查询来创建相关的Index。 </li>
</ul>

<h1>适用场景</h1>

<p>现在而言，App Engne主要适用于下面这三个场景：</p>

<ul>
<li>Web Hosting：这是最常见的场景，在App Engine上已经部署了数以十万计的小型网站（其中有很多主要为了学习目的），而且还部署了一些突发流量很大的网站，其中最著名的例子就是美国白宫的"Open For Questions"这个站点，主要用于让美国人民给奥巴马总统提问的，这个站点在短短的几个小时内处理接近百万级别的流量。 </li>
<li>REST服务：这也是在App Engine平台上很常见的场景，最出名的例子就是BuddyPoke，BuddyPoke的客户端就是一个Flash应用，在用户的浏览器上运行，而它的服务器端则是以REST服务的形式放置在App Engine上，每当Flash客户端需要读取和存储数据的时候，它都会发请求给后端的REST服务，来让其执行相关的Datastore操作。 </li>
<li>依赖Google服务的应用：比如应用能够通过App Engine的Email服务来发送大规模的电子邮件。 </li>
</ul>

<h1>未来的期望</h1>
<ul>
<li>更稳定的表现，更少的超时异常和更快的反应速度，特别是在Datastore和Memcached这两方面。 </li>
<li>支持对数据中心的选择，虽然现在App Engine会根据应用的用户群的所在地来调整应用所在的数据中心，但由于整个过程对开发者而言是不可控的，所以希望能在创建应用的时候，能让用户自己选择合适的数据中心。 </li>
<li>SLA，如果App Engine能像S3那样设定一些SLA条款，这样将使用户更放心地在App Engine上部署应用。 </li>
<li>新的语言：比如PHP，但是如果在现有的App Engine架构上添加一门新的语言，整个工作量会非常大的，因为App Engine有接近一半的模块是语言特定的，比如应用服务器和开发环境等，所以短期内我认为不太可能支持新的语言。 </li>
</ul>

<p>总体而言，Google App Engine是Google大战略中一个不可分割的一部分，因为Google希望能通过App Engine来降低Web应用开发的难度，只要难度降低了，那么Web应用替代客户端应用的整体速度将会加快，如果出现这样的情况的话，那么将会对Google今后的发展非常有利。</p>

<p>本系列文章结束。</p>

<p>参考资料：</p>

<ul>
<li><a href="http://perspectives.mvdirona.com/2008/06/25/GooglesDrKaiFuLeeOnCloudComputing.aspx">Google's Dr. Kai-Fu Lee on Cloud Computing</a></li>
<li><a href="http://perspectives.mvdirona.com/2009/10/31/TheCostOfLatency.aspx">The Cost of Latency</a> </li>
<li><a href="http://googleappengine.blogspot.com/" target="_blank">Google App Engine Blog</a></li>
<li><a href="http://labs.google.com/papers/bigtable.html" target="_blank">Bigtable: A Distributed Storage System for Structured Data</a></li>
<li><a href="http://code.google.com/events/io/sessions/FromSparkPlugToDriveTrain.html" target="_blank">From Spark Plug to Drive Train: Life of an App Engine Request</a></li>
<li><a href="http://perspectives.mvdirona.com/2008/07/10/GoogleMegastore.aspx" target="_blank">Google Megastore</a></li>
<li><a href="http://code.google.com/intl/zh-CN/appengine/docs/" target="_blank">Google App Engine官方文档</a></li>
<li><a href="http://highscalability.com/google-architecture" target="_blank">Google Architecture</a></li>
<li><a href="http://highscalability.com/google-appengine-first-look" target="_blank">Google App Engine - a first look</a></li>
<li><a href="http://www.infoq.com/news/2009/08/google-chose-jetty" target="_blank">Google Chose Jetty for App Engine</a></li>
<li><a href="http://www.readwriteweb.com/cloud/2010/02/google-app-engine-is-down---ba.php" target="_blank">Google App Engine is Down - Backup Data Center Having Problems</a></li>
<li><a href="http://www.ibm.com/developerworks/cn/opensource/os-cloud-virtual2/" target="_blank">面向虚拟基础设施的云服务，第 2 部分: Platform as a Service (PaaS) 和 AppScale</a></li>
<li><a href="http://www.google.org.cn/posts/google-working-on-new-filesystem.html" target="_blank">传Google正在开发新的服务器文件系统</a></li>
<li><a href="http://zh.wikipedia.org/zh-cn/Google%E6%AA%94%E6%A1%88%E7%B3%BB%E7%B5%B1" target="_blank">Google File System</a></li>
<li><a href="http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf" target="_blank">Designs, Lessons and Advice from Building Large Distributed Systems</a></li>
<li><a href="http://labs.google.com/papers/chubby.html" target="_blank">The Chubby lock service for loosely-coupled distributed systems</a></li>
<li><a href="http://perspectives.mvdirona.com/2009/01/01/GooglesWillPowerAndDataCenterEfficiency.aspx" target="_blank">Google's Will Power and Data Center Efficiency</a></li>
<li><a href="http://zh.wikipedia.org/zh-cn/MapReduce" target="_blank">MapReduce</a></li>
<li><a href="labs.google.com/papers/mapreduce-osdi04.pdf%20-" target="_blank">MapReduce的论文</a></li>
<li><a href="http://kimilv.javaeye.com/blog/411092" target="_blank">Protocol Buffer 简介</a></li>
<li><a href="http://www.theregister.co.uk/2008/04/11/google_data_center_map/" target="_blank">Google data centers snub Africa, Oz, and anything near Wyoming Or do they?</a></li>
<li><a href="http://server.ctocio.com.cn/comment/367/8785867.shtml" target="_blank">Google揭秘服务器创新技术 内置电池替换UPS</a></li>
<li><a href="http://www.dbanotes.net/database/database_sharding.html" target="_blank">开源数据库 Sharding 技术（Share Nothing）</a> </li>
<li><a href="http://www.theregister.co.uk/2009/08/12/google_file_system_part_deux/" target="_blank">Google File System II: Dawn of the Multiplying Master Nodes</a></li>
<li><a href="http://snarfed.org/space/transactions_across_datacenters_io.html" target="_blank">Transactions Across Datacenters</a></li>
<li><a href="http://server.51cto.com/IDC-81960.htm" target="_blank">探秘Google全球数据中心与中国机房</a></li>
<li><a href="http://server.51cto.com/NGDC-197298.htm" target="_blank">揭开Google数据中心五大神话</a></li>
<li><a href="http://tech.watchstor.com/storage-systems-112892.htm" target="_blank">俄勒冈州的Google数据中心耗电惊人</a></li>
<li><a href="http://tomuse.com/google-app-engine-java-microblog-development-review/#ixzz0nLlxnZQ2">Google App Engine For Java - Microblogging Case Study</a></li>
<li><a href="http://snarfed.org/space/datastore_talk.html">Under the covers of the App Engine Datastore</a></li>
<li><a href="http://perspectives.mvdirona.com/2008/07/10/GoogleMegastore.aspx">Google Megastore</a></li>
<li><a href="http://hi.baidu.com/knuthocean/blog/item/12bb9f3dea0e400abba1673c.html">Megastore/Bigtable Replication的文章</a></li>
</ul>

<p>--EOF--<br />
</p>]]>
        
    </content>
</entry>

<entry>
    <title>探索Google App Engine背后的奥秘(5)- Datastore的设计</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/google_app_engine-datastore.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1433" title="探索Google App Engine背后的奥秘(5)- Datastore的设计" />
    <id>tag:www.dbanotes.net,2010://1.1433</id>
    
    <published>2010-06-15T18:47:01Z</published>
    <updated>2010-06-15T18:47:22Z</updated>
    
    <summary><![CDATA[按：此为客座博文系列。投稿人吴朱华曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。

本篇会首先会从程序员角度来介绍一下Datastore在使用方面的一些信息，之后会接着介绍Datastore是如何构建的。

使用方面

首先，在编程方面，Datastore是基于"Entity（实体）"这个概念，而且Entity和"对象"这个概念比较类似，同时Entity可以包括多个Property（属性），Property的类别有整数，浮点和字符串等，比如，可以设计一个名为"Person"的Entity，它包含名为"Name"的字符串Property和名为"Age"的整数Property。由于Datastore是"Schema-less"的，所以数据的Schema都由应用维护，而且能非常方便地对一个Entity所包含的属性进行增删和修改。在存储方面，一个Entity的实例可以被认为是一个普通的"Row（行）"，而包含所有这种Entity的实例的Table被称为Kind，比如，所有通过"Person"这个Entity生成实例，比如小吴，小朱和小华等，它们都会存放在同一个名为"Person"的Kind中。在结构方面，虽然也能通过特定的方式在Datastore中实现关系型结构，但是Datastore在设计上是为层次（Hierarchical）性结构"度身定做"的，有Root Entity和Child Entity之分，比如，可以把"Person"作为Root Entity（父实体），"Address"作为"Person"的Child Entity，两者合在一起可以称为一个"Entity Group"。这样做的好处是能将这两个实体集中一个BigTable本地分区中，而且能对这两个实体进行本地事务。

接下来，将谈一下Datastore支持那些高级功能：其一是提供名为GQL（Google Query Language）的查询语言，GQL是SQL的一个非常小的子集，包括对"&gt;"，"&lt;"和"="等操作符。其二是App Engine会根据代码中查询语句来自动生成相应Index，但不支持对Composite Index生成。其三是虽然由于Datastore分布式的设计，所以在速度方面和传统的关系型数据库相比一定的差距，但是Google的架构师保证大部分对Datastore的操作能在200ms之内完成，同时也得益于它的分布式设计，使得它在扩展性方面特别出色。其四是Datastore也支持在实体之间创建关系，比如在Python版App Engine中可以使用ReferenceProperty在实体间构建一对多和多对多的关系。

下表为Datastore和传统的关系型数据库之间的比较：





&nbsp;
Datastore
关系型数据库


SQL支持
只支持一些基本的查询
全部支持


主要结构
层次（Hierarchical）
关系


Index
部分可自动创建
手动创建


事务
只支持在一个Entity Group内执行
支持


平均执行速度（ms）
低于200
低于100


扩展型
非常好
很困难，而且需要进行大量的修改



表1. Datastore和关系型数据库之间的比较 

最后，在接口方面，Python版提供一套私有的API和框架，在基本功能方面，比较容易学习，但在部分高级功能方面，比如关系和事务等方面，学习难度很高；Java版的API是基于JDO和JPA这两套官方的ORM标准，但是和现在事实的标准Hibernate有一定的差异。

实现方面

在实现方面，Datastore是在BigTable的基础上构建的，所以本段会首先重新介绍一下BigTable，之后会介绍Datastore的两个组成部分：Entities Table和Index，最后会讲一下它在事务和备份这两方面所采用的机制。

BigTable

在本系列的第一篇已经按照Google的Paper对BigTable技术做了一定的介绍，但其实BigTable本身其实没有之前介绍的那样复杂，其实就是一个非常巨大的Table，这也是是它之所以名为"BigTable"的原因，而且结构就像图1那样非常简单，就是一个个ROW，每个ROW都有一个Name和一组Cloumn，但是为了支持海量的数据，它将这个大的Table进行分片（Sharding）处理，每台服务器存储一个海量的Table的一小部分，并且为了查询效率，会对这个Table进行排序。就像App Engine的创始人之一Ryan Barrett所说的那样"BigTable is a sharded, sorted array "。


图1. BigTable简化版模型

在功能方面，首先，BigTable支持基本的CRUD操作，也就是增加(Create)，查询(Read)，更新(Update)和删除(Delete)。其次支持对Single-Row的事务与基于前缀和范围的扫描。

Entities Table

它是Datastore最核心的Table，是以BigTable的形式存在的，主要用于存储所有的Entity，而且是格式非常简单，每行都会有一个Row Name，也称为Entity Key（可认为它是一个Entity的Primary Key），而且只有唯一一个Column，主要用于存放被序列化的Entity。每个Entity的Key的生成是基于它的父Entity（如果有的话）和其父至上的Entity，直到其Root Entity。以下图为例，timmy的父Entity是jane，jane的父Entity兼Root Entity是Ethel，所以最后timmy的Entity Key是"/Grandparent:Ethel/Parent:Jane/Child:Timmy"。


图2. Entity Key的例子

Index

Index主要是为方便和加速查询而生的，所以在切入Index之前，先介绍一下Datastore主要支持那些查询，主要有三类：其一是基于Kind的，其二是基于Property值的，其三是基于多个Property值的。

Index表也是以BigTable的形式存在，但是和上面的Entities Table是分离的，主要用来单独存放那些需要被Index的数据，而且由于怕Index表体积太大，所以不会有时将其放置在内存中以提升查询速度。

主要有下面这几种Index表：


Kind Index：用于加速那些用于获取所有属于某个Kind的Entity的查询，比如把所有属于Person这个Kind的Entity，包括小吴，小朱和小华等提取出来，Kind Index表每行有Kind和Entity Key这两个列，此Index会有系统自动生成。 
Single-property Index：用于加速那些基于单一属性值的查询，比如要找出所有Age在20之下的Person，Age就是所谓的那个单一属性值，Single-property Index表每行除了Kind和Entity Key之外，还有属性名和属性值这两个列，此Index也会有系统自动生成，还会根据升降序的不同，生成两个表。 
Composite Index：用于加速那些基于对多个属性值的查询，Composite Index表基本和上面的Single-property Index表非常类似，但是每行包括多个属性名和属性值，而且由于此Index消耗资源非常多，所有由开发人自己确定是不是需要这个Index，系统不自动生成。 


事务

原则上所有对单一Entity的Write操作都是事务的，并基于上面提到的BigTable的Single-Row事务和Optimistic Concurrency Control这两个技术，下面是流程：首先，系统会读这个Entity的Committed Timestamp（提交时间戳），Write会以串行（Serialized）的形式写入到BigTable的日志中，之后，系统会将日志更新到BigTable的表中，如果成功的话，系统会更新这个Entity的Committed Timestamp，但如果系统发现在更新之前，Committed Timestamp发生了变化，也就是说另一个事务在这个事务执行过程中已经对这个Entity进行了操作，在这个时候，系统会重新执行这个事务。由于在整个事务过程采用Optimistic Concurrency Control，而不是Locking，所以在吞吐量方面表现不错。

如果要对多个Entity执行事务，那就需要将这几个Entity设为一个Entity Group，也就意味着将这几个Entity放在同一台物理机上。在执行的时候，会将以Root Entity的Committed Timestamp为准来对所有参与事务的Entity进行和上面差不多的事务操作。

备份

与BigTable基于Row级别的备份不同的是，Datastore是基于Enity Group级别，而且采用Paxos算法，所以Datastore的备份方法比BigTable的更安全。

总体而言，Datastore在设计理念上和传统的关系型数据库有很大的不同，所以其在反应速度和写数据方面不是最优的，但是现在Web应用以读为主，而且需要能通过简单的扩展就能支持其海量的数据，而这两点却是Datastore所擅长，所以Datastore非常适合支撑Web应用。

本篇结束，下篇是本系列的总结。

--EOF--]]></summary>
    <author>
        <name>ikewu</name>
        <uri>http://peopleyun.com/</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<blockquote>按：此为客座博文系列。投稿人<a href="http://peopleyun.com/">吴朱华</a>曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。</blockquote>

<p>本篇会首先会从程序员角度来介绍一下Datastore在使用方面的一些信息，之后会接着介绍Datastore是如何构建的。</p>

<h1>使用方面</h1>

<p>首先，在编程方面，Datastore是基于"Entity（实体）"这个概念，而且Entity和"对象"这个概念比较类似，同时Entity可以包括多个Property（属性），Property的类别有整数，浮点和字符串等，比如，可以设计一个名为"Person"的Entity，它包含名为"Name"的字符串Property和名为"Age"的整数Property。由于Datastore是"Schema-less"的，所以数据的Schema都由应用维护，而且能非常方便地对一个Entity所包含的属性进行增删和修改。在存储方面，一个Entity的实例可以被认为是一个普通的"Row（行）"，而包含所有这种Entity的实例的Table被称为Kind，比如，所有通过"Person"这个Entity生成实例，比如小吴，小朱和小华等，它们都会存放在同一个名为"Person"的Kind中。在结构方面，虽然也能通过特定的方式在Datastore中实现关系型结构，但是Datastore在设计上是为层次（Hierarchical）性结构"度身定做"的，有Root Entity和Child Entity之分，比如，可以把"Person"作为Root Entity（父实体），"Address"作为"Person"的Child Entity，两者合在一起可以称为一个"Entity Group"。这样做的好处是能将这两个实体集中一个BigTable本地分区中，而且能对这两个实体进行本地事务。</p>

<p>接下来，将谈一下Datastore支持那些高级功能：其一是提供名为GQL（Google Query Language）的查询语言，GQL是SQL的一个非常小的子集，包括对"&gt;"，"&lt;"和"="等操作符。其二是App Engine会根据代码中查询语句来自动生成相应Index，但不支持对Composite Index生成。其三是虽然由于Datastore分布式的设计，所以在速度方面和传统的关系型数据库相比一定的差距，但是Google的架构师保证大部分对Datastore的操作能在200ms之内完成，同时也得益于它的分布式设计，使得它在扩展性方面特别出色。其四是Datastore也支持在实体之间创建关系，比如在Python版App Engine中可以使用ReferenceProperty在实体间构建一对多和多对多的关系。</p>

<p>下表为Datastore和传统的关系型数据库之间的比较：</p>

<div align="center">
<table width="568" cellspacing="0" cellpadding="2" border="1" align="center">
<tbody>
<tr>
<td width="138" valign="top">&nbsp;</td>
<td width="211" valign="top">Datastore</td>
<td width="217" valign="top">关系型数据库</td>
</tr>
<tr>
<td width="138" valign="top">SQL支持</td>
<td width="211" valign="top">只支持一些基本的查询</td>
<td width="217" valign="top">全部支持</td>
</tr>
<tr>
<td width="138" valign="top">主要结构</td>
<td width="211" valign="top">层次（Hierarchical）</td>
<td width="217" valign="top">关系</td>
</tr>
<tr>
<td width="138" valign="top">Index</td>
<td width="211" valign="top">部分可自动创建</td>
<td width="217" valign="top">手动创建</td>
</tr>
<tr>
<td width="138" valign="top">事务</td>
<td width="211" valign="top">只支持在一个Entity Group内执行</td>
<td width="217" valign="top">支持</td>
</tr>
<tr>
<td width="138" valign="top">平均执行速度（ms）</td>
<td width="211" valign="top">低于200</td>
<td width="217" valign="top">低于100</td>
</tr>
<tr>
<td width="138" valign="top">扩展型</td>
<td width="211" valign="top">非常好</td>
<td width="217" valign="top">很困难，而且需要进行大量的修改</td>
</tr>
</tbody>
</table></div>
<p align="center">表1. Datastore和关系型数据库之间的比较 </p>

<p>最后，在接口方面，Python版提供一套私有的API和框架，在基本功能方面，比较容易学习，但在部分高级功能方面，比如关系和事务等方面，学习难度很高；Java版的API是基于JDO和JPA这两套官方的ORM标准，但是和现在事实的标准Hibernate有一定的差异。</p>

<h1>实现方面</h1>

<p>在实现方面，Datastore是在BigTable的基础上构建的，所以本段会首先重新介绍一下BigTable，之后会介绍Datastore的两个组成部分：Entities Table和Index，最后会讲一下它在事务和备份这两方面所采用的机制。</p>

<p><strong>BigTable</strong></p>

<p>在本系列的第一篇已经按照Google的Paper对BigTable技术做了一定的介绍，但其实BigTable本身其实没有之前介绍的那样复杂，其实就是一个非常巨大的Table，这也是是它之所以名为"BigTable"的原因，而且结构就像图1那样非常简单，就是一个个ROW，每个ROW都有一个Name和一组Cloumn，但是为了支持海量的数据，它将这个大的Table进行分片（Sharding）处理，每台服务器存储一个海量的Table的一小部分，并且为了查询效率，会对这个Table进行排序。就像App Engine的创始人之一Ryan Barrett所说的那样"BigTable is a sharded, sorted array "。</p>

<p><img alt="BigTable Simple.PNG" src="http://www.dbanotes.net/Images/BigTable%20Simple.PNG" width="468" height="222" class="mt-image-none" style="" /></p>
<p align="center">图1. BigTable简化版模型</p>

<p>在功能方面，首先，BigTable支持基本的CRUD操作，也就是增加(Create)，查询(Read)，更新(Update)和删除(Delete)。其次支持对Single-Row的事务与基于前缀和范围的扫描。</p>

<p><strong>Entities Table</strong></p>

<p>它是Datastore最核心的Table，是以BigTable的形式存在的，主要用于存储所有的Entity，而且是格式非常简单，每行都会有一个Row Name，也称为Entity Key（可认为它是一个Entity的Primary Key），而且只有唯一一个Column，主要用于存放被序列化的Entity。每个Entity的Key的生成是基于它的父Entity（如果有的话）和其父至上的Entity，直到其Root Entity。以下图为例，timmy的父Entity是jane，jane的父Entity兼Root Entity是Ethel，所以最后timmy的Entity Key是"/Grandparent:Ethel/Parent:Jane/Child:Timmy"。</p>

<p><a href="http://www.dbanotes.net/Images/entity%20keys.PNG"><img alt="entity keys.PNG" src="http://www.dbanotes.net/assets_c/2010/06/entity%20keys-thumb-580x272-62.png" width="580" height="272" class="mt-image-none" style="" /></a></p>
<p align="center">图2. Entity Key的例子</p>

<p><strong>Index</strong></p>

<p>Index主要是为方便和加速查询而生的，所以在切入Index之前，先介绍一下Datastore主要支持那些查询，主要有三类：其一是基于Kind的，其二是基于Property值的，其三是基于多个Property值的。</p>

<p>Index表也是以BigTable的形式存在，但是和上面的Entities Table是分离的，主要用来单独存放那些需要被Index的数据，而且由于怕Index表体积太大，所以不会有时将其放置在内存中以提升查询速度。</p>

<p>主要有下面这几种Index表：</p>

<ul>
<li>Kind Index：用于加速那些用于获取所有属于某个Kind的Entity的查询，比如把所有属于Person这个Kind的Entity，包括小吴，小朱和小华等提取出来，Kind Index表每行有Kind和Entity Key这两个列，此Index会有系统自动生成。 </li>
<li>Single-property Index：用于加速那些基于单一属性值的查询，比如要找出所有Age在20之下的Person，Age就是所谓的那个单一属性值，Single-property Index表每行除了Kind和Entity Key之外，还有属性名和属性值这两个列，此Index也会有系统自动生成，还会根据升降序的不同，生成两个表。 </li>
<li>Composite Index：用于加速那些基于对多个属性值的查询，Composite Index表基本和上面的Single-property Index表非常类似，但是每行包括多个属性名和属性值，而且由于此Index消耗资源非常多，所有由开发人自己确定是不是需要这个Index，系统不自动生成。 </li>
</ul>

<p><strong>事务</strong></p>

<p>原则上所有对单一Entity的Write操作都是事务的，并基于上面提到的BigTable的Single-Row事务和Optimistic Concurrency Control这两个技术，下面是流程：首先，系统会读这个Entity的Committed Timestamp（提交时间戳），Write会以串行（Serialized）的形式写入到BigTable的日志中，之后，系统会将日志更新到BigTable的表中，如果成功的话，系统会更新这个Entity的Committed Timestamp，但如果系统发现在更新之前，Committed Timestamp发生了变化，也就是说另一个事务在这个事务执行过程中已经对这个Entity进行了操作，在这个时候，系统会重新执行这个事务。由于在整个事务过程采用Optimistic Concurrency Control，而不是Locking，所以在吞吐量方面表现不错。</p>

<p>如果要对多个Entity执行事务，那就需要将这几个Entity设为一个Entity Group，也就意味着将这几个Entity放在同一台物理机上。在执行的时候，会将以Root Entity的Committed Timestamp为准来对所有参与事务的Entity进行和上面差不多的事务操作。</p>

<p><strong>备份</strong></p>

<p>与BigTable基于Row级别的备份不同的是，Datastore是基于Enity Group级别，而且采用Paxos算法，所以Datastore的备份方法比BigTable的更安全。</p>

<p>总体而言，Datastore在设计理念上和传统的关系型数据库有很大的不同，所以其在反应速度和写数据方面不是最优的，但是现在Web应用以读为主，而且需要能通过简单的扩展就能支持其海量的数据，而这两点却是Datastore所擅长，所以Datastore非常适合支撑Web应用。</p>

<p>本篇结束，下篇是本系列的总结。</p>

<p>--EOF--</p>]]>
        
    </content>
</entry>

<entry>
    <title>探索Google App Engine背后的奥秘(4)- Google App Engine的架构</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/google_app_engine-arch_intro.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1432" title="探索Google App Engine背后的奥秘(4)- Google App Engine的架构" />
    <id>tag:www.dbanotes.net,2010://1.1432</id>
    
    <published>2010-06-15T18:16:24Z</published>
    <updated>2010-06-15T18:46:24Z</updated>
    
    <summary>按：此为客座博文系列。投稿人吴朱华曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。

本篇将首先介绍App Engine的一些设计理念，接着将对App Engine的组成部分等进行介绍。

设计理念

App Engine在设计理念方面，主要可以总结为下面这五条：


重用现有的Google技术：大家都知道，重用是软件工程的核心理念之一，因为通过重用不仅能减低开发成本，而且能简化架构。在App Engine开发的过程中，重用的思想也得到了非常好的体现，比如Datastore是基于Google的bigtable技术，Images服务是基于Picasa的，用户认证服务是利用Google Account的，Email服务是基于Gmail的等。 
无状态：为了让更好地支持扩展，Google没有在应用服务器层存储任何重要的状态，而主要在datastore这层对数据进行持久化，这样当应用流量突然爆发时，可以通过为应用添加新的服务器来实现扩展。 
硬限制：App Engine对运行在其之上的应用代码设置了很多硬性限制，比如无法创建Socket和Thread等有限的系统资源，这样能保证不让一些恶性的应用影响到与其临近应用的正常运行，同时也能保证在应用之间能做到一定的隔离。 
利用Protocol Buffers技术来解决服务方面的异构性：应用服务器和很多服务相连，有可能会出现异构性的问题，比如应用服务器是用Java写的，而部分服务是用C++写的等。Google在这方面的解决方法是基于语言中立，平台中立和可扩展的Protocol Buffer，并且在App Engine平台上所有API的调用都需要在进行RPC（Remote Procedure Call，远程方面调用）之前被编译成Protocol Buffer的二进制格式。 
分布式数据库：因为App Engine将支撑海量的网络应用，所以独立数据库的设计肯定是不可取的，而且很有可能将面对起伏不定的流量，所以需要一个分布式的数据库来支撑海量的数据和海量的查询。 


组成部分

 
图1. GAE的架构图（图源自参[6]）

简单而言，其架构可以分为三个部分：前端，Datastore和服务群：

前端

共包括四个模块：


Front End：既可以认为它是Load Balancer，也可以认为它是Proxy，它主要负责负载均衡和将请求转发给App Server（应用服务器）或者Static Files等工作。 
Static Files：在概念上，比较类似于CDN（Content Delivery Network，内容分发网络），用于存储和传送那些应用附带的静态文件，比如图片，CSS和JS脚本等。 
App Server：用于处理用户发来的请求，并根据请求的内容来调用后面的Datastore和服务群。 
App Master：是在应用服务器间调度应用，并将调度之后的情况通知Front End。 


Datastore

它是基于BigTable技术的分布式数据库，虽然其也可以被理解成为一个服务，但是由于其是整个App Engine唯一存储持久化数据的地方，所以其是App Engine中一个非常核心的模块。其具体细节将在下篇和大家讨论。

服务群

整个服务群包括很多服务供App Server调用，比如Memcache，图形，用户，URL抓取和任务队列等。

Python版和Java版App Engine在实现方面的区别

因为大多数服务都可以被这两个版本共享，所以两者之间的区别主要集中在App Server端，Python版App Server应该是经过Google修改的Python Runtime，版本号应该是2.5.2，而Java版App Server是基于Jetty 6的，因为它的体积和最常用的Tomcat相比更娇小，这样能使得一台服务器支持更多的应用，而且其应该经过Google的一定的修改。

流程

在这里举一个普通的HTTP请求的处理流程为例：


用户发送一个HTTP请求。 
Front End接受这个请求，并将这个请求转发给一个空闲的App Server。 
App Server会处理这个请求。
检查用于处理这个请求的Handler是不是已经被初始化了，如果没有的话，需要对这个Handler进行初始化。 
调用服务群的用户认证服务来对用户进行认证，如果失败的话，需要终止整个请求的处理工作，并返回用户无法被认证的信息。 
查看这个请求所需的数据是否已经缓存在Memcahe中，如果没有的话，将对Datastore发出查询请求来得到数据。 
通过整合上步得到数据来生成相关的HTML，并返回给用户。 

由于HTML里面会包含对一些静态文件的引用，比如图片和CSS等，所以当用户收到HTML之后，还会通过Front End对Static Files里面存储的静态文件进行读取。 

本篇结束，下篇将关注App Engine最核心的Datastore的设计。

--EOF--</summary>
    <author>
        <name>ikewu</name>
        <uri>http://peopleyun.com/</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<blockquote>按：此为客座博文系列。投稿人<a href="http://peopleyun.com/">吴朱华</a>曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。</blockquote>

<p>本篇将首先介绍App Engine的一些设计理念，接着将对App Engine的组成部分等进行介绍。</p>

<h1><strong>设计理念</strong></h1>

<p>App Engine在设计理念方面，主要可以总结为下面这五条：</p>

<ul>
<li>重用现有的Google技术：大家都知道，重用是软件工程的核心理念之一，因为通过重用不仅能减低开发成本，而且能简化架构。在App Engine开发的过程中，重用的思想也得到了非常好的体现，比如Datastore是基于Google的bigtable技术，Images服务是基于Picasa的，用户认证服务是利用Google Account的，Email服务是基于Gmail的等。 </li>
<li>无状态：为了让更好地支持扩展，Google没有在应用服务器层存储任何重要的状态，而主要在datastore这层对数据进行持久化，这样当应用流量突然爆发时，可以通过为应用添加新的服务器来实现扩展。 </li>
<li>硬限制：App Engine对运行在其之上的应用代码设置了很多硬性限制，比如无法创建Socket和Thread等有限的系统资源，这样能保证不让一些恶性的应用影响到与其临近应用的正常运行，同时也能保证在应用之间能做到一定的隔离。 </li>
<li>利用Protocol Buffers技术来解决服务方面的异构性：应用服务器和很多服务相连，有可能会出现异构性的问题，比如应用服务器是用Java写的，而部分服务是用C++写的等。Google在这方面的解决方法是基于语言中立，平台中立和可扩展的Protocol Buffer，并且在App Engine平台上所有API的调用都需要在进行RPC（Remote Procedure Call，远程方面调用）之前被编译成Protocol Buffer的二进制格式。 </li>
<li>分布式数据库：因为App Engine将支撑海量的网络应用，所以独立数据库的设计肯定是不可取的，而且很有可能将面对起伏不定的流量，所以需要一个分布式的数据库来支撑海量的数据和海量的查询。 </li>
</ul>

<h1><strong>组成部分</strong></h1>

<p><a href="http://www.dbanotes.net/Images/GAE%20ARCH.jpg"><img alt="GAE ARCH.jpg" src="http://www.dbanotes.net/assets_c/2010/06/GAE%20ARCH-thumb-580x434-59.jpg" width="580" height="434" class="mt-image-none" style="" /></a></a> </p>
<p align="center">图1. GAE的架构图（图源自参[6]）</p>

<p>简单而言，其架构可以分为三个部分：前端，Datastore和服务群：</p>

<p><strong>前端</strong></p>

<p>共包括四个模块：</p>

<ul>
<li>Front End：既可以认为它是Load Balancer，也可以认为它是Proxy，它主要负责负载均衡和将请求转发给App Server（应用服务器）或者Static Files等工作。 </li>
<li>Static Files：在概念上，比较类似于CDN（Content Delivery Network，内容分发网络），用于存储和传送那些应用附带的静态文件，比如图片，CSS和JS脚本等。 </li>
<li>App Server：用于处理用户发来的请求，并根据请求的内容来调用后面的Datastore和服务群。 </li>
<li>App Master：是在应用服务器间调度应用，并将调度之后的情况通知Front End。 </li>
</ul>

<p><strong>Datastore</strong></p>

<p>它是基于BigTable技术的分布式数据库，虽然其也可以被理解成为一个服务，但是由于其是整个App Engine唯一存储持久化数据的地方，所以其是App Engine中一个非常核心的模块。其具体细节将在下篇和大家讨论。</p>

<p><strong>服务群</strong></p>

<p>整个服务群包括很多服务供App Server调用，比如Memcache，图形，用户，URL抓取和任务队列等。</p>

<h1>Python版和Java版App Engine在实现方面的区别</h1>

<p>因为大多数服务都可以被这两个版本共享，所以两者之间的区别主要集中在App Server端，Python版App Server应该是经过Google修改的Python Runtime，版本号应该是2.5.2，而Java版App Server是基于Jetty 6的，因为它的体积和最常用的Tomcat相比更娇小，这样能使得一台服务器支持更多的应用，而且其应该经过Google的一定的修改。</p>

<h1>流程</h1>

<p>在这里举一个普通的HTTP请求的处理流程为例：</p>

<ul>
<li>用户发送一个HTTP请求。 </li>
<li>Front End接受这个请求，并将这个请求转发给一个空闲的App Server。 </li>
<li>App Server会处理这个请求。
<li>检查用于处理这个请求的Handler是不是已经被初始化了，如果没有的话，需要对这个Handler进行初始化。 </li>
<li>调用服务群的用户认证服务来对用户进行认证，如果失败的话，需要终止整个请求的处理工作，并返回用户无法被认证的信息。 </li>
<li>查看这个请求所需的数据是否已经缓存在Memcahe中，如果没有的话，将对Datastore发出查询请求来得到数据。 </li>
<li>通过整合上步得到数据来生成相关的HTML，并返回给用户。 </li>
</li>
<li>由于HTML里面会包含对一些静态文件的引用，比如图片和CSS等，所以当用户收到HTML之后，还会通过Front End对Static Files里面存储的静态文件进行读取。 </li>
</ul>

<p>本篇结束，下篇将关注App Engine最核心的Datastore的设计。</p>

<p>--EOF--</p>]]>
        
    </content>
</entry>

<entry>
    <title>探索Google App Engine背后的奥秘(3)- Google App Engine的简介</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/google_app_engine-intro.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1431" title="探索Google App Engine背后的奥秘(3)- Google App Engine的简介" />
    <id>tag:www.dbanotes.net,2010://1.1431</id>
    
    <published>2010-06-15T13:11:37Z</published>
    <updated>2010-06-15T18:32:00Z</updated>
    
    <summary>按：此为客座博文系列。投稿人吴朱华曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。

通过前面两篇介绍，大家应该对Google强大的基础设施有一定的了解。本篇开始介绍构筑在这强大基础设施之上的Google App Engine。

Google App Engine的介绍

由于发布S3和EC2这两个优秀的云服务，使得Amazon已经率先在云计算市场站稳了脚跟，而身为云计算这个浪潮的发起者之一的Google肯定不甘示弱，并在2008年四月份推出了Google App Engine这项PaaS服务，虽然现在无法称其为一个革命性的产品，但肯定是现在市面上最成熟，并且功能最全面的PaaS平台。

Google App Engine 提供一整套开发组件来让用户轻松地在本地构建和调试网络应用，之后能让用户在Google强大的基础设施上部署和运行网络应用程序，并自动根据应用所承受的负载来对应用进行扩展，并免去用户对应用和服务器等的维护工作。同时提供大量的免费额度和灵活的资费标准。在开发语言方面，现支持Java和Python这两种语言，并为这两种语言提供基本相同的功能和API。

功能

在功能上，主要有六个方面：


动态网络服务，并提供对常用网络技术的支持，比如SSL等 。 
持久存储空间，并支持简单的查询和本地事务。 
能对应用进行自动扩展和负载平衡。 
一套功能完整的本地开发环境，可以让用户在本机上对App Engine进行开发和调试。 
支持包括Email和用户认证等多种服务。 
提供能在指定时间和定期触发事件的计划任务和能实现后台处理的任务队列。 


使用流程

整个使用流程主要包括五个步骤：


下载SDK和IDE，并在本地搭建开发环境。 
在本地对应用进行开发和调试。 
使用GAE自带上传工具来将应用部署到平台上。 
在管理界面中启动这个应用。 
利用管理界面来监控整个应用的运行状态和资费。 


由于本系列是专注于GAE的实现和设计两方面，所以不会对GAE的使用有非常深入地介绍，如果希望大家对GAE的使用方面有更深的理解，具体可以参看一下GAE的官方文档。

Google App Engine的主要组成部分

主要可分为五部分：


应用服务器：主要是用于接收来自于外部的Web请求。 
Datastore：主要用于对信息进行持久化，并基于Google著名的BigTable技术。 
服务：除了必备的应用服务器和Datastore之外，GAE还自带很多服务来帮助开发者，比如：Memcache，邮件，网页抓取，任务队列，XMPP等。 
管理界面：主要用于管理应用并监控应用的运行状态，比如，消耗了多少资源，发送了多少邮件和应用运行的日志等。 
本地开发环境：主要是帮助用户在本地开发和调试基于GAE的应用，包括用于安全调试的沙盒，SDK和IDE插件等工具。


应用服务器

应用服务器依据其支持语言的不同而有不同的实现。

Python的实现

Python版应用服务器的基础就是普通的Python 2.5.2版的Runtime，并考虑在在未来版本中添加对Python 3的支持，但是因为Python 3对Python而言，就好比Java2之于Java1，跨度非常大，所以引入Python3的难度很大。在Web技术方面，支持诸如Django，CherryPy，Pylons和Web2py等Python Web框架，并自带名为&quot;WSGI&quot;的CGI框架。虽然Python版应用服务器是基于标准的Python Runtime，但是为了安全并更好地适应App Engine的整体架构，对运行在应用服务器内的代码设置了很多方面的限制，比如不能加载用C编写Python模块和无法创建Socket等。

Java的实现

在实现方面，Java版应用服务器和Python版基本一致，也是基于标准的Java Web容器，而且选用了轻量级的Jetty技术，并跑在Java 6上。通过这个Web容器不仅能运行常见的Java Web 技术，包括Servlet，JSP，JSTL和GWT等，而且还能跑大多数常用的Java API（App Engine有一个The JRE Class White List来定义那些Java API能在App Engine的环境中被使用）和一些基于JVM的脚本语言，例如JavaScript，Ruby或Scala等，但同样无法创建Socket和Thread，或者对文件进行读写，也不支持一些比较高阶的API和框架，包括JDBC，JSF，Struts 2，RMI，JAX-RPC和Hibernate等。

Datastore

Datastore提供了一整套强大的分布式数据存储和查询服务，并能通过水平扩展来支撑海量的数据。但Datastore并不是传统的关系型数据库，它主要以&quot;Entity&quot;的形式存储数据，一个Entity包括一个Kind（在概念上和数据库的Table比较类似）和一系列属性。

Datastore提供强一致性和乐观（optimistic）同步控制，而在事务方面，则支持本地事务，也就是在只能同一个Entity Group内执行事务。

在接口方面，Python版提供了非常丰富的接口，而且还包括名为GQL的查询语言，而Java版则提供了标准的JDO和JPA这两套API。

而且Google已经在今年的Google I/O大会上宣布将在未来的App Engine for Business套件中包含标准的SQL数据库服务，但现在还不确定这个SQL数据库的实现方式，是基于开源的MySQL技术，还是基于其私有的实现，这是一个问题。

服务

Memcache

Memcache是大中型网站所备的服务，主要用来在内存中存储常用的数据，而App Engine也包含了这个服务。有趣的是App Engine的Memcache也是由Brad Fitzpatrick开发。

URL抓取（Fetch）

App Engine的应用可以通过URL抓取这个服务抓取网上的资源，并可以这个服务来与其他主机进行通信。这样避免了应用在Python和Java环境中无法使用Socket的尴尬。

Email

App Engine应用使用这个服务来利用Gmail的基础设施来发送电子邮件。

计划任务（Cron）

计划服务允许应用在指定时间或按指定间隔执行其设定的任务。这些任务通常称为Cron job。
图形
App Engine 提供了使用专用图像服务来操作图像数据的功能。图像服务可以调整图像大小，旋转、翻转和裁剪图像。它还能够使用预先定义的算法提升图片的质量。
用户认证
App Engine的应用可以依赖Google帐户系统来验证用户。App Engine还将支持OAuth。
XMPP
在App Engine上运行的程序能利用XMPP服务和其他兼容XMPP的IM服务（比如Google Talk）进行通信。

任务队列（Task Queue）

App Engine应用能通过在一个队列插入任务（以Web Hook的形式）来实现后台处理，而且App Engine会根据调度方面的设置来安排这个队列里面的任务执行。

Blobstore

因为Datastore最多支持存储1MB大小的数据对象，所以App Engine推出了Blobstore服务来存储和调用那些大于1MB但小于2G的二进制数据对象。

Mapper

Mapper可以认为就是&quot;Map Reduce&quot;中的Map，也就是能通过Mapper API对大规模的数据进行平行的处理，这些数据可以存储在Datastore或者Blobstore，但这个功能还处于内部开发阶段。

Channel

其实Channel就是我们常说的&quot;Comet&quot;，通过Channel API能让应用将内容直接推至用户的浏览器，而不需常见的轮询。

除了Java版的Memcache，Email和URL抓取都是采用标准的API之外，其他服务无论是Java版还是Python版，其API都是私有的，但是提供了丰富和细致的文档来帮助用户使用。

管理界面

用了让用户更好地管理应用，Google提供了一整套完善的管理界面，地址是http://appengine.google.com/ ，而且只需用户的Google帐户就能登录和使用。下图为其截屏：

 图1. 管理界面（点击看大图）

使用这个管理界面可执行许多操作，包括创建新的应用程序，为这个应用设置域名，查看与访问数据和错误相关的日志，观察主要资源的使用状况。

本地开发环境

为了安全起见，本地开发环境采用了沙箱（Sandbox）模式，基本上和上面提到的应用服务器的限制差不多，比如无法创建Socket和Thread，也无法对文件进行读写。Python版App Engine SDK是以普通的应用程序的形式发布，本地需要安装相应的Python Runtime，通过命令行方式启动Python版的Sandbox，同时也可以在安装有PyDev插件的Eclipse上启动。Java版App Engine SDK是以Eclispe Plugin形式发布，只要用户在他的Eclipse上安装这个Plugin，用户就能启动本地Java沙箱来开发和调试应用。

编程模型 

因为App Engine主要为了支撑Web应用而存在，所以Web层编程模型对于App Engine也是最关键的。App Engine主要使用的Web模型是CGI，CGI全称为&quot;Common Gateway Interface&quot;，它的意思非常简单，就是收到一个请求，起一个进程或者线程来处理这个请求，当处理结束后这个进程或者线程自动关闭，之后是不断地重复这个流程。由于CGI这种方式每次处理的时候，都要重新起一个新的进程或者线程，可以说在资源消耗方面还是很厉害的，虽然有线程池（Thread Pool）这样的优化技术。但是由于CGI在架构上的简单性使其成为GAE首选的编程模型，同时由于CGI支持无状态模式，所以也在伸缩性方面非常有优势。而且App Engine的两个语言版本都自带一个CGI框架：在Python平台为WSGI。在Java平台则为经典的Servlet。最近，由于App Engine引入了计划任务和任务队列这两个特性，所以App Engine已经支持计划任务和后台进程这两种编程模型。

限制和资费

首先，谈一下App Engine的使用限制，具体请看下表：





类别
限制


每个开发者所拥有的项目
10个


每个项目的文件数
1000个


每个项目代码的大小
150MB


每个请求最多执行时间
30秒


Blobstore（二进制存储）的大小
1GB


HTTP Response的大小
10MB


Datastore中每个对象的大小
1MB



表1. App Engine的使用限制

虽然这些限制对开发者是一种障碍，但对App Engine这样的多租户环境而且却是非常重要的，因为如果一个租户的应用消耗过多的资源的话，将会影响到在临近应用的正常使用，而App Engine上面这些限制就是为了是运行在其平台上面应用能安全地运行着想，避免了一个吞噬资源或恶性的应用影响到临近应用的情况。除了安全的方面考虑之后，还有伸缩的原因，也就是说，当一个应用的所占空间（footprint）处于比较低的状态，比如少于1000个文件和大小低于150MB等，那么能够非常方便地通过复制应用来实现伸缩。

接着，谈一下资费情况，App Engine的资费情况主要有两个特点：其一是免费额度高，现有免费的额度能支撑一个中型网站的运行，且不需付任何费用。其二是资费项目非常细粒度，普通IaaS服务资费，主要就是CPU，内存，硬盘和网络带宽这四项，而App Engine则除了常见的CPU和网络带宽这两项之外，还包括很多应用级别的项目，比如：Datastore API和邮件API的调用次数等。具体资费的机制是这样的：如果用户的应用每天消费的各种资源都低于这个额度，那们用户无需支付任何费用，但是当免费额度被超过的时候，用户就需要为超过的部分付费。因为App Engine整套资费标准比较复杂，所以在这里就主要介绍一下它的免费额度，具体请看下表：





类型
数量（每天）


邮件API调用
7000次


传出（outbound）带宽
10G


传入（inbound）带宽
10G


CPU时间
46个小时


HTTP请求
130万次


Datastore API
1000万次


存储的数据
1G


URL抓取的API
657千次



表2. App Engine的免费额度表

从上面免费额度来看，除了存储数据的容量外，其它都是非常强大的。 

本篇结束，下篇将对App Engine的架构进行介绍。

--EOF--</summary>
    <author>
        <name>ikewu</name>
        <uri>http://peopleyun.com/</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<blockquote>按：此为客座博文系列。投稿人<a href="http://peopleyun.com/">吴朱华</a>曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。</blockquote>

<p>通过前面两篇介绍，大家应该对Google强大的基础设施有一定的了解。本篇开始介绍构筑在这强大基础设施之上的Google App Engine。</p>

<h1>Google App Engine的介绍</h1>

<p>由于发布S3和EC2这两个优秀的云服务，使得Amazon已经率先在云计算市场站稳了脚跟，而身为云计算这个浪潮的发起者之一的Google肯定不甘示弱，并在2008年四月份推出了Google App Engine这项PaaS服务，虽然现在无法称其为一个革命性的产品，但肯定是现在市面上最成熟，并且功能最全面的PaaS平台。</p>

<p>Google App Engine 提供一整套开发组件来让用户轻松地在本地构建和调试网络应用，之后能让用户在Google强大的基础设施上部署和运行网络应用程序，并自动根据应用所承受的负载来对应用进行扩展，并免去用户对应用和服务器等的维护工作。同时提供大量的免费额度和灵活的资费标准。在开发语言方面，现支持Java和Python这两种语言，并为这两种语言提供基本相同的功能和API。</p>

<p><strong>功能</strong></p>

<p>在功能上，主要有六个方面：</p>

<ul>
<li>动态网络服务，并提供对常用网络技术的支持，比如SSL等 。 </li>
<li>持久存储空间，并支持简单的查询和本地事务。 </li>
<li>能对应用进行自动扩展和负载平衡。 </li>
<li>一套功能完整的本地开发环境，可以让用户在本机上对App Engine进行开发和调试。 </li>
<li>支持包括Email和用户认证等多种服务。 </li>
<li>提供能在指定时间和定期触发事件的计划任务和能实现后台处理的任务队列。 </li>
</ul>

<p><strong>使用流程</strong></p>

<p>整个使用流程主要包括五个步骤：</p>

<ul>
<li>下载SDK和IDE，并在本地搭建开发环境。 </li>
<li>在本地对应用进行开发和调试。 </li>
<li>使用GAE自带上传工具来将应用部署到平台上。 </li>
<li>在管理界面中启动这个应用。 </li>
<li>利用管理界面来监控整个应用的运行状态和资费。 </li>
</ul>

<p>由于本系列是专注于GAE的实现和设计两方面，所以不会对GAE的使用有非常深入地介绍，如果希望大家对GAE的使用方面有更深的理解，具体可以参看一下GAE的<a href="http://code.google.com/intl/zh-CN/appengine/docs/whatisgoogleappengine.html">官方文档</a>。</p>

<h1>Google App Engine的主要组成部分</h1>

<p>主要可分为五部分：</p>

<ul>
<li>应用服务器：主要是用于接收来自于外部的Web请求。 </li>
<li>Datastore：主要用于对信息进行持久化，并基于Google著名的BigTable技术。 </li>
<li>服务：除了必备的应用服务器和Datastore之外，GAE还自带很多服务来帮助开发者，比如：Memcache，邮件，网页抓取，任务队列，XMPP等。 </li>
<li>管理界面：主要用于管理应用并监控应用的运行状态，比如，消耗了多少资源，发送了多少邮件和应用运行的日志等。 </li>
<li>本地开发环境：主要是帮助用户在本地开发和调试基于GAE的应用，包括用于安全调试的沙盒，SDK和IDE插件等工具。</li>
</ul>

<h1><strong>应用服务器</strong></h1>

<p>应用服务器依据其支持语言的不同而有不同的实现。</p>

<p><strong>Python的实现</strong></p>

<p>Python版应用服务器的基础就是普通的Python 2.5.2版的Runtime，并考虑在在未来版本中添加对Python 3的支持，但是因为Python 3对Python而言，就好比Java2之于Java1，跨度非常大，所以引入Python3的难度很大。在Web技术方面，支持诸如Django，CherryPy，Pylons和Web2py等Python Web框架，并自带名为"WSGI"的CGI框架。虽然Python版应用服务器是基于标准的Python Runtime，但是为了安全并更好地适应App Engine的整体架构，对运行在应用服务器内的代码设置了很多方面的限制，比如不能加载用C编写Python模块和无法创建Socket等。</p>

<p><strong>Java的实现</strong></p>

<p>在实现方面，Java版应用服务器和Python版基本一致，也是基于标准的Java Web容器，而且选用了轻量级的Jetty技术，并跑在Java 6上。通过这个Web容器不仅能运行常见的Java Web 技术，包括Servlet，JSP，JSTL和GWT等，而且还能跑大多数常用的Java API（App Engine有一个<a href="http://code.google.com/appengine/docs/java/jrewhitelist.html">The JRE Class White List</a>来定义那些Java API能在App Engine的环境中被使用）和一些基于JVM的脚本语言，例如JavaScript，Ruby或Scala等，但同样无法创建Socket和Thread，或者对文件进行读写，也不支持一些比较高阶的API和框架，包括JDBC，JSF，Struts 2，RMI，JAX-RPC和Hibernate等。</p>

<h1><strong>Datastore</strong></h1>

<p>Datastore提供了一整套强大的分布式数据存储和查询服务，并能通过水平扩展来支撑海量的数据。但Datastore并不是传统的关系型数据库，它主要以"Entity"的形式存储数据，一个Entity包括一个Kind（在概念上和数据库的Table比较类似）和一系列属性。</p>

<p>Datastore提供强一致性和乐观（optimistic）同步控制，而在事务方面，则支持本地事务，也就是在只能同一个Entity Group内执行事务。</p>

<p>在接口方面，Python版提供了非常丰富的接口，而且还包括名为GQL的查询语言，而Java版则提供了标准的JDO和JPA这两套API。</p>

<p>而且Google已经在今年的Google I/O大会上宣布将在未来的App Engine for Business套件中包含标准的SQL数据库服务，但现在还不确定这个SQL数据库的实现方式，是基于开源的MySQL技术，还是基于其私有的实现，这是一个问题。</p>

<h1><strong>服务</strong></h1>

<p><strong>Memcache</strong></p>

<p>Memcache是大中型网站所备的服务，主要用来在内存中存储常用的数据，而App Engine也包含了这个服务。有趣的是App Engine的Memcache也是由Brad Fitzpatrick开发。</p>

<p><strong>URL抓取（Fetch）</strong></p>

<p>App Engine的应用可以通过URL抓取这个服务抓取网上的资源，并可以这个服务来与其他主机进行通信。这样避免了应用在Python和Java环境中无法使用Socket的尴尬。</p>

<p><strong>Email</strong></p>

<p>App Engine应用使用这个服务来利用Gmail的基础设施来发送电子邮件。</p>

<blockquote><p><strong>计划任务（Cron）</strong></p></blockquote>

<p>计划服务允许应用在指定时间或按指定间隔执行其设定的任务。这些任务通常称为Cron job。</p>
<p><strong>图形</strong></p>
<p>App Engine 提供了使用专用图像服务来操作图像数据的功能。图像服务可以调整图像大小，旋转、翻转和裁剪图像。它还能够使用预先定义的算法提升图片的质量。</p>
<p><strong>用户认证</strong></p>
<p>App Engine的应用可以依赖Google帐户系统来验证用户。App Engine还将支持OAuth。</p>
<p><strong>XMPP</strong></p>
<blockquote><p>在App Engine上运行的程序能利用XMPP服务和其他兼容XMPP的IM服务（比如Google Talk）进行通信。</p></blockquote>

<p><strong>任务队列（Task Queue）</strong></p>

<p>App Engine应用能通过在一个队列插入任务（以Web Hook的形式）来实现后台处理，而且App Engine会根据调度方面的设置来安排这个队列里面的任务执行。</p>

<p><strong>Blobstore</strong></p>

<p>因为Datastore最多支持存储1MB大小的数据对象，所以App Engine推出了Blobstore服务来存储和调用那些大于1MB但小于2G的二进制数据对象。</p>

<p><strong>Mapper</strong></p>

<p>Mapper可以认为就是"Map Reduce"中的Map，也就是能通过Mapper API对大规模的数据进行平行的处理，这些数据可以存储在Datastore或者Blobstore，但这个功能还处于内部开发阶段。</p>

<p><strong>Channel</strong></p>

<p>其实Channel就是我们常说的"Comet"，通过Channel API能让应用将内容直接推至用户的浏览器，而不需常见的轮询。</p>

<p>除了Java版的Memcache，Email和URL抓取都是采用标准的API之外，其他服务无论是Java版还是Python版，其API都是私有的，但是提供了丰富和细致的文档来帮助用户使用。</p>

<h1>管理界面</h1>

<p>用了让用户更好地管理应用，Google提供了一整套完善的管理界面，地址是http://appengine.google.com/ ，而且只需用户的Google帐户就能登录和使用。下图为其截屏：</p>

<p align="center"><a href="http://www.dbanotes.net/Images/Dashboard.PNG"><img alt="Dashboard.PNG" src="http://www.dbanotes.net/assets_c/2010/06/Dashboard-thumb-580x261-57.png" width="580" height="261" class="mt-image-none" style="" /></a></a> 图1. 管理界面（点击看大图）</p>

<p align="left">使用这个管理界面可执行许多操作，包括创建新的应用程序，为这个应用设置域名，查看与访问数据和错误相关的日志，观察主要资源的使用状况。</p>

<h1><strong>本地开发环境</strong></h1>

<p>为了安全起见，本地开发环境采用了沙箱（Sandbox）模式，基本上和上面提到的应用服务器的限制差不多，比如无法创建Socket和Thread，也无法对文件进行读写。Python版App Engine SDK是以普通的应用程序的形式发布，本地需要安装相应的Python Runtime，通过命令行方式启动Python版的Sandbox，同时也可以在安装有PyDev插件的Eclipse上启动。Java版App Engine SDK是以Eclispe Plugin形式发布，只要用户在他的Eclipse上安装这个Plugin，用户就能启动本地Java沙箱来开发和调试应用。</p>

<h1>编程模型 </h1>

<p>因为App Engine主要为了支撑Web应用而存在，所以Web层编程模型对于App Engine也是最关键的。App Engine主要使用的Web模型是CGI，CGI全称为"Common Gateway Interface"，它的意思非常简单，就是收到一个请求，起一个进程或者线程来处理这个请求，当处理结束后这个进程或者线程自动关闭，之后是不断地重复这个流程。由于CGI这种方式每次处理的时候，都要重新起一个新的进程或者线程，可以说在资源消耗方面还是很厉害的，虽然有线程池（Thread Pool）这样的优化技术。但是由于CGI在架构上的简单性使其成为GAE首选的编程模型，同时由于CGI支持无状态模式，所以也在伸缩性方面非常有优势。而且App Engine的两个语言版本都自带一个CGI框架：在Python平台为WSGI。在Java平台则为经典的Servlet。最近，由于App Engine引入了计划任务和任务队列这两个特性，所以App Engine已经支持计划任务和后台进程这两种编程模型。</p>

<h1>限制和资费</h1>

<p>首先，谈一下App Engine的使用限制，具体请看下表：</p>

<div align="center">
<table width="276" cellspacing="0" cellpadding="2" border="1" align="center">
<tbody>
<tr>
<td width="215" valign="top">类别</td>
<td width="59" valign="top">限制</td>
</tr>
<tr>
<td width="215" valign="top">每个开发者所拥有的项目</td>
<td width="59" valign="top">10个</td>
</tr>
<tr>
<td width="215" valign="top">每个项目的文件数</td>
<td width="59" valign="top">1000个</td>
</tr>
<tr>
<td width="215" valign="top">每个项目代码的大小</td>
<td width="59" valign="top">150MB</td>
</tr>
<tr>
<td width="215" valign="top">每个请求最多执行时间</td>
<td width="59" valign="top">30秒</td>
</tr>
<tr>
<td width="215" valign="top">Blobstore（二进制存储）的大小</td>
<td width="59" valign="top">1GB</td>
</tr>
<tr>
<td width="215" valign="top">HTTP Response的大小</td>
<td width="59" valign="top">10MB</td>
</tr>
<tr>
<td width="215" valign="top">Datastore中每个对象的大小</td>
<td width="59" valign="top">1MB</td>
</tr>
</tbody>
</table></div>
<p align="center">表1. App Engine的使用限制</p>

<p>虽然这些限制对开发者是一种障碍，但对App Engine这样的多租户环境而且却是非常重要的，因为如果一个租户的应用消耗过多的资源的话，将会影响到在临近应用的正常使用，而App Engine上面这些限制就是为了是运行在其平台上面应用能安全地运行着想，避免了一个吞噬资源或恶性的应用影响到临近应用的情况。除了安全的方面考虑之后，还有伸缩的原因，也就是说，当一个应用的所占空间（footprint）处于比较低的状态，比如少于1000个文件和大小低于150MB等，那么能够非常方便地通过复制应用来实现伸缩。</p>

<p>接着，谈一下资费情况，App Engine的资费情况主要有两个特点：其一是免费额度高，现有免费的额度能支撑一个中型网站的运行，且不需付任何费用。其二是资费项目非常细粒度，普通IaaS服务资费，主要就是CPU，内存，硬盘和网络带宽这四项，而App Engine则除了常见的CPU和网络带宽这两项之外，还包括很多应用级别的项目，比如：Datastore API和邮件API的调用次数等。具体资费的机制是这样的：如果用户的应用每天消费的各种资源都低于这个额度，那们用户无需支付任何费用，但是当免费额度被超过的时候，用户就需要为超过的部分付费。因为App Engine整套资费标准比较复杂，所以在这里就主要介绍一下它的免费额度，具体请看下表：</p>

<div align="center">
<table width="355" cellspacing="0" cellpadding="2" border="1" align="center">
<tbody>
<tr>
<td width="230" valign="top">类型</td>
<td width="123" valign="top">数量（每天）</td>
</tr>
<tr>
<td width="230" valign="top">邮件API调用</td>
<td width="123" valign="top">7000次</td>
</tr>
<tr>
<td width="230" valign="top">传出（outbound）带宽</td>
<td width="123" valign="top">10G</td>
</tr>
<tr>
<td width="230" valign="top">传入（inbound）带宽</td>
<td width="123" valign="top">10G</td>
</tr>
<tr>
<td width="230" valign="top">CPU时间</td>
<td width="123" valign="top">46个小时</td>
</tr>
<tr>
<td width="230" valign="top">HTTP请求</td>
<td width="123" valign="top">130万次</td>
</tr>
<tr>
<td width="230" valign="top">Datastore API</td>
<td width="123" valign="top">1000万次</td>
</tr>
<tr>
<td width="230" valign="top">存储的数据</td>
<td width="123" valign="top">1G</td>
</tr>
<tr>
<td width="230" valign="top">URL抓取的API</td>
<td width="123" valign="top">657千次</td>
</tr>
</tbody>
</table></div>
<p align="center">表2. App Engine的免费额度表</p>

<p>从上面免费额度来看，除了存储数据的容量外，其它都是非常强大的。 </p>

<p>本篇结束，下篇将对App Engine的架构进行介绍。</p>

<p>--EOF--</p>]]>
        
    </content>
</entry>

<entry>
    <title>探索Google App Engine背后的奥秘(2)--Google的整体架构猜想</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/google_app_engine_arch_guess.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1430" title="探索Google App Engine背后的奥秘(2)--Google的整体架构猜想" />
    <id>tag:www.dbanotes.net,2010://1.1430</id>
    
    <published>2010-06-07T11:11:48Z</published>
    <updated>2010-06-15T18:35:16Z</updated>
    
    <summary><![CDATA[按：此为客座博文系列。投稿人吴朱华曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。

本文是基于现有的公开资料和个人的经验来对Google的整体架构进行总结和猜想。

在软件工程界，大家有一个共识，那就是"需求决定架构"，也就是说，架构的发展是为了更好地支撑应用。那么本文在介绍架构之前，先介绍一下Google所提供的主要产品有哪些？

产品

对于Google和它几个主要产品，比如搜索和邮件等，大家已经非常熟悉了，但是其提供服务的不只于此，并主要可分为六大类：


各种搜索：网页搜索，图片搜索和视频搜索等。 
广告系统：AdWords和AdSense。 
生产力工具：Gmail和Google Apps等。 
地理产品：地图，Google Earth和Google Sky等。 
视频播放：Youtube。 
PaaS平台：Google App Engine。 


设计理念

根据现有的资料，Google的设计理念主要可以总结出下面这六条：


Scale，Scale，Scale Scale：因为Google大多数服务所面对的客户都是百万级别以上的，导致Scale也就是伸缩已经深深植入Google的DNA中，而且Google为了帮助其开发人员更好地开发分布式应用和服务，不仅研发了用于大规模数据处理MapReduce框架，还推出了用于部署分布式应用的PaaS平台Google App Engine。 
容错：一个分布式系统，就算是构建在昂贵的小型机或者大型机之上，也会不时地出现软件或者硬件方面的错误，何况Google的分布式系统还是浇筑在便宜的X86服务器之上，即使其设备标称的MTBF（平均故障间隔时间）很高，但是由于一个集群内的设备极多，导致其错误发生的几率非常高，比如李开复曾经提过这样一个例子：在一个拥有两万台X86服务器的集群中，每天大约有110台机器会出现宕机等恶劣情况，所以容错是一个不可被忽视的问题，同时这点也被Google院士Jeffrey Dean在多次演讲中提到。 
低延迟：延迟是影响用户体验的一个非常重要的因素，Google的副总裁Marissa Mayer曾经说过："如果每次搜索的时间多延迟半秒的话，那么使用搜索服务的人将减少20%"，从这个例子可以看出，低延迟对用户体验非常关键，而且为了避免光速和复杂网络环境造成的延时，Google已在很多地区设置了本地的数据中心。 
廉价的硬件和软件：由于Google每天所处理的数据和请求在规模上是史无前例的，所以现有的服务器和商业软件厂商是很难为Google"度身定做"一套分布式系统，而且就算能够设计和生产出来，其价格也是Google所无法承受的，所以其上百万台服务器基本采用便宜的X86系统和开源的Linux，并开发了一整套分布式软件栈，其中就包括上篇提到的MapReduce，BigTable和GFS等。 
优先移动计算：虽然随着摩尔定律的不断发展，使得很多资源都处于不断地增长中，比如带宽等，但是到现在为止移动数据成本远大于移动计算的成本，所以在处理大规模数据的时候，Google还是倾向于移动计算，而不是移动数据。 
服务模式：在Google的系统中，服务是相当常用的，比如其核心的搜索引擎需要依赖700-1000个内部服务，而且服务这种松耦合的开发模式在测试，开发和扩展等方面都有优势，因为它适合小团队开发，并且便于测试。 


整体架构的猜想

在整体架构这部分，首先会举出Google的三种主要工作负载，接着会试着对数据中心进行分类，最后会做一下总结。

三种工作负载

对于Google而言，其实工作负载并不仅仅只有搜索这一种，主要可以被分为三大类：


本地交互：用于在用户本地为其提供基本的Google服务，比如网页搜索等，但会将内容的生成和管理工作移交给下面的内容交付系统，比如：生成搜索所需的Index等。通过本地交互，能让用户减少延迟，从而提高用户体验，而且其对SLA要求很高，因为是直接面对客户的。 
内容交付：用于为Google大多数服务提供内容的存储，生成和管理工作，比如创建搜索所需的Index，存储YouTube的视频和GMail的数据等，而且内容交互系统主要基于Google自己开发那套分布式软件栈。还有，这套系统非常重视吞吐量和成本，而不是SLA。 
关键业务：主要包括Google一些企业级事务，比如用于企业日常运行的客户管理和人力资源等系统和赚取利润的广告系统（AdWords和AdSense），同时关键业务对SLA的要求非常高。 


两类数据中心

按照2008年数据，Google在全球有37个数据中心，其中19个在美国，12个在欧洲，3个在亚洲(北京、香港、东京)，另外3个分布于俄罗斯和南美。下图显示其中36个数据中心在全球的分布：

 图1. 2008年Google全球数据中心分布图

根据 Jeffrey Dean 在2009年末的一次演讲和最近几期季报可以推测出Google并没有在2009年过多地增加全球数据中心的数量，总数应该还是稍多于36个，但很有可能在台湾、马来西亚、立陶宛等地增加新的数据中心。

虽然Google拥有数据中心数量很多，但是它们之间存在一定的差异，而且主要可以分为两类：其一是巨型数据中心，其二是大中型数据中心。

巨型数据中心：服务器规模应该在十万台以上，常坐落于发电厂旁以获得更廉价的能源，主要用于Google内部服务，也就是内容交付服务，而且在设计方面主要关注成本和吞吐量，所以引入了大量的定制硬件和软件，来减低PUE并提升处理量，但其对SLA方面要求不是特别严厉，只要保证绝大部分时间可用即可。下图是Google巨型数据中心的一个代表，这个数据中心位于美国俄勒冈州北部哥伦比亚河畔的Dalles市，总占地面积接近30英亩，并占用了附近一个1.8GW水力发电站的大部分电力输出，当这个数据中心全部投入使用后，将消耗103兆瓦的电力，这相当于一个中小型城市的整个生活用电。


图2. Google在美国俄勒冈州哥伦比亚河畔的巨型数据中心近景图

大中型数据中心：服务器规模在千台至万台左右，可用于本地交互或者关键业务，在设计方面上非常重视延迟和高可用性，使得其坐落地点尽可能地接近用户而且采用了标准硬件和软件，比如Dell的服务器和MySQL的数据库等，常见的PUE大概在1.5和1.9之间。本来坐落于北京朝阳区酒仙桥附近的"世纪互联"机房的Google中国数据中心也属于大中型数据中心这类，其采用的硬件有DELL的工作站和Juniper的防火墙等，下图为其一角。

 
图3. Google前中国数据中心的一角（参[26]）

关于两者的区别：具体请查看下表： 


&nbsp;
巨型数据中心
大中型数据中心
工作负载
内容交付
本地交互/关键业务
地点
离发电厂近
离用户近
设计特点
高吞吐，低成本
低延迟，高可用性

服务器定制化
多
少

SLA
普通
高

服务器数量
十万台以上
千台以上

数据中心数量
十个以内
几十个

PUE估值
1.2
1.5


表1. 巨型与大中型数据中心的对比表

总结

最后，稍微总结一下，首先，普通的用户当访问Google服务时，大多会根据其请求的IP地址或者其所属的ISP将这个请求转发到用户本地的数据中心，如果本地数据中心无法处理这个请求，它很有可能将这个请求转发给远端的内容交互中心。其次，当广告客户想接入Google的广告系统时，这个请求会直接转发至其专业的关键业务数据中心来处理。

 

图4. 总结

因为本文是基于现有的公开资料和个人的经验的总结和猜想，所以和Google实际的运行情况没有任何联系。 

本篇结束，下篇将对Google App Engine及其主要组成部分进行介绍。

--EOF--]]></summary>
    <author>
        <name>ikewu</name>
        <uri>http://peopleyun.com/</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<blockquote>按：此为客座博文系列。投稿人<a href="http://peopleyun.com/">吴朱华</a>曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。</blockquote>

<p>本文是基于现有的公开资料和个人的经验来对Google的整体架构进行总结和猜想。</p>

<p>在软件工程界，大家有一个共识，那就是"需求决定架构"，也就是说，架构的发展是为了更好地支撑应用。那么本文在介绍架构之前，先介绍一下Google所提供的主要产品有哪些？</p>

<h1>产品</h1>

<p>对于Google和它几个主要产品，比如搜索和邮件等，大家已经非常熟悉了，但是其提供服务的不只于此，并主要可分为六大类：</p>

<ul>
<li>各种搜索：网页搜索，图片搜索和视频搜索等。 </li>
<li>广告系统：AdWords和AdSense。 </li>
<li>生产力工具：Gmail和Google Apps等。 </li>
<li>地理产品：地图，Google Earth和Google Sky等。 </li>
<li>视频播放：Youtube。 </li>
<li>PaaS平台：Google App Engine。 </li>
</ul>

<h1>设计理念</h1>

<p>根据现有的资料，Google的设计理念主要可以总结出下面这六条：</p>

<ul>
<li>Scale，Scale，Scale Scale：因为Google大多数服务所面对的客户都是百万级别以上的，导致Scale也就是伸缩已经深深植入Google的DNA中，而且Google为了帮助其开发人员更好地开发分布式应用和服务，不仅研发了用于大规模数据处理MapReduce框架，还推出了用于部署分布式应用的PaaS平台Google App Engine。 </li>
<li>容错：一个分布式系统，就算是构建在昂贵的小型机或者大型机之上，也会不时地出现软件或者硬件方面的错误，何况Google的分布式系统还是浇筑在便宜的X86服务器之上，即使其设备标称的MTBF（平均故障间隔时间）很高，但是由于一个集群内的设备极多，导致其错误发生的几率非常高，比如李开复曾经提过这样一个例子：在一个拥有两万台X86服务器的集群中，每天大约有110台机器会出现宕机等恶劣情况，所以容错是一个不可被忽视的问题，同时这点也被Google院士Jeffrey Dean在多次演讲中提到。 </li>
<li>低延迟：延迟是影响用户体验的一个非常重要的因素，Google的副总裁Marissa Mayer曾经说过："如果每次搜索的时间多延迟半秒的话，那么使用搜索服务的人将减少20%"，从这个例子可以看出，低延迟对用户体验非常关键，而且为了避免光速和复杂网络环境造成的延时，Google已在很多地区设置了本地的数据中心。 </li>
<li>廉价的硬件和软件：由于Google每天所处理的数据和请求在规模上是史无前例的，所以现有的服务器和商业软件厂商是很难为Google"度身定做"一套分布式系统，而且就算能够设计和生产出来，其价格也是Google所无法承受的，所以其上百万台服务器基本采用便宜的X86系统和开源的Linux，并开发了一整套分布式软件栈，其中就包括上篇提到的MapReduce，BigTable和GFS等。 </li>
<li>优先移动计算：虽然随着摩尔定律的不断发展，使得很多资源都处于不断地增长中，比如带宽等，但是到现在为止移动数据成本远大于移动计算的成本，所以在处理大规模数据的时候，Google还是倾向于移动计算，而不是移动数据。 </li>
<li>服务模式：在Google的系统中，服务是相当常用的，比如其核心的搜索引擎需要依赖700-1000个内部服务，而且服务这种松耦合的开发模式在测试，开发和扩展等方面都有优势，因为它适合小团队开发，并且便于测试。 </li>
</ul>

<h1>整体架构的猜想</h1>

<p>在整体架构这部分，首先会举出Google的三种主要工作负载，接着会试着对数据中心进行分类，最后会做一下总结。</p>

<p><strong>三种工作负载</strong></p>

<p>对于Google而言，其实工作负载并不仅仅只有搜索这一种，主要可以被分为三大类：</p>

<ul>
<li>本地交互：用于在用户本地为其提供基本的Google服务，比如网页搜索等，但会将内容的生成和管理工作移交给下面的内容交付系统，比如：生成搜索所需的Index等。通过本地交互，能让用户减少延迟，从而提高用户体验，而且其对SLA要求很高，因为是直接面对客户的。 </li>
<li>内容交付：用于为Google大多数服务提供内容的存储，生成和管理工作，比如创建搜索所需的Index，存储YouTube的视频和GMail的数据等，而且内容交互系统主要基于Google自己开发那套分布式软件栈。还有，这套系统非常重视吞吐量和成本，而不是SLA。 </li>
<li>关键业务：主要包括Google一些企业级事务，比如用于企业日常运行的客户管理和人力资源等系统和赚取利润的广告系统（AdWords和AdSense），同时关键业务对SLA的要求非常高。 </li>
</ul>

<p><strong>两类数据中心</strong></p>

<p>按照2008年数据，Google在全球有37个数据中心，其中19个在美国，12个在欧洲，3个在亚洲(北京、香港、东京)，另外3个分布于俄罗斯和南美。下图显示其中36个数据中心在全球的分布：</p>

<p align="center"><img alt="pingdom_google_map_worldwide.jpg" src="http://www.dbanotes.net/Images/pingdom_google_map_worldwide.jpg" width="450" height="222" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a> 图1. 2008年Google全球数据中心分布图</p>

<p>根据 <a href="http://research.google.com/people/jeff/">Jeffrey Dean</a> 在2009年末的一次演讲和最近几期季报可以推测出Google并没有在2009年过多地增加全球数据中心的数量，总数应该还是稍多于36个，但很有可能在台湾、马来西亚、立陶宛等地增加新的数据中心。</p>

<p>虽然Google拥有数据中心数量很多，但是它们之间存在一定的差异，而且主要可以分为两类：其一是巨型数据中心，其二是大中型数据中心。</p>

<p><strong>巨型数据中心</strong>：服务器规模应该在十万台以上，常坐落于发电厂旁以获得更廉价的能源，主要用于Google内部服务，也就是内容交付服务，而且在设计方面主要关注成本和吞吐量，所以引入了大量的定制硬件和软件，来减低PUE并提升处理量，但其对SLA方面要求不是特别严厉，只要保证绝大部分时间可用即可。下图是Google巨型数据中心的一个代表，这个数据中心位于美国俄勒冈州北部哥伦比亚河畔的Dalles市，总占地面积接近30英亩，并占用了附近一个1.8GW水力发电站的大部分电力输出，当这个数据中心全部投入使用后，将消耗103兆瓦的电力，这相当于一个中小型城市的整个生活用电。</p>

<p><a href="http://www.dbanotes.net/Images/google%20DC.jpg"><img alt="google DC.jpg" src="http://www.dbanotes.net/assets_c/2010/06/google%20DC-thumb-580x433-51.jpg" width="580" height="433" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></p>
<p align="center">图2. Google在美国俄勒冈州哥伦比亚河畔的巨型数据中心近景图</p>

<p><strong>大中型数据中心</strong>：服务器规模在千台至万台左右，可用于本地交互或者关键业务，在设计方面上非常重视延迟和高可用性，使得其坐落地点尽可能地接近用户而且采用了标准硬件和软件，比如Dell的服务器和MySQL的数据库等，常见的PUE大概在1.5和1.9之间。本来坐落于北京朝阳区酒仙桥附近的"世纪互联"机房的Google中国数据中心也属于大中型数据中心这类，其采用的硬件有DELL的工作站和Juniper的防火墙等，下图为其一角。</p>

<p><a href="http://www.dbanotes.net/Images/2008421124418.jpg"><img alt="2008421124418.jpg" src="http://www.dbanotes.net/assets_c/2010/06/2008421124418-thumb-580x495-55.jpg" width="580" height="495" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></a> </p>
<p align="center">图3. Google前中国数据中心的一角（参[26]）</p>

<p>关于两者的区别：具体请查看下表： </p>
<table width="420" cellspacing="0" cellpadding="2" border="1" align="center">
<tbody>
<tr><td width="141" valign="top">&nbsp;</td>
<td width="139" valign="top">巨型数据中心</td>
<td width="140" valign="top">大中型数据中心</td></tr>
<tr><td width="141" valign="top">工作负载</td>
<td width="139" valign="top">内容交付</td>
<td width="140" valign="top">本地交互/关键业务</td>
</tr><tr><td width="141" valign="top">地点</td>
<td width="139" valign="top">离发电厂近</td>
<td width="140" valign="top">离用户近</td>
</tr><tr><td width="141" valign="top">设计特点</td>
<td width="139" valign="top">高吞吐，低成本</td>
<td width="140" valign="top">低延迟，高可用性</td>
</tr><tr>
<td width="141" valign="top">服务器定制化</td>
<td width="139" valign="top">多</td>
<td width="140" valign="top">少</td>
</tr><tr>
<td width="141" valign="top">SLA</td>
<td width="139" valign="top">普通</td>
<td width="140" valign="top">高</td>
</tr><tr>
<td width="141" valign="top">服务器数量</td>
<td width="139" valign="top">十万台以上</td>
<td width="140" valign="top">千台以上</td>
</tr><tr>
<td width="141" valign="top">数据中心数量</td>
<td width="139" valign="top">十个以内</td>
<td width="140" valign="top">几十个</td>
</tr><tr>
<td width="141" valign="top">PUE估值</td>
<td width="139" valign="top">1.2</td>
<td width="140" valign="top">1.5</td>
</tr></tbody>
</table>
<p  align="center">表1. 巨型与大中型数据中心的对比表</p>

<p><strong>总结</strong></p>

<p>最后，稍微总结一下，首先，普通的用户当访问Google服务时，大多会根据其请求的IP地址或者其所属的ISP将这个请求转发到用户本地的数据中心，如果本地数据中心无法处理这个请求，它很有可能将这个请求转发给远端的内容交互中心。其次，当广告客户想接入Google的广告系统时，这个请求会直接转发至其专业的关键业务数据中心来处理。</p>

<p><a href="http://www.dbanotes.net/Images/google%20architecture.PNG"><img alt="google architecture.PNG" src="http://www.dbanotes.net/assets_c/2010/06/google%20architecture-thumb-580x422-53.png" width="580" height="422" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a> </p>

<p>图4. 总结</p>

<p>因为本文是基于现有的公开资料和个人的经验的总结和猜想，所以和Google实际的运行情况没有任何联系。 </p>

<p>本篇结束，<a href="http://www.dbanotes.net/arch/google_app_engine-intro.html">下篇</a>将对Google App Engine及其主要组成部分进行介绍。</p>

<p>--EOF--</p>]]>
        
    </content>
</entry>

<entry>
    <title>探索Google App Engine背后的奥秘(1)--Google的核心技术</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/google_app_engine_arch.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1429" title="探索Google App Engine背后的奥秘(1)--Google的核心技术" />
    <id>tag:www.dbanotes.net,2010://1.1429</id>
    
    <published>2010-06-04T15:26:37Z</published>
    <updated>2010-06-15T18:34:05Z</updated>
    
    <summary>按：此为客座博文系列。投稿人吴朱华曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。

本系列文章基于公开资料对Google App Engine的实现机制这个话题进行深度探讨。在切入Google App Engine之前，首先会对Google的核心技术和其整体架构进行分析，以帮助大家之后更好地理解Google App Engine的实现。

本篇将主要介绍Google的十个核心技术，而且可以分为四大类：


分布式基础设施：GFS、Chubby 和 Protocol Buffer。 
分布式大规模数据处理：MapReduce 和 Sawzall。 
分布式数据库技术：BigTable 和数据库 Sharding。 
数据中心优化技术：数据中心高温化、12V电池和服务器整合。 


分布式基础设施

GFS

由于搜索引擎需要处理海量的数据，所以Google的两位创始人Larry Page和Sergey Brin在创业初期设计一套名为&quot;BigFiles&quot;的文件系统，而GFS（全称为&quot;Google File System&quot;）这套分布式文件系统则是&quot;BigFiles&quot;的延续。
首先，介绍它的架构，GFS主要分为两类节点：

Master节点：主要存储与数据文件相关的元数据，而不是Chunk（数据块）。元数据包括一个能将64位标签映射到数据块的位置及其组成文件的表格，数据块副本位置和哪个进程正在读写特定的数据块等。还有Master节点会周期性地接收从每个Chunk节点来的更新（&quot;Heart-beat&quot;）来让元数据保持最新状态。 
Chunk节点：顾名思义，肯定用来存储Chunk，数据文件通过被分割为每个默认大小为64MB的Chunk的方式存储，而且每个Chunk有唯一一个64位标签，并且每个Chunk都会在整个分布式系统被复制多次，默认为3次。 


下图就是GFS的架构图：

图1. GFS的架构图（参片[15]）

接着，在设计上，GFS主要有八个特点：


大文件和大数据块：数据文件的大小普遍在GB级别，而且其每个数据块默认大小为64MB，这样做的好处是减少了元数据的大小，能使Master节点能够非常方便地将元数据放置在内存中以提升访问效率。 
操作以添加为主：因为文件很少被删减或者覆盖，通常只是进行添加或者读取操作，这样能充分考虑到硬盘线性吞吐量大和随机读写慢的特点。 
支持容错：首先，虽然当时为了设计方便，采用了单Master的方案，但是整个系统会保证每个Master都会有其相对应的复制品，以便于在Master节点出现问题时进行切换。其次，在Chunk层，GFS已经在设计上将节点失败视为常态，所以能非常好地处理Chunk节点失效的问题。 
高吞吐量：虽然其单个节点的性能无论是从吞吐量还是延迟都很普通，但因为其支持上千的节点，所以总的数据吞吐量是非常惊人的。 
保护数据：首先，文件被分割成固定尺寸的数据块以便于保存，而且每个数据块都会被系统复制三份。 
扩展能力强：因为元数据偏小，使得一个Master节点能控制上千个存数据的Chunk节点。 
支持压缩：对于那些稍旧的文件，可以通过对它进行压缩，来节省硬盘空间，并且压缩率非常惊人，有时甚至接近90%。 
用户空间：虽然在用户空间运行在运行效率方面稍差，但是更便于开发和测试，还有能更好利用Linux的自带的一些POSIX API。 


现在Google内部至少运行着200多个GFS集群，最大的集群有几千台服务器，并且服务于多个Google服务，比如Google搜索。但由于GFS主要为搜索而设计，所以不是很适合新的一些Google产品，比YouTube、Gmail和更强调大规模索引和实时性的Caffeine搜索引擎等，所以Google已经在开发下一代GFS，代号为&quot;Colossus&quot;，并且在设计方面有许多不同，比如：支持分布式Master节点来提升高可用性并能支撑更多文件，Chunk节点能支持1MB大小的chunk以支撑低延迟应用的需要。

Chubby

简单的来说，Chubby 属于分布式锁服务，通过 Chubby，一个分布式系统中的上千个client都能够对于某项资源进行&quot;加锁&quot;或者&quot;解锁&quot;，常用于BigTable的协作工作，在实现方面是通过对文件的创建操作来实现&quot;加锁&quot;，并基于著名科学家Leslie Lamport的Paxos算法。

Protocol Buffer

Protocol Buffer，是Google内部使用一种语言中立、平台中立和可扩展的序列化结构化数据的方式，并提供 Java、C++ 和 Python 这三种语言的实现，每一种实现都包含了相应语言的编译器以及库文件，而且它是一种二进制的格式，所以其速度是使用 XML 进行数据交换的10倍左右。它主要用于两个方面：其一是RPC通信，它可用于分布式应用之间或者异构环境下的通信。其二是数据存储方面，因为它自描述，而且压缩很方便，所以可用于对数据进行持久化，比如存储日志信息，并可被Map Reduce程序处理。与Protocol Buffer比较类似的产品还有Facebook的 Thrift ，而且 Facebook 号称Thrift在速度上还有一定的优势。

分布式大规模数据处理

MapReduce

首先，在Google数据中心会有大规模数据需要处理，比如被网络爬虫（Web Crawler）抓取的大量网页等。由于这些数据很多都是PB级别，导致处理工作不得不尽可能的并行化，而Google为了解决这个问题，引入了MapReduce这个编程模型，MapReduce是源自函数式语言，主要通过&quot;Map（映射）&quot;和&quot;Reduce（化简）&quot;这两个步骤来并行处理大规模的数据集。Map会先对由很多独立元素组成的逻辑列表中的每一个元素进行指定的操作，且原始列表不会被更改，会创建多个新的列表来保存Map的处理结果。也就意味着，Map操作是高度并行的。当Map工作完成之后，系统会先对新生成的多个列表进行清理（Shuffle）和排序，之后会这些新创建的列表进行Reduce操作，也就是对一个列表中的元素根据Key值进行适当的合并。

下图为MapReduce的运行机制：

 
图2. MapReduce的运行机制（参[19]） 

接下来，将根据上图来举一个MapReduce的例子：比如，通过搜索Spider将海量的Web页面抓取到本地的GFS集群中，然后Index系统将会对这个GFS集群中多个数据Chunk进行平行的Map处理，生成多个Key为URL，value为html页面的键值对（Key-Value Map），接着系统会对这些刚生成的键值对进行Shuffle（清理），之后系统会通过Reduce操作来根据相同的key值（也就是URL）合并这些键值对。

最后，通过MapReduce这么简单的编程模型，不仅能用于处理大规模数据，而且能将很多繁琐的细节隐藏起来，比如自动并行化，负载均衡和机器宕机处理等，这样将极大地简化程序员的开发工作。MapReduce可用于包括&quot;分布grep，分布排序，web访问日志分析，反向索引构建，文档聚类，机器学习，基于统计的机器翻译，生成Google的整个搜索的索引&quot;等大规模数据处理工作。Yahoo也推出MapReduce的开源版本Hadoop，而且Hadoop在业界也已经被大规模使用。

Sawzall

Sawzall可以被认为是构建在MapReduce之上的采用类似Java语法的DSL（Domain-Specific Language），也可以认为它是分布式的AWK。它主要用于对大规模分布式数据进行筛选和聚合等高级数据处理操作，在实现方面，是通过解释器将其转化为相对应的MapReduce任务。除了Google的Sawzall之外，yahoo推出了相似的Pig语言，但其语法类似于SQL。

分布式数据库技术

BigTable

由于在Google的数据中心存储PB级以上的非关系型数据时候，比如网页和地理数据等，为了更好地存储和利用这些数据，Google开发了一套数据库系统，名为&quot;BigTable&quot;。BigTable不是一个关系型的数据库，它也不支持关联（Join）等高级SQL操作，取而代之的是多级映射的数据结构，并是一种面向大规模处理、容错性强的自我管理系统，拥有TB级的内存和PB级的存储能力，使用结构化的文件来存储数据，并每秒可以处理数百万的读写操作。

什么是多级映射的数据结构呢？就是一个稀疏的，多维的，排序的Map，每个Cell由行关键字，列关键字和时间戳三维定位．Cell的内容是一个不解释的字符串，比如下表存储每个网站的内容与被其他网站的反向连接的文本。 反向的URL com.cnn.www是这行的关键字；contents列存储网页内容，每个内容有一个时间戳，因为有两个反向连接，所以archor的Column Family有两列：anchor: cnnsi.com和anchhor:my.look.ca。Column Family这个概念，使得表可以轻松地横向扩展。下面是它具体的数据模型图：


图3. BigTable数据模型图（参[4]） 

在结构上，首先，BigTable基于GFS分布式文件系统和Chubby分布式锁服务。其次BigTable也分为两部分：其一是Master节点，用来处理元数据相关的操作并支持负载均衡。其二是tablet节点，主要用于存储数据库的分片tablet，并提供相应的数据访问，同时Tablet是基于名为SSTable的格式，对压缩有很好的支持。


图4. BigTable架构图（参[15]） 

BigTable正在为Google六十多种产品和项目提供存储和获取结构化数据的支撑平台，其中包括有Google Print、 Orkut、Google Maps、Google Earth和Blogger等，而且Google至少运行着500个BigTable集群。    

随着Google内部服务对需求的不断提高和技术的不断地发展，导致原先的BigTable已经无法满足用户的需求，而Google也正在开发下一代BigTable，名为&quot;Spanner（扳手）&quot;，它主要有下面这些BigTable所无法支持的特性：


支持多种数据结构，比如table，familie，group和coprocessor等。 
基于分层目录和行的细粒度的复制和权限管理。 
支持跨数据中心的强一致性和弱一致性控制。 
基于Paxos算法的强一致性副本同步，并支持分布式事务。 
提供许多自动化操作。 
强大的扩展能力，能支持百万台服务器级别的集群。 
用户可以自定义诸如延迟和复制次数等重要参数以适应不同的需求。 


数据库Sharding

Sharding就是分片的意思，虽然非关系型数据库比如BigTable在Google的世界中占有非常重要的地位，但是面对传统OLTP应用，比如广告系统，Google还是采用传统的关系型数据库技术，也就是MySQL，同时由于Google所需要面对流量非常巨大，所以Google在数据库层采用了分片（Sharding）的水平扩展（Scale Out）解决方案，分片是在传统垂直扩展（Scale Up）的分区模式上的一种提升，主要通过时间，范围和面向服务等方式来将一个大型的数据库分成多片，并且这些数据片可以跨越多个数据库和服务器来实现水平扩展。
Google整套数据库分片技术主要有下面这些优点：


扩展性强：在Google生产环境中，已经有支持上千台服务器的MySQL分片集群。 
吞吐量惊人：通过巨大的MySQL分片集群能满足巨量的查询请求。 
全球备份：不仅在一个数据中心还是在全球的范围，Google都会对MySQL的分片数据进行备份，这样不仅能保护数据，而且方便扩展。 


在实现方面，主要可分为两块：其一是在MySQL InnoDB基础上添加了数据库分片的技术。其二是在ORM层的Hibernate的基础上也添加了相关的分片技术，并支持虚拟分片（Virtual Shard）来便于开发和管理。同时Google也已经将这两方面的代码提交给相关组织。

数据中心优化技术

数据中心高温化

大中型数据中心的PUE（Power Usage Effectiveness）普遍在2左右，也就是在服务器等计算设备上耗1度电，在空调等辅助设备上也要消耗一度电。对一些非常出色的数据中心，最多也就能达到1.7，但是Google通过一些有效的设计使部分数据中心到达了业界领先的1.2，在这些设计当中，其中最有特色的莫过于数据中心高温化，也就是让数据中心内的计算设备运行在偏高的温度下，Google的能源方面的总监Erik Teetzel在谈到这点的时候说：&quot;普通的数据中心在70华氏度（21摄氏度）下面工作，而我们则推荐80华氏度（27摄氏度）&quot;。但是在提高数据中心的温度方面会有两个常见的限制条件：其一是服务器设备的崩溃点，其二是精确的温度控制。如果做好这两点，数据中心就能够在高温下工作，因为假设数据中心的管理员能对数据中心的温度进�</summary>
    <author>
        <name>ikewu</name>
        <uri>http://peopleyun.com/</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<blockquote>按：此为客座博文系列。投稿人<a href="http://peopleyun.com/">吴朱华</a>曾在IBM中国研究院从事与云计算相关的研究，现在正致力于研究云计算技术。</blockquote>

<p>本系列文章基于公开资料对Google App Engine的实现机制这个话题进行深度探讨。在切入Google App Engine之前，首先会对Google的核心技术和其整体架构进行分析，以帮助大家之后更好地理解Google App Engine的实现。</p>

<p>本篇将主要介绍Google的十个核心技术，而且可以分为四大类：</p>

<ul>
<li>分布式基础设施：GFS、Chubby 和 Protocol Buffer。 </li>
<li>分布式大规模数据处理：MapReduce 和 Sawzall。 </li>
<li>分布式数据库技术：BigTable 和数据库 Sharding。 </li>
<li>数据中心优化技术：数据中心高温化、12V电池和服务器整合。 </li>
</ul>
<br />
<h1>分布式基础设施</h1>

<p><strong>GFS</strong></p>

<p>由于搜索引擎需要处理海量的数据，所以Google的两位创始人Larry Page和Sergey Brin在创业初期设计一套名为"BigFiles"的文件系统，而GFS（全称为"Google File System"）这套分布式文件系统则是"BigFiles"的延续。</p>
<p>首先，介绍它的架构，GFS主要分为两类节点：</p>
<ul>
<li>Master节点：主要存储与数据文件相关的元数据，而不是Chunk（数据块）。元数据包括一个能将64位标签映射到数据块的位置及其组成文件的表格，数据块副本位置和哪个进程正在读写特定的数据块等。还有Master节点会周期性地接收从每个Chunk节点来的更新（"Heart-beat"）来让元数据保持最新状态。 </li>
<li>Chunk节点：顾名思义，肯定用来存储Chunk，数据文件通过被分割为每个默认大小为64MB的Chunk的方式存储，而且每个Chunk有唯一一个64位标签，并且每个Chunk都会在整个分布式系统被复制多次，默认为3次。 </li>
</ul>

<p>下图就是GFS的架构图：</p>
<p><a href="http://www.dbanotes.net/Images/Google-file-system.png"><img alt="Google-file-system.png" src="http://www.dbanotes.net/assets_c/2010/06/Google-file-system-thumb-600x269-42.png" width="580" height="260" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></p>
<p align="center">图1. GFS的架构图（参片[15]）</p>

<p>接着，在设计上，GFS主要有八个特点：</p>

<ul>
<li>大文件和大数据块：数据文件的大小普遍在GB级别，而且其每个数据块默认大小为64MB，这样做的好处是减少了元数据的大小，能使Master节点能够非常方便地将元数据放置在内存中以提升访问效率。 </li>
<li>操作以添加为主：因为文件很少被删减或者覆盖，通常只是进行添加或者读取操作，这样能充分考虑到硬盘线性吞吐量大和随机读写慢的特点。 </li>
<li>支持容错：首先，虽然当时为了设计方便，采用了单Master的方案，但是整个系统会保证每个Master都会有其相对应的复制品，以便于在Master节点出现问题时进行切换。其次，在Chunk层，GFS已经在设计上将节点失败视为常态，所以能非常好地处理Chunk节点失效的问题。 </li>
<li>高吞吐量：虽然其单个节点的性能无论是从吞吐量还是延迟都很普通，但因为其支持上千的节点，所以总的数据吞吐量是非常惊人的。 </li>
<li>保护数据：首先，文件被分割成固定尺寸的数据块以便于保存，而且每个数据块都会被系统复制三份。 </li>
<li>扩展能力强：因为元数据偏小，使得一个Master节点能控制上千个存数据的Chunk节点。 </li>
<li>支持压缩：对于那些稍旧的文件，可以通过对它进行压缩，来节省硬盘空间，并且压缩率非常惊人，有时甚至接近90%。 </li>
<li>用户空间：虽然在用户空间运行在运行效率方面稍差，但是更便于开发和测试，还有能更好利用Linux的自带的一些POSIX API。 </li>
</ul>

<p>现在Google内部至少运行着200多个GFS集群，最大的集群有几千台服务器，并且服务于多个Google服务，比如Google搜索。但由于GFS主要为搜索而设计，所以不是很适合新的一些Google产品，比YouTube、Gmail和更强调大规模索引和实时性的Caffeine搜索引擎等，所以Google已经在开发下一代GFS，代号为"Colossus"，并且在设计方面有许多不同，比如：支持分布式Master节点来提升高可用性并能支撑更多文件，Chunk节点能支持1MB大小的chunk以支撑低延迟应用的需要。</p>

<p><strong>Chubby</strong></p>

<p>简单的来说，Chubby 属于分布式锁服务，通过 Chubby，一个分布式系统中的上千个client都能够对于某项资源进行"加锁"或者"解锁"，常用于BigTable的协作工作，在实现方面是通过对文件的创建操作来实现"加锁"，并基于著名科学家Leslie Lamport的Paxos算法。</p>

<p><strong>Protocol Buffer</strong></p>

<p>Protocol Buffer，是Google内部使用一种语言中立、平台中立和可扩展的序列化结构化数据的方式，并提供 Java、C++ 和 Python 这三种语言的实现，每一种实现都包含了相应语言的编译器以及库文件，而且它是一种二进制的格式，所以其速度是使用 XML 进行数据交换的10倍左右。它主要用于两个方面：其一是RPC通信，它可用于分布式应用之间或者异构环境下的通信。其二是数据存储方面，因为它自描述，而且压缩很方便，所以可用于对数据进行持久化，比如存储日志信息，并可被Map Reduce程序处理。与Protocol Buffer比较类似的产品还有Facebook的 <a href="http://incubator.apache.org/thrift/">Thrift </a>，而且 Facebook 号称Thrift在速度上还有一定的优势。</p>

<h1>分布式大规模数据处理</h1>

<p><strong>MapReduce</strong></p>

<p>首先，在Google数据中心会有大规模数据需要处理，比如被网络爬虫（Web Crawler）抓取的大量网页等。由于这些数据很多都是PB级别，导致处理工作不得不尽可能的并行化，而Google为了解决这个问题，引入了MapReduce这个编程模型，MapReduce是源自函数式语言，主要通过"Map（映射）"和"Reduce（化简）"这两个步骤来并行处理大规模的数据集。Map会先对由很多独立元素组成的逻辑列表中的每一个元素进行指定的操作，且原始列表不会被更改，会创建多个新的列表来保存Map的处理结果。也就意味着，Map操作是高度并行的。当Map工作完成之后，系统会先对新生成的多个列表进行清理（Shuffle）和排序，之后会这些新创建的列表进行Reduce操作，也就是对一个列表中的元素根据Key值进行适当的合并。</p>

<p>下图为MapReduce的运行机制：</p>

<p><a href="http://www.dbanotes.net/Images/Map%20Reduce.PNG"><img alt="Map Reduce.PNG" src="http://www.dbanotes.net/assets_c/2010/06/Map%20Reduce-thumb-580x415-44.png" width="580" height="415" class="mt-image-none" style="" /></a> </p>
<p align="center">图2. MapReduce的运行机制（参[19]） </p>

<p>接下来，将根据上图来举一个MapReduce的例子：比如，通过搜索Spider将海量的Web页面抓取到本地的GFS集群中，然后Index系统将会对这个GFS集群中多个数据Chunk进行平行的Map处理，生成多个Key为URL，value为html页面的键值对（Key-Value Map），接着系统会对这些刚生成的键值对进行Shuffle（清理），之后系统会通过Reduce操作来根据相同的key值（也就是URL）合并这些键值对。</p>

<p>最后，通过MapReduce这么简单的编程模型，不仅能用于处理大规模数据，而且能将很多繁琐的细节隐藏起来，比如自动并行化，负载均衡和机器宕机处理等，这样将极大地简化程序员的开发工作。MapReduce可用于包括"分布grep，分布排序，web访问日志分析，反向索引构建，文档聚类，机器学习，基于统计的机器翻译，生成Google的整个搜索的索引"等大规模数据处理工作。Yahoo也推出MapReduce的开源版本Hadoop，而且Hadoop在业界也已经被大规模使用。</p>

<p><strong>Sawzall</strong></p>

<p>Sawzall可以被认为是构建在MapReduce之上的采用类似Java语法的DSL（Domain-Specific Language），也可以认为它是分布式的AWK。它主要用于对大规模分布式数据进行筛选和聚合等高级数据处理操作，在实现方面，是通过解释器将其转化为相对应的MapReduce任务。除了Google的Sawzall之外，yahoo推出了相似的Pig语言，但其语法类似于SQL。</p>

<h1>分布式数据库技术</h1>

<p><strong>BigTable</strong></p>

<p>由于在Google的数据中心存储PB级以上的非关系型数据时候，比如网页和地理数据等，为了更好地存储和利用这些数据，Google开发了一套数据库系统，名为"BigTable"。BigTable不是一个关系型的数据库，它也不支持关联（Join）等高级SQL操作，取而代之的是多级映射的数据结构，并是一种面向大规模处理、容错性强的自我管理系统，拥有TB级的内存和PB级的存储能力，使用结构化的文件来存储数据，并每秒可以处理数百万的读写操作。</p>

<p>什么是多级映射的数据结构呢？就是一个稀疏的，多维的，排序的Map，每个Cell由行关键字，列关键字和时间戳三维定位．Cell的内容是一个不解释的字符串，比如下表存储每个网站的内容与被其他网站的反向连接的文本。 反向的URL com.cnn.www是这行的关键字；contents列存储网页内容，每个内容有一个时间戳，因为有两个反向连接，所以archor的Column Family有两列：anchor: cnnsi.com和anchhor:my.look.ca。Column Family这个概念，使得表可以轻松地横向扩展。下面是它具体的数据模型图：</p>

<p><a href="http://www.dbanotes.net/Images/Big%20Table%20Model.PNG"><img alt="Big Table Model.PNG" src="http://www.dbanotes.net/assets_c/2010/06/Big%20Table%20Model-thumb-580x132-46.png" width="580" height="132" class="mt-image-none" style="" /></a></p>
<p align="center">图3. BigTable数据模型图（参[4]） </p>

<p>在结构上，首先，BigTable基于GFS分布式文件系统和Chubby分布式锁服务。其次BigTable也分为两部分：其一是Master节点，用来处理元数据相关的操作并支持负载均衡。其二是tablet节点，主要用于存储数据库的分片tablet，并提供相应的数据访问，同时Tablet是基于名为SSTable的格式，对压缩有很好的支持。</p>

<p><a href="http://www.dbanotes.net/Images/BigTable.PNG"><img alt="BigTable.PNG" src="http://www.dbanotes.net/assets_c/2010/06/BigTable-thumb-580x335-48.png" width="580" height="335" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></p>
<p align="center">图4. BigTable架构图（参[15]） </p>

<p>BigTable正在为Google六十多种产品和项目提供存储和获取结构化数据的支撑平台，其中包括有Google Print、 Orkut、Google Maps、Google Earth和Blogger等，而且Google至少运行着500个BigTable集群。    </p>

<p>随着Google内部服务对需求的不断提高和技术的不断地发展，导致原先的BigTable已经无法满足用户的需求，而Google也正在开发下一代BigTable，名为"Spanner（扳手）"，它主要有下面这些BigTable所无法支持的特性：</p>

<ul>
<li>支持多种数据结构，比如table，familie，group和coprocessor等。 </li>
<li>基于分层目录和行的细粒度的复制和权限管理。 </li>
<li>支持跨数据中心的强一致性和弱一致性控制。 </li>
<li>基于Paxos算法的强一致性副本同步，并支持分布式事务。 </li>
<li>提供许多自动化操作。 </li>
<li>强大的扩展能力，能支持百万台服务器级别的集群。 </li>
<li>用户可以自定义诸如延迟和复制次数等重要参数以适应不同的需求。 </li>
</ul>

<p><strong>数据库Sharding</strong></p>

<p>Sharding就是分片的意思，虽然非关系型数据库比如BigTable在Google的世界中占有非常重要的地位，但是面对传统OLTP应用，比如广告系统，Google还是采用传统的关系型数据库技术，也就是MySQL，同时由于Google所需要面对流量非常巨大，所以Google在数据库层采用了分片（Sharding）的水平扩展（Scale Out）解决方案，分片是在传统垂直扩展（Scale Up）的分区模式上的一种提升，主要通过时间，范围和面向服务等方式来将一个大型的数据库分成多片，并且这些数据片可以跨越多个数据库和服务器来实现水平扩展。</p>
<p>Google整套数据库分片技术主要有下面这些优点：</p>

<ul>
<li>扩展性强：在Google生产环境中，已经有支持上千台服务器的MySQL分片集群。 </li>
<li>吞吐量惊人：通过巨大的MySQL分片集群能满足巨量的查询请求。 </li>
<li>全球备份：不仅在一个数据中心还是在全球的范围，Google都会对MySQL的分片数据进行备份，这样不仅能保护数据，而且方便扩展。 </li>
</ul>

<p>在实现方面，主要可分为两块：其一是在MySQL InnoDB基础上添加了数据库分片的技术。其二是在ORM层的Hibernate的基础上也添加了相关的分片技术，并支持虚拟分片（Virtual Shard）来便于开发和管理。同时Google也已经将这两方面的代码提交给相关组织。</p>

<h1>数据中心优化技术</h1>

<p><strong>数据中心高温化</strong></p>

<p>大中型数据中心的PUE（Power Usage Effectiveness）普遍在2左右，也就是在服务器等计算设备上耗1度电，在空调等辅助设备上也要消耗一度电。对一些非常出色的数据中心，最多也就能达到1.7，但是Google通过一些有效的设计使部分数据中心到达了业界领先的1.2，在这些设计当中，其中最有特色的莫过于数据中心高温化，也就是让数据中心内的计算设备运行在偏高的温度下，Google的能源方面的总监Erik Teetzel在谈到这点的时候说："普通的数据中心在70华氏度（21摄氏度）下面工作，而我们则推荐80华氏度（27摄氏度）"。但是在提高数据中心的温度方面会有两个常见的限制条件：其一是服务器设备的崩溃点，其二是精确的温度控制。如果做好这两点，数据中心就能够在高温下工作，因为假设数据中心的管理员能对数据中心的温度进行正负1/2度的调节，这将使服务器设备能在崩溃点5度之内工作，而不是常见的20度之内，这样既经济，又安全。还有，业界传言Intel为Google提供抗高温设计的定制芯片，但云计算界的顶级专家James Hamilton认为不太可能，因为虽然处理器也非常惧怕热量，但是与内存和硬盘相比还是强很多，所以处理器在抗高温设计中并不是一个核心因素。同时他也非常支持使数据中心高温化这个想法，而且期望将来数据中心甚至能运行在40摄氏度下，这样不仅能节省空调方面的成本，而且对环境也很有利。</p>

<p><strong>12V电池</strong></p>

<p>由于传统的UPS在资源方面比较浪费，所以Google在这方面另辟蹊径，采用了给每台服务器配一个专用的12V电池的做法来替换了常用的UPS，如果主电源系统出现故障，将由该电池负责对服务器供电。虽然大型UPS可以达到92%到95%的效率，但是比起内置电池的99.99%而言是非常捉襟见肘的，而且由于能量守恒的原因，导致那么未被UPS充分利用的电力会被转化成热能，这将导致用于空调的能耗相应地攀升，从而走入一个恶性循环。同时在电源方面也有类似的"神来之笔"，普通的服务器电源会同时提供5V和12V的直流电。但是Google设计的服务器电源只输出12V直流电，必要的转换在主板上进行，虽然这种设计会使主板的成本增加1美元到2美元，但是它不仅能使电源能在接近其峰值容量的情况下运行，而且在铜线上传输电流时效率更高。</p>

<p><strong>服务器整合</strong></p>

<p>谈到虚拟化的杀手锏时，第一个让人想到肯定是服务器整合，而且普遍能实现1:8的整合率来降低各方面的成本。有趣的是，Google在硬件方面也引入类似服务器整合的想法，它的做法是在一个机箱大小的空间内放置两台服务器，这些做的好处有很多，首先，减小了占地面积。其次，通过让两台服务器共享诸如电源等设备，来降低设备和能源等方面的投入。</p>

<p>本篇结束，<a href="http://www.dbanotes.net/arch/google_app_engine_arch_guess.html">下篇</a>将猜想一下Google整体架构。</p>

<p>--EOF--</p>]]>
        
    </content>
</entry>

<entry>
    <title>从 Reddit 学到的经验</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/Lessons_Learned_at_Reddit.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1425" title="从 Reddit 学到的经验" />
    <id>tag:www.dbanotes.net,2010://1.1425</id>
    
    <published>2010-05-19T14:28:39Z</published>
    <updated>2010-05-19T15:55:54Z</updated>
    
    <summary>最近有一些比较有价值的文章似乎没引起太多人注意，比如 Steve Huffman 分享创建 Reddit 过程中的经验这篇文章，在 Twitter 上的中文技术圈子似乎没有被提及。

作为社会化新闻站点，国内似乎关注 Reddit 的人并不多，我只知道少数 Geek 是其死忠粉丝。Reddit 在 2005 年 6 月由 Steve Huffman 与 Alexis Ohanian 创建，之后在 2007 年被 Condé Nast 收购。到现在看 Alexa 排名在 300 名之内。

根据维基百科的介绍(refer)：Reddit 最早是用 Common Lisp 开发，随之用 Python 进行了重写。著名的Python 框架 Web.py 就是 Reddit 当时的员工 Aaron Swartz 开发的，现在 Reddit 的 Web 框架则使用了 Pylons 。在 2009 年 11 月，Reddit 迁移到 Amazon 的云计算平台。前端框架现在用的是 jQuery。或许你早就知道，Reddit 网站程序现在已经开源，如果你感兴趣的话，不妨下载研究。

严格来说，Steve 的这个演讲其实并没有涉及多深入的技术信息，只是这几条经验的确可以作为通用规则与大家分享。

	宕机是家常便饭(Crash Often)可能很多人会认为一些 Startup 的创建人都是天才，其实也未必。两个22岁的初出茅庐的大学毕业生写的程序会好到哪里？网站起步的时候，频繁的宕机让他们吃尽了苦头。其实 Twitter 以及最近热火的 FourSquare 在初期的稳定性也不怎么样，但是仍然能对用户产生足够的吸引力。这是很多创业者需要细思量之处。
	服务分离( Separation of Services)现在已经超过 20 台数据库，每个数据库只处理一种特定类型的数据，原因无他，更为简化。另外，Reddit 得到的一个经验是不要使用 Python 的线程，而是用多进程的方式。
	开放 Schema（Open Schema）个人觉得，应该叫 Key-Value 更恰当。
	无状态处理请求(Keep it Stateless)&quot;无状态&quot;意味着横向扩展更为容易。单节点服务器向多台扩展，或许这是第一个要考虑的问题。否则，背的包袱就会越来越重。
	Memcached除了尽可能的利用 Memcached 加速用户对数据的访问速度，在 Memcached 中存储了大量预生成的页面内容，另外，也在适当的场景使用了 MemcacheDB 以满足数据持久化的需要。
	存储冗余数据（Store Redundant Data） 让站点变得更慢的一个&quot;好办法&quot;就是遵循范式设计数据库。除了在 RDBMS 中存储数据外，在上一条提到的 MemcacheDB 中也存储了大量数据，和收益相比，冗余的成本并不高。前提是数据一致性要能得到有效保证。
	脱机工作(Work Offline)	尽可能的异步处理用户操作，对计算量比较大的功能利用离线计算的模式。消息队列用用 RabbitMQ(Rabbit Technologies Ltd.已经被 SpringSource 收购) ，采用了 AMQP 协议。


或许还有意犹未尽之处，各位自己顺着文章来源分析吧。Reddit 就像一个技术标本，仔细琢磨下去还会有很多有趣的地方，相信也会对你有帮助。

--EOF--
</summary>
    <author>
        <name>Fenng</name>
        <uri>http://www.dbanotes.net</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<p>最近有一些比较有价值的文章似乎没引起太多人注意，比如 <a href="http://en.wikipedia.org/wiki/Steve_Huffman">Steve Huffman</a> 分享<a href="http://carsonified.com/blog/dev/steve-huffman-on-lessons-learned-at-reddit/">创建 Reddit 过程中的经验</a>这篇文章，在 Twitter 上的中文技术圈子似乎没有被提及。<img alt="150px-Reddit_logo.svg.png" src="http://www.dbanotes.net/Images/150px-Reddit_logo.svg.png" width="150" height="50" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /></p>

<p>作为社会化新闻站点，国内似乎关注 <a href="http://www.reddit.com/">Reddit</a> 的人并不多，我只知道少数 Geek 是其死忠粉丝。Reddit 在 2005 年 6 月由 Steve Huffman 与 Alexis Ohanian 创建，之后在 2007 年被 Condé Nast 收购。到现在看 Alexa 排名在 300 名之内。</p>

<p>根据维基百科的介绍(<a href="http://en.wikipedia.org/wiki/Reddit">refer</a>)：Reddit 最早是用 Common Lisp 开发，随之用 Python 进行了重写。著名的Python 框架 Web.py 就是 Reddit 当时的员工 Aaron Swartz 开发的，现在 Reddit 的 Web 框架则使用了 <a href="http://wiki.pylonshq.com/display/pylonscommunity/Sites+Using+Pylons">Pylons</a> 。在 2009 年 11 月，Reddit 迁移到 Amazon 的云计算平台。前端框架现在用的是 jQuery。或许你早就知道，Reddit 网站程序现在已经<a href="http://code.reddit.com/">开源</a>，如果你感兴趣的话，不妨下载研究。</p>

<p>严格来说，Steve 的这个演讲其实并没有涉及多深入的技术信息，只是这几条经验的确可以作为通用规则与大家分享。</p>

<ul>	<li><strong>宕机是家常便饭(Crash Often)</strong><br />可能很多人会认为一些 Startup 的创建人都是天才，其实也未必。两个22岁的初出茅庐的大学毕业生写的程序会好到哪里？网站起步的时候，频繁的宕机让他们吃尽了苦头。其实 Twitter 以及最近热火的 FourSquare 在初期的稳定性也不怎么样，但是仍然能对用户产生足够的吸引力。这是很多创业者需要细思量之处。</li>
	<li><strong>服务分离( Separation of Services)</strong><br />现在已经超过 20 台数据库，每个数据库只处理一种特定类型的数据，原因无他，更为简化。另外，Reddit 得到的一个经验是不要使用 Python 的线程，而是用多进程的方式。</li>
	<li><strong>开放 Schema（Open Schema）</strong><br />个人觉得，应该叫 Key-Value 更恰当。</li>
	<li><strong>无状态处理请求(Keep it Stateless)</strong><br />"无状态"意味着横向扩展更为容易。单节点服务器向多台扩展，或许这是第一个要考虑的问题。否则，背的包袱就会越来越重。</li>
	<li><strong>Memcached</strong><br />除了尽可能的利用 Memcached 加速用户对数据的访问速度，在 Memcached 中存储了大量预生成的页面内容，另外，也在适当的场景使用了 <a href="http://memcachedb.org/">MemcacheDB</a> 以满足数据持久化的需要。</li>
	<li><strong>存储冗余数据（Store Redundant Data）</strong> <br />让站点变得更慢的一个"好办法"就是遵循范式设计数据库。除了在 RDBMS 中存储数据外，在上一条提到的 MemcacheDB 中也存储了大量数据，和收益相比，冗余的成本并不高。前提是数据一致性要能得到有效保证。</li>
	<li><strong>脱机工作(Work Offline)</strong><br />	尽可能的异步处理用户操作，对计算量比较大的功能利用离线计算的模式。消息队列用用 <a href="http://www.rabbitmq.com/">RabbitMQ</a>(Rabbit Technologies Ltd.已经被 SpringSource 收购) ，采用了 AMQP 协议。</li>
</ul>

<p>或许还有意犹未尽之处，各位自己顺着文章来源分析吧。Reddit 就像一个技术标本，仔细琢磨下去还会有很多有趣的地方，相信也会对你有帮助。</p>

<p>--EOF--<br />
</p>]]>
        
    </content>
</entry>

<entry>
    <title>剖析Force.com的多租户架构（5）- 总结</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_summary.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1424" title="剖析Force.com的多租户架构（5）- 总结" />
    <id>tag:www.dbanotes.net,2010://1.1424</id>
    
    <published>2010-05-11T10:00:10Z</published>
    <updated>2010-05-14T15:15:27Z</updated>
    
    <summary>按：此为客座博文系列。投稿人吴朱华，曾在IBM中国研究院从事与云计算相关的研究，现在则致力于研发下一代云计算系统，撰写一些与云计算相关的文章，他的个人站点: PeopleYun.com。(文章版权属于原作者，转载请勿混淆。本篇原文地址)

本篇是本系列最终章，将会首先总结了Force.com的设计理念，之后会对整个系列进行总结。

设计理念

根据 Craig Weissman 的演讲和几份官方的白皮书，在Force.com的设计方面Salesforce团队主要有下面这五大考量：

数据驱动：由于 Salesforce 主要面向企业用户，导致其上面运行的应用，无论是 CRM ，还是报表工具，都是以数据的CRUD（增删改查）为核心，所以 Force.com 需要由数据来驱动，而且也需要为此做一定程度的优化。 
规模经济：由于需要在低价格和灵活付费的基础上提供可定制化应用，所以需要让尽可能多用户共享同一套系统，来大幅减低基础设施和管理等资源的投入，并实现规模经济的效益。 
安全为先：由于在一套物理设备上将承载数以万计客户的企业级应用，那么如果出现严重的程序错误或者数据方面遗失或者错乱，将会发生非常严重的后果，所以安全问题是一个  Salesforce绝不能轻视的问题。 
定制方便：虽然各个企业都会存在一部分比较通用的流程，但是每个企业都可能存在一部分私有或者独特的流程，所以Force.com需要提供方便的定制功能来帮助用户将更快捷地将企业的业务迁移到其上。 
功能丰富：虽然用户能在 Force.com 上进行开发和定制，但是如果 Force.com 能提供更多的功能模块或者能让用户购买和整合第三方的应用将非常有效地帮助用户开发应用。 


虽然这些设计理念说起来很容易，但是实现起来是非常艰难的。可贵地是，Salesforce 团队在开发 Force.com  的过程中基本实现了这些设计理念。

总结

关于本系列的总结，也主要包括五个方面：

Trade-Off 是难免的：为了满足设计目标，有时不得不做Trade-Off 。由于 Salesforce 所需要承载的多租户应用的规模之大，定制化需求之高都是前所未见的，所以Salesforce并没有采用在第二篇所提到几种常见模型，而是从长计议，采用了更灵活但技术要求更高的 Metadata 方式。 还有为了避免在数据库中执行成本非常高并会 Locking 整个数据库的 DDL（数据库定义语句）操作，所以在 Force.com 运行的时候是无法创建和修改数据库表，而这样将会提升实现的难度。
优化很重要，虽然 Force.com 的多租户架构就像 Java 一样，采用了很多动态生成的机制。很显然，如果像早期的Java那样缺乏优化的话，那么 Force.com 整体的性能将会非常糟糕，从而无法实现其设计要求。但幸运的是，Salesforce 团队不仅做了优化，而且凭借着其很多核心成员来自于 Oracle 的背景，在数据库端做了很多高水平的优化，比如添加了很多貌似累赘的 Pivot 表来加快部分常用数据的读取。 
人才很重要：经过本系列的介绍，可以看出 Force.com 的整个架构并不全是在现有的框架和库的基础上构建的，而是为了设计目标开发了很多比较底层和比较复杂的模块，而且这些模块是只有那些顶级的程序员才能编写出来的，所以说如果没有硅谷那个庞大的优秀程序员池，Salesforce 就很难走到今天。 
软件是一个进化的工程：刚开始的时候 Salesforce 架构是普普通通的 B/S 架构，但是随着用户不断地提出定制化的要求，Salesforce 也不得不在架构中引入多租户的概念，之后，由于用户需要更灵活的，可伸缩的和功能更强大的平台，导致 Salesforce 不断地对其架构进行重构，到最后，终于整出了 Force.com 这一优秀的 PaaS 平台。
有用的创新才珍贵：Salesforce 不仅在 Force.com 引入很多创新，而且都非常有效。在这些创新当中，最有用的除了 Metadata 驱动这种多租户架构实现机制之外，还有一个名为&quot;回收站（Recycle Bin）&quot;的概念，这个回收站主要存储30天来那些从数据表里面删除的数据，如果用户在30天内发现数据是误删，可以对数据进行恢复，这样既减低数据误删的可能性，而且能回收部分物理资源，比如硬盘空间等。


最后，我想说虽然到现在为止，Salesforce 还不能算是一场巨大的商业胜利，但是它在产品和思路方面有很多值得我们借鉴的地方，这也是我写本文的初衷，并谢谢大家花时间在这个系列上面，希望能对得起大家的时间。还有，如果大家对本系列有什么疑问或者见解，那么就不要吝惜你的时间，请留下你的评论。

本系列参考资料

The Internal Design of Force.com&apos;s Multi-Tenant Architecture
Salesforce.com在Wikipedia上的介绍
Cloud Computing in Practice：Fast Application Development and Delivery on Force.com
The Force.com Multitenant Architecture
Multitenancy在Wikipedia上的定义 
Salesforce多租户架构 
A Comparison of Flexible Schemas for Software as a Service




本系列文章列表

剖析Force.com的多租户架构（1）- Salesforce的简介
剖析Force.com的多租户架构（2）- 多租户的介绍
剖析Force.com的多租户架构（3）- Force.com的多租户架构（上）
剖析Force.com的多租户架构（4）- Force.com的多租户架构（下）
剖析Force.com的多租户架构（5）- 总结 


--EOF--
</summary>
    <author>
        <name>ikewu</name>
        <uri>http://peopleyun.com/</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<blockquote>按：此为客座博文系列。投稿人吴朱华，曾在IBM中国研究院从事与云计算相关的研究，现在则致力于研发下一代云计算系统，撰写一些与云计算相关的文章，他的个人站点: <a href="http://peopleyun.com">PeopleYun.com</a>。(文章版权属于原作者，转载请勿混淆。本篇<a href="http://peopleyun.com/?p=361">原文地址</a>)</blockquote>

<p>本篇是本系列最终章，将会首先总结了Force.com的设计理念，之后会对整个系列进行总结。</p>

<h1>设计理念</h1>

<p>根据 <a href="http://qconsf.com/sf2008/speaker/Craig+Weissman">Craig Weissman</a> 的演讲和几份官方的白皮书，在Force.com的设计方面Salesforce团队主要有下面这五大考量：</p>
<ul>
<li>数据驱动：由于 Salesforce 主要面向企业用户，导致其上面运行的应用，无论是 CRM ，还是报表工具，都是以数据的CRUD（增删改查）为核心，所以 Force.com 需要由数据来驱动，而且也需要为此做一定程度的优化。 </li>
<li>规模经济：由于需要在低价格和灵活付费的基础上提供可定制化应用，所以需要让尽可能多用户共享同一套系统，来大幅减低基础设施和管理等资源的投入，并实现规模经济的效益。 </li>
<li>安全为先：由于在一套物理设备上将承载数以万计客户的企业级应用，那么如果出现严重的程序错误或者数据方面遗失或者错乱，将会发生非常严重的后果，所以安全问题是一个  Salesforce绝不能轻视的问题。 </li>
<li>定制方便：虽然各个企业都会存在一部分比较通用的流程，但是每个企业都可能存在一部分私有或者独特的流程，所以Force.com需要提供方便的定制功能来帮助用户将更快捷地将企业的业务迁移到其上。 </li>
<li>功能丰富：虽然用户能在 Force.com 上进行开发和定制，但是如果 Force.com 能提供更多的功能模块或者能让用户购买和整合第三方的应用将非常有效地帮助用户开发应用。 </li>
</ul>

<p>虽然这些设计理念说起来很容易，但是实现起来是非常艰难的。可贵地是，Salesforce 团队在开发 Force.com  的过程中基本实现了这些设计理念。</p>

<h1>总结</h1>

<p>关于本系列的总结，也主要包括五个方面：</p>
<ul>
<li>Trade-Off 是难免的：为了满足设计目标，有时不得不做Trade-Off 。由于 Salesforce 所需要承载的多租户应用的规模之大，定制化需求之高都是前所未见的，所以Salesforce并没有采用在第二篇所提到几种常见模型，而是从长计议，采用了更灵活但技术要求更高的 Metadata 方式。 还有为了避免在数据库中执行成本非常高并会 Locking 整个数据库的 DDL（数据库定义语句）操作，所以在 Force.com 运行的时候是无法创建和修改数据库表，而这样将会提升实现的难度。</li>
<li>优化很重要，虽然 Force.com 的多租户架构就像 Java 一样，采用了很多动态生成的机制。很显然，如果像早期的Java那样缺乏优化的话，那么 Force.com 整体的性能将会非常糟糕，从而无法实现其设计要求。但幸运的是，Salesforce 团队不仅做了优化，而且凭借着其很多核心成员来自于 Oracle 的背景，在数据库端做了很多高水平的优化，比如添加了很多貌似累赘的 Pivot 表来加快部分常用数据的读取。 </li>
<li>人才很重要：经过本系列的介绍，可以看出 Force.com 的整个架构并不全是在现有的框架和库的基础上构建的，而是为了设计目标开发了很多比较底层和比较复杂的模块，而且这些模块是只有那些顶级的程序员才能编写出来的，所以说如果没有硅谷那个庞大的优秀程序员池，Salesforce 就很难走到今天。 </li>
<li>软件是一个进化的工程：刚开始的时候 Salesforce 架构是普普通通的 B/S 架构，但是随着用户不断地提出定制化的要求，Salesforce 也不得不在架构中引入多租户的概念，之后，由于用户需要更灵活的，可伸缩的和功能更强大的平台，导致 Salesforce 不断地对其架构进行重构，到最后，终于整出了 Force.com 这一优秀的 PaaS 平台。</li>
<li>有用的创新才珍贵：Salesforce 不仅在 Force.com 引入很多创新，而且都非常有效。在这些创新当中，最有用的除了 Metadata 驱动这种多租户架构实现机制之外，还有一个名为"回收站（Recycle Bin）"的概念，这个回收站主要存储30天来那些从数据表里面删除的数据，如果用户在30天内发现数据是误删，可以对数据进行恢复，这样既减低数据误删的可能性，而且能回收部分物理资源，比如硬盘空间等。</li>
</ul>

<p>最后，我想说虽然到现在为止，Salesforce 还不能算是一场巨大的商业胜利，但是它在产品和思路方面有很多值得我们借鉴的地方，这也是我写本文的初衷，并谢谢大家花时间在这个系列上面，希望能对得起大家的时间。还有，如果大家对本系列有什么疑问或者见解，那么就不要吝惜你的时间，请留下你的评论。

<p><strong>本系列参考资料</strong></p>
<ul>
<li><a href="http://www.infoq.com/presentations/SalesForce-Multi-Tenant-Architecture-Craig-Weissman">The Internal Design of Force.com's Multi-Tenant Architecture</a></li>
<li><a href="http://zh.wikipedia.org/zh-cn/Salesforce.com">Salesforce.com在Wikipedia上的介绍</a></li>
<li><a href="http://www.slideshare.net/catherinewall/cloud-computing-in-practice-fast-application-development-and-delivery-on-forcecom">Cloud Computing in Practice：Fast Application Development and Delivery on Force.com</a></li>
<li><a href="http://wiki.developerforce.com/index.php/Multi_Tenant_Architecture">The Force.com Multitenant Architecture</a></li>
<li><a href="http://en.wikipedia.org/wiki/Multitenancy">Multitenancy在Wikipedia上的定义</a> </li>
<li><a href="http://datacenter.chinabyte.com/206/8789206.shtml">Salesforce多租户架构</a> </li>
<li><a href="http://portal.acm.org/citation.cfm?id=1559845.1559941">A Comparison of Flexible Schemas for Software as a Service</a>
</ul>

<hr />

<p>本系列文章列表</p>
<ul>
<li><a href="http://www.dbanotes.net/arch/salesforce_intro.html">剖析Force.com的多租户架构（1）- Salesforce的简介</a></li>
<li><a href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_intro.html">剖析Force.com的多租户架构（2）- 多租户的介绍</a></li>
<li><a href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_arch.html">剖析Force.com的多租户架构（3）- Force.com的多租户架构（上）</a></li>
<li><a href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_arch_2.html">剖析Force.com的多租户架构（4）- Force.com的多租户架构（下）</a></li>
<li><a href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_summary.html"><strong>剖析Force.com的多租户架构（5）- 总结</strong> </a></li>
</ul>

<p>--EOF--<br />
</p>]]>
        
    </content>
</entry>

<entry>
    <title> 剖析Force.com的多租户架构（4）- Force.com的多租户架构（下）</title>
    <link rel="alternate" type="text/html" href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_arch_2.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://www.dbanotes.net/cgi-bin/mt-atom.cgi/weblog/blog_id=1/entry_id=1423" title=" 剖析Force.com的多租户架构（4）- Force.com的多租户架构（下）" />
    <id>tag:www.dbanotes.net,2010://1.1423</id>
    
    <published>2010-05-11T09:59:35Z</published>
    <updated>2010-05-14T15:31:59Z</updated>
    
    <summary>按：此为客座博文系列。投稿人吴朱华，曾在IBM中国研究院从事与云计算相关的研究，现在则致力于研发下一代云计算系统，撰写一些与云计算相关的文章，他的个人站点: PeopleYun.com。(文章版权属于原作者，转载请勿混淆。本篇原文地址)

本篇是上篇的延续，主要是通过对上篇提到的几个模块进行深入地分析。

大规模数据处理引擎

由于Force.com需要处理的数据量不论是来自网页端，还是来自Web Service端都是非常巨大的，所以Salesforce在Force.com中引入了特制的大规模数据处理引擎来处理大量的数据读写和在线事务。它主要有两大特点：其一是对大规模数据处理进行了优化，特别是当一个API调用发来很多待处理的数据时，这个引擎能非常快速地处理。其二是这个引擎内置错误恢复机制，当处理大规模数据时候，假如其中一个步骤发生错误时，这个引擎会捕捉和修复这个错误，并且保持这个步骤之前正确的结果以避免整个重做。

多租户感知的查询优化引擎

大多数现在数据库都自带基于成本的查询优化器，这种优化器主要是基于数据库表和索引数据等相关数值来进行计算和比较。但是由于传统的基于成本的优化器都是主要为单租户的环境设计的，所以他们并不能很好地适应多租户的环境，因为在数据库中是没有多租户这个概念。为了让优化器能够在多租户环境下良好工作，Salesforce在Oracle自带优化器的基础上搭建了一个多租户感知的查询优化引擎，它也主要有两个特点：其一是这个引擎为每个多租户对象维护了一整套便于优化的数据（租户层的，组层的和用户层的）。其二是这个引擎也维护租户和租户下面用户的安全信息，这样不仅能提升了效率，因为能避免将那些不属于这个租户的数据加入到计算，而且能提升数据的安全性。

全文检索引擎

全文检索功能对Web应用而言，基本可以算是一种基本功能，而对基于Force.com的应用而言，同样如此，Force.com为此内置一个全文检索引擎，其是基于大名鼎鼎的Lucene技术。当一个运行在Force.com平台上的应用对数据库中数据进行更新的时候，会有一组称为检索服务器的后台进程来异步更新数据相关的索引。通过这种异步机制不仅能够保证检索工作不影响处理事务的效率，而且同时也能让用户使用到最新的搜索结果。为了优化这个检索流程，系统会同步将修改过的数据复制到一个内部&quot;等待检索&quot;的表，之后检索服务器会访问这个表来进行检索，这样好处是减少了检索服务器的I/O处理量。而且为了更好地适应多租户环境，检索引擎自动为每个租户维护一个独立的索引。

数据库表的设计

下图为Force.com的数据库表结构：


图1. 数据库表的结构（图源自参[4]）

Metadata表

Metadata表的作用是存储用户定制的对象和对象所包含的字段的结构信息，不保存具体的数据，主要有两大类：


Object Metadata表：这个表主要存储对象的信息，其中主要字段包括对象的ID（ObjID），拥有这个对象的租户的ID（OrgID）和这个对象的名字（ObjName）。 
Field Metadata表：这个表主要存储对象附带字段的信息，其中主要字段包括字段的ID（FieldID），拥有这个字段的租户的ID（OrgID），这个字段的名字（FieldName），这个字段的数据类型（datatype）和一个布尔字段（IsIndexed）来定义这个字段是否需要被检索。 


Data表

Data表的作用和Metadata表正好相反，它主要存储那些用户定制的对象和对象所包含的字段的数据，主要也包括两大类：


Data表：这个表放置着上面那些对象和字段所对应的数据，核心字段有全局唯一的ID（GUID），租户ID（OrgID），对象的ID（ObjID）和存放对象名字的&quot;Nature Name（自然名称）&quot;，比如这行和一个会计对象有关，这行的&quot;&quot;Nature Name&quot;字段可能是&quot;Account Name&quot;，除了这些核心字段之外，这个表还有名字从Value0到Value500的501个数据列来存储数据，而且这些列都是varchar的形式来承载不同类型的数据，这种数据列也被称为&quot;flex列&quot;。 
Clob表：这个表主要存放那些CLOB（Character Large Object，字符大对象）数据，对象最大支持到32000个字符。 


Pivot表
Pivot表，也称为&quot;数据透视表&quot;，在Force.com中是以denormalized （去规范化）格式存储那些用于特殊目的的数据，比如用于检索（indexing），唯一性和关系等，主要作用是加速这些特殊数据的读取以提升系统整体的性能。主要有五种Pivot表：

Index Pivot表：由于Data表里面数据都是以&quot;flex列&quot;的形式存储，所以很难在Data表的基础上对表中的数据进行检索，所以Force.com引入Index Pivot表来解决这个问题，系统在运行的时候会将需要索引的数据从Data表同步到Index Pivot表中相对应的字段来方便检索，比如这个数据的类型是日期型的，那么它将会被同步到Index Pivot表中的日期字段。 
UniqueFields Pivot表：这个表是用来帮助系统在Data表中字段实现唯一性。 
Relationships Pivot表：Force.com提供了&quot;Relationship&quot;这个数据类型来定义多个对象之间的关系，而Relationships Pivot表则起到方便和加速&quot;Relationship&quot;数据读取的作用。 
NameDenorm表：是一个简单的数据表用于存储对象的ID（ObjID）和这个对象的实例的名字，主要让一些仅需获取名字的查询调用，从而让一些简单的查询无需查询规模庞大的Data表。 
FallbackIndex表：这个表将记录所有对象的名字，来免去成本高昂的&quot;UNION&quot;操作，从而加速查询。 


APEX

APEX的语言是为Force.com度身定做的一门语法上类似Java的强类型面向对象语言，主要可以通过APEX在Force.com上创建Web Service，编辑复杂的商业逻辑和整合多个Force.com的模块等。APEX主要以两种方式执行：其一是以单独脚本的形式，按照用户的需要执行。其二是以触发器的形式，当一个特定的数据处理事件发生的之前或者之后，与这个事件绑定的APEX代码将会被执行。而且所有APEX代码将会以Metadata的形式存储在Metadata表内。当一段APEX代码被调用的时候，APEX的翻译器（runtime interpreter）将会从Metadata Cache读取编译之后的APEX代码，而且能够同时被多个租户共享以提升效率。

那么为什么要在Force.com引入APEX这门新的语言，而不是像Google App Engine那样支持已经有一定市场占有率的语言，比如Java和Pyhon。Salesforce的首席架构师在谈到这点时，他提出了一个非常重要的原因，那就是安全，首先，Salesforce会APEX语言度身设计一组管理工具，通过这个工具能够非常方便地监控APEX脚本的执行，并且能知道这个脚本在执行过程所耗费的CPU时间，内存容量和SQL语句的数量等数据来判断是否需要中断这个APEX脚本，以避免影响到属于其他租户的应用，如果中断的话，系统会抛出一个runtime exception给上层的调用者。其次，基于APEX语言的代码能够对其内嵌的SOQL（Sforce Object Query Language）和SOSL（Sforce Object Search Language）进行验证来避免实际运行时出现错误。还有，在安全方面除了APEX自带的功能之外，Salesforce还要求每个上传到Force.com的APEX脚本，都需要自带能覆盖其75%代码的测试用例，这种做法不仅显著地提升APEX代码的质量从而确保平台整体运行的稳定，而且在Force.com自己更新的时候，能使用这些用例来确保新的更新不会影响现有的基于Force.com的应用。

关于Force.com多租户架构的详细介绍已经告一段落，下篇会对本系列所提到的内容进行总结！



本系列文章列表

剖析Force.com的多租户架构（1）- Salesforce的简介
剖析Force.com的多租户架构（2）- 多租户的介绍
剖析Force.com的多租户架构（3）- Force.com的多租户架构（上）
剖析Force.com的多租户架构（4）- Force.com的多租户架构（下）
剖析Force.com的多租户架构（5）- 总结 


--EOF--</summary>
    <author>
        <name>ikewu</name>
        <uri>http://peopleyun.com/</uri>
    </author>
    
        <category term="Arch" />
    
    <content type="html" xml:lang="en" xml:base="http://www.dbanotes.net/">
        <![CDATA[<blockquote>按：此为客座博文系列。投稿人吴朱华，曾在IBM中国研究院从事与云计算相关的研究，现在则致力于研发下一代云计算系统，撰写一些与云计算相关的文章，他的个人站点: <a href="http://peopleyun.com">PeopleYun.com</a>。(文章版权属于原作者，转载请勿混淆。本篇<a href="http://peopleyun.com/?p=359">原文地址</a>)</blockquote>

<p>本篇是上篇的延续，主要是通过对上篇提到的几个模块进行深入地分析。</p>

<h1>大规模数据处理引擎</h1>

<p>由于Force.com需要处理的数据量不论是来自网页端，还是来自Web Service端都是非常巨大的，所以Salesforce在Force.com中引入了特制的大规模数据处理引擎来处理大量的数据读写和在线事务。它主要有两大特点：其一是对大规模数据处理进行了优化，特别是当一个API调用发来很多待处理的数据时，这个引擎能非常快速地处理。其二是这个引擎内置错误恢复机制，当处理大规模数据时候，假如其中一个步骤发生错误时，这个引擎会捕捉和修复这个错误，并且保持这个步骤之前正确的结果以避免整个重做。</p>

<h1>多租户感知的查询优化引擎</h1>

<p>大多数现在数据库都自带基于成本的查询优化器，这种优化器主要是基于数据库表和索引数据等相关数值来进行计算和比较。但是由于传统的基于成本的优化器都是主要为单租户的环境设计的，所以他们并不能很好地适应多租户的环境，因为在数据库中是没有多租户这个概念。为了让优化器能够在多租户环境下良好工作，Salesforce在Oracle自带优化器的基础上搭建了一个多租户感知的查询优化引擎，它也主要有两个特点：其一是这个引擎为每个多租户对象维护了一整套便于优化的数据（租户层的，组层的和用户层的）。其二是这个引擎也维护租户和租户下面用户的安全信息，这样不仅能提升了效率，因为能避免将那些不属于这个租户的数据加入到计算，而且能提升数据的安全性。</p>

<h1>全文检索引擎</h1>

<p>全文检索功能对Web应用而言，基本可以算是一种基本功能，而对基于Force.com的应用而言，同样如此，Force.com为此内置一个全文检索引擎，其是基于大名鼎鼎的Lucene技术。当一个运行在Force.com平台上的应用对数据库中数据进行更新的时候，会有一组称为检索服务器的后台进程来异步更新数据相关的索引。通过这种异步机制不仅能够保证检索工作不影响处理事务的效率，而且同时也能让用户使用到最新的搜索结果。为了优化这个检索流程，系统会同步将修改过的数据复制到一个内部"等待检索"的表，之后检索服务器会访问这个表来进行检索，这样好处是减少了检索服务器的I/O处理量。而且为了更好地适应多租户环境，检索引擎自动为每个租户维护一个独立的索引。</p>

<h1>数据库表的设计</h1>

<p>下图为Force.com的数据库表结构：</p>

<p><img alt="Force DB.PNG" src="http://www.dbanotes.net/Images/Force%20DB.PNG" width="469" height="547" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></p>
<p align="center">图1. 数据库表的结构（图源自参[4]）</p>

<p><strong>Metadata表</strong></p>

<p>Metadata表的作用是存储用户定制的对象和对象所包含的字段的结构信息，不保存具体的数据，主要有两大类：</p>

<ul>
<li>Object Metadata表：这个表主要存储对象的信息，其中主要字段包括对象的ID（ObjID），拥有这个对象的租户的ID（OrgID）和这个对象的名字（ObjName）。 </li>
<li>Field Metadata表：这个表主要存储对象附带字段的信息，其中主要字段包括字段的ID（FieldID），拥有这个字段的租户的ID（OrgID），这个字段的名字（FieldName），这个字段的数据类型（datatype）和一个布尔字段（IsIndexed）来定义这个字段是否需要被检索。 </li>
</ul>

<p><strong>Data表</strong></p>

<p>Data表的作用和Metadata表正好相反，它主要存储那些用户定制的对象和对象所包含的字段的数据，主要也包括两大类：</p>

<ul>
<li>Data表：这个表放置着上面那些对象和字段所对应的数据，核心字段有全局唯一的ID（GUID），租户ID（OrgID），对象的ID（ObjID）和存放对象名字的"Nature Name（自然名称）"，比如这行和一个会计对象有关，这行的""Nature Name"字段可能是"Account Name"，除了这些核心字段之外，这个表还有名字从Value0到Value500的501个数据列来存储数据，而且这些列都是varchar的形式来承载不同类型的数据，这种数据列也被称为"flex列"。 </li>
<li>Clob表：这个表主要存放那些CLOB（Character Large Object，字符大对象）数据，对象最大支持到32000个字符。 </li>
</ul>

<p><strong>Pivot表</strong></p>
<p>Pivot表，也称为"数据透视表"，在Force.com中是以denormalized （去规范化）格式存储那些用于特殊目的的数据，比如用于检索（indexing），唯一性和关系等，主要作用是加速这些特殊数据的读取以提升系统整体的性能。主要有五种Pivot表：</p>
<ul>
<li>Index Pivot表：由于Data表里面数据都是以"flex列"的形式存储，所以很难在Data表的基础上对表中的数据进行检索，所以Force.com引入Index Pivot表来解决这个问题，系统在运行的时候会将需要索引的数据从Data表同步到Index Pivot表中相对应的字段来方便检索，比如这个数据的类型是日期型的，那么它将会被同步到Index Pivot表中的日期字段。 </li>
<li>UniqueFields Pivot表：这个表是用来帮助系统在Data表中字段实现唯一性。 </li>
<li>Relationships Pivot表：Force.com提供了"Relationship"这个数据类型来定义多个对象之间的关系，而Relationships Pivot表则起到方便和加速"Relationship"数据读取的作用。 </li>
<li>NameDenorm表：是一个简单的数据表用于存储对象的ID（ObjID）和这个对象的实例的名字，主要让一些仅需获取名字的查询调用，从而让一些简单的查询无需查询规模庞大的Data表。 </li>
<li>FallbackIndex表：这个表将记录所有对象的名字，来免去成本高昂的"UNION"操作，从而加速查询。 </li>
</ul>

<h1>APEX</h1>

<p>APEX的语言是为Force.com度身定做的一门语法上类似Java的强类型面向对象语言，主要可以通过APEX在Force.com上创建Web Service，编辑复杂的商业逻辑和整合多个Force.com的模块等。APEX主要以两种方式执行：其一是以单独脚本的形式，按照用户的需要执行。其二是以触发器的形式，当一个特定的数据处理事件发生的之前或者之后，与这个事件绑定的APEX代码将会被执行。而且所有APEX代码将会以Metadata的形式存储在Metadata表内。当一段APEX代码被调用的时候，APEX的翻译器（runtime interpreter）将会从Metadata Cache读取编译之后的APEX代码，而且能够同时被多个租户共享以提升效率。</p>

<p>那么为什么要在Force.com引入APEX这门新的语言，而不是像Google App Engine那样支持已经有一定市场占有率的语言，比如Java和Pyhon。Salesforce的首席架构师在谈到这点时，他提出了一个非常重要的原因，那就是安全，首先，Salesforce会APEX语言度身设计一组管理工具，通过这个工具能够非常方便地监控APEX脚本的执行，并且能知道这个脚本在执行过程所耗费的CPU时间，内存容量和SQL语句的数量等数据来判断是否需要中断这个APEX脚本，以避免影响到属于其他租户的应用，如果中断的话，系统会抛出一个runtime exception给上层的调用者。其次，基于APEX语言的代码能够对其内嵌的SOQL（Sforce Object Query Language）和SOSL（Sforce Object Search Language）进行验证来避免实际运行时出现错误。还有，在安全方面除了APEX自带的功能之外，Salesforce还要求每个上传到Force.com的APEX脚本，都需要自带能覆盖其75%代码的测试用例，这种做法不仅显著地提升APEX代码的质量从而确保平台整体运行的稳定，而且在Force.com自己更新的时候，能使用这些用例来确保新的更新不会影响现有的基于Force.com的应用。</p>

<p>关于Force.com多租户架构的详细介绍已经告一段落，下篇会对本系列所提到的内容进行总结！</p>

<hr />

<p>本系列文章列表</p>
<ul>
<li><a href="http://www.dbanotes.net/arch/salesforce_intro.html">剖析Force.com的多租户架构（1）- Salesforce的简介</a></li>
<li><a href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_intro.html">剖析Force.com的多租户架构（2）- 多租户的介绍</a></li>
<li><a href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_arch.html">剖析Force.com的多租户架构（3）- Force.com的多租户架构（上）</a></li>
<li><a href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_arch_2.html"><strong>剖析Force.com的多租户架构（4）- Force.com的多租户架构（下）</strong></a></li>
<li><a href="http://www.dbanotes.net/arch/Salesforce_Multitenancy_summary.html">剖析Force.com的多租户架构（5）- 总结 </a></li>
</ul>

<p>--EOF--</p>]]>
        
    </content>
</entry>

</feed> 

