<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet href='http://feeds.feedsky.com/styles/temp01.xsl' type='text/xsl' ?><!--这是一个由Feedsy提供技术支持的Feed，为了提高读者阅读的体验，以及满足用户美化自己Feed的需要，我们设计了多种精美的Feed模板，提供给大家选择，所有最终呈现出来的样式，皆由用户自愿选择使用，未经许可，任何团体和个人，请不要擅自修改样式或者盗用，这是对于用户选择权的尊重。--><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fs="http://www.feedsky.com/namespace/feed" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link href="http://feeds.feedsky.com/csdn.net/heiyeshuwu" type="application/rss+xml" rel="self"></atom:link><fs:self_link href="http://feeds.feedsky.com/csdn.net/heiyeshuwu" type="application/rss+xml"></fs:self_link><lastBuildDate>Mon, 21 May 2012 15:47:02 GMT</lastBuildDate><title>heiyeluren的blog（黑夜路人的开源世界）</title><description>【 LAMP技术交流群：172737140】</description><link>http://blog.csdn.net/heiyeshuwu</link><language>zh-cn</language><copyright>Copyright &amp;copy; heiyeshuwu</copyright><pubDate>Wed, 23 May 2012 16:43:51 GMT</pubDate><image><url>http://static.blog.csdn.net/images/logo.gif</url><link>http://blog.csdn.net</link></image><item><title>[转][转]异步编程与响应式框架</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7589215</link><description>&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;作者：老赵&lt;/p&gt;
&lt;p&gt;来源：http://blog.zhaojie.me/2010/09/async-programming-and-reactive-framework.html&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:rgb(51,51,51); font-family:'Trebuchet MS',Georgia,'Times New Roman',Times,sans-serif; font-size:14px; line-height:25px&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h1 style=&quot;font-size:26px; margin-top:24px; margin-bottom:12px; padding-top:5px; padding-right:5px; padding-bottom:5px; padding-left:5px; color:white; background-color:gray&quot;&gt;
前言&lt;/h1&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
异步操作是强大的，它是许多高伸缩性架构的基石。异步操作在许多情况下是必须的，例如在客户端保持用户界面的响应能力，以及在日益兴起的云计算场景中。但是，异步编程又是十分困难的，它让这让许多程序员敬而远之。因此，越来越多的编程语言都对异步编程提供了相当程度的支持，其中的典型代表便是F#中的异步工作流以及Scala的Actor模型。不过目前的一些主流编程语言，如C#或是JavaScript，它们在设计之时并没有在异步编程上考虑太多，我们便会根据它们的语言特性，提供合适的异步编程模型及其实现。而本文介绍的便是其中一例：响应式编程（Reactive
 Programming）模型及响应式框架（Reactive Framework，简称Rx）。&lt;/p&gt;
&lt;h1 style=&quot;font-size:26px; margin-top:24px; margin-bottom:12px; padding-top:5px; padding-right:5px; padding-bottom:5px; padding-left:5px; color:white; background-color:gray&quot;&gt;
异步编程的难点&lt;/h1&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
异步编程之所以困难，主要有三大难点。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
首先是对于状态的维护。在普通编程中，我们已经习惯了根据各种状态采取不同做法的编程方式。在异步编程中，状态对于操作的影响则往往更为复杂。例如，我们在编写一个鼠标“拖动及绘图”的行为时，一般会采用这样的逻辑：&lt;/p&gt;
&lt;ol&gt;
&lt;li style=&quot;padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;
在MouseDown事件中将isDragging标记设为true，表示“拖动开始”，并记录当前鼠标位置prevPos。&lt;/li&gt;&lt;li style=&quot;padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;
在MouseUp事件中将isDragging标记设为false，表示“拖动结束”。&lt;/li&gt;&lt;li style=&quot;padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;
在MouseMove事件中检查isDragging标记，如果为true，根据鼠标当前位置currPos和之前记录的prevPos进行绘图，并将currPos的&amp;#20540;写入prevPos。&lt;/li&gt;&lt;/ol&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
仅在这样一个最基本的场景中，我们便需要编写三个事件处理器（Event Handler），控制isDragging，prevPos等外部状态，并根据这些状态决定事件触发时的效果。这样的例子数不胜数，尤其是在各式拖放操作中，几乎都会涉及大量状态的控制（例如，判断物体是否进入某个特定区域）。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
异步编程的另一个难点，在于异步操作之间的组合及交互。例如在如上的简单拖放操作中，我们便涉及到了MouseDown，MouseUp及MouseMove三个事件。从某些角度来说，客户端的UI事件还是比较容易处理的，因为它们往往都是在单一线程上依次执行。但是在另外一些场景中，如云计算时，我们往往会同时发起多个异步操作，并根据这些操作的结果进行后续处理，甚至还会有一个额外的超时监控，这样便很有可能会出现并发操作的竞争（Race）情况，这将会成为程序复杂度的灾难。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
此外，异步操作还会破坏“代码局部性（Code Locality）”，这可能也是异步操作中最为常见的阻碍。程序员早已习惯了“线性”地表达逻辑，但即便是多个顺序执行的异步操作，也会因为大量的回调函数而将算法拆得支离破碎，更何况还会出现各种循环及条件判断。同时，在线性的代码中，我们可以使用“局部变量”保存状态，而在编写异步代码时则需要手动地在多个函数中传递状态。此外，由于逻辑被拆分至多个方法，因此我们也无法使用传统的try/catch进行统一异常处理。&lt;/p&gt;
&lt;h1 style=&quot;font-size:26px; margin-top:24px; margin-bottom:12px; padding-top:5px; padding-right:5px; padding-bottom:5px; padding-left:5px; color:white; background-color:gray&quot;&gt;
推模型与拉模型&lt;/h1&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
平时我们使用最多的便是“交互式（Interactive）”的编程方式，采用的是组件之间的相互调用来表现逻辑。例如，对象A向对象B请求数据并等待返回，待对象B完成并返还数据之后A才继续进行后面的操作。交互式编程的一个典型应用便是GoF23中的迭代器（Iterator）模式，它在.NET中的实现为IEnumerable及IEnumerator接口，例如：&lt;/p&gt;
&lt;pre class=&quot;code&quot; style=&quot;font-size:10pt; line-height:18px; border-top-color:rgb(192,192,192); border-right-color:rgb(192,192,192); border-bottom-color:rgb(192,192,192); border-left-color:rgb(108,226,108); border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:5px; border-top-style:dashed; border-right-style:dashed; border-bottom-style:dashed; border-left-style:solid; padding-top:8px; padding-right:8px; padding-bottom:8px; padding-left:8px; white-space:pre-wrap; word-wrap:break-word; font-family:Consolas,Monaco,'Lucida Console','Liberation Mono','DejaVu Sans Mono','Bitstream Vera Sans Mono','Courier New',宋体; margin-top:10px; margin-bottom:10px&quot;&gt;&lt;span style=&quot;color:blue&quot;&gt;void &lt;/span&gt;Traverse(&lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:blue&quot;&gt;int&lt;/span&gt;&amp;gt; source)
{
    &lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;etor = source.GetEnumerator();
    &lt;span style=&quot;color:blue&quot;&gt;while &lt;/span&gt;(etor.MoveNext())
    {
        &lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;Console&lt;/span&gt;.WriteLine(etor.Current);
    }
}&lt;/pre&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
为了更好地说明问题，这里我们将标准的foreach操作展开为传统的迭代器使用形式，并省略了using语句。在使用时，我们先调用一个IEnumerable对象的GetEnumerator方法，获得一个迭代器，再根据MoveNext及Current进行遍历。在调用MoveNext时，迭代器会去“准备”下一个元素，并根据存在与否返回true或者false。试想，如果其中某个MoveNext的“准备”工作涉及到一个耗时较长的操作，则迭代器的使用者也必须&amp;#30524;巴巴地等待其返回。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
这是一种“拉（Pull）”模型，数据由消费者（Consumer）从生产者（Producer）那里主动“拉”来。这是一种同步的交互方式，数据消费者会依赖于数据生产者的表现。这就好比我们去食堂吃饭时必须主动去取餐，此时则必须从队伍的最后排起，我们什么时候能结束等待并进行下一步操作（即“吃饭”），则要看食堂的生产速度如何。很显然，有些时候这种交互方式是不可接受的，例如我们在实现一个搜索引擎的“关键字提示”功能时，不可能让用户在输入一个字符后，必须等待远程的提示请求返回才能继续输入下一个字符。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
而与交互式编程对应的便是“响应式（Reactive）”编程。响应式编程是一种基于“改变”的编程方式。例如在交互式编程中，A = B &amp;#43; C这样的表达式意味着将B与C之和赋给A，而此后B与C的改变都与A无关。而在响应式编程中，A会去“响应”B或C的变化，即一旦B或C改变之后，A的&amp;#20540;也会随之变化。响应式编程的一个典型应用便是GoF23中的观察者（Observer）模式。与迭代器的IEnumerable/IEnumerator不同，在之前的.NET框架中并没有对这样一种编程模型指定“标准化（Formallized）”接口，不过在.NET
 4.0的基础类库中增加了IObservable及IObserver接口，签名如下：&lt;/p&gt;
&lt;pre class=&quot;code&quot; style=&quot;font-size:10pt; line-height:18px; border-top-color:rgb(192,192,192); border-right-color:rgb(192,192,192); border-bottom-color:rgb(192,192,192); border-left-color:rgb(108,226,108); border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:5px; border-top-style:dashed; border-right-style:dashed; border-bottom-style:dashed; border-left-style:solid; padding-top:8px; padding-right:8px; padding-bottom:8px; padding-left:8px; white-space:pre-wrap; word-wrap:break-word; font-family:Consolas,Monaco,'Lucida Console','Liberation Mono','DejaVu Sans Mono','Bitstream Vera Sans Mono','Courier New',宋体; margin-top:10px; margin-bottom:10px&quot;&gt;&lt;span style=&quot;color:blue&quot;&gt;public interface &lt;/span&gt;&lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;IObservable&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:blue&quot;&gt;out &lt;/span&gt;T&amp;gt;
{
    &lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;IDisposable &lt;/span&gt;Subscribe(&lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;IObserver&lt;/span&gt;&amp;lt;T&amp;gt; observer);
}

&lt;span style=&quot;color:blue&quot;&gt;public interface &lt;/span&gt;&lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;IObserver&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:blue&quot;&gt;in &lt;/span&gt;T&amp;gt;
{
    &lt;span style=&quot;color:blue&quot;&gt;void &lt;/span&gt;OnCompleted();
    &lt;span style=&quot;color:blue&quot;&gt;void &lt;/span&gt;OnError(&lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;Exception &lt;/span&gt;error);
    &lt;span style=&quot;color:blue&quot;&gt;void &lt;/span&gt;OnNext(T value);
}&lt;/pre&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
如果我们仔细比较“迭代器”与“观察者”的标准化接口，则会发现它们是完全“对偶（dual）”的：&lt;/p&gt;
&lt;ul style=&quot;margin-top:10px; margin-right:10px; margin-bottom:10px; margin-left:10px; list-style-type:none; list-style-position:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;
&lt;li style=&quot;padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:15px&quot;&gt;
IEnumerable.GetEnumerator方法“输出”一个IEnumerater对象；IObservable.Subscribe方法“输入”一个IObserver对象。&lt;/li&gt;&lt;li style=&quot;padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:15px&quot;&gt;
在遍历元素用尽时，IEnumerator.MoveNext方法返回false；在响应内容用尽时，IObserver.OnCompleted方法被调用。&lt;/li&gt;&lt;li style=&quot;padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:15px&quot;&gt;
在有新元素需要遍历时，IEnumerator.MoveNext方法返回true，并通过Current属性“输出”；在有新元素需要响应时，IObserver.OnNext方法被调用，并通过参数“输入”。&lt;/li&gt;&lt;li style=&quot;padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:15px&quot;&gt;
在出现错误时，IEnumerator.MoveNext方法会“抛出”一个异常；在出现错误时，IObserver.OnError方法会被调用，并通过参数“接受”异常信息。&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
至于IObservable.Subscribe方法返回的IDisposable对象，则用于“退定”操作，即让输入的IObserver对象再也不需要继续响应IObservable对象的新元素了。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
从比较中可以看出，如果说IEnumerator对象是由数据消费者使用的话，那么IObserver对象则是由数据的生产者，即IObservable对象使用的。换句话说，数据是由数据的生产者“推”给数据消费者的，是一种“推（Push）”模型。在这种异步的交互方式中，数据消费者不必依赖于数据生产者的表现。这就好比我们去饭店吃饭，点菜后便可坐下和同伴聊聊天或是用手机上上网，而作为菜品的生产者，饭店，则会在产出之后主动端上桌来。这么做无疑解放了数据的消费者，例如用户可以在文本框里不断地输入字符，而只需等远程服务器将提示结果“推”给客户端后再显示即可。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
许多模型都可以统一至标准的生产者接口IObservable上，如MouseMove事件便可以认做是“永不停止的MouseEventArgs对象的生产者”。而另一方面，单个异步操作则可以被视为“只产出单个数据便结束的生产者”。&lt;/p&gt;
&lt;h1 style=&quot;font-size:26px; margin-top:24px; margin-bottom:12px; padding-top:5px; padding-right:5px; padding-bottom:5px; padding-left:5px; color:white; background-color:gray&quot;&gt;
LINQ to Observable&lt;/h1&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
在许多人&amp;#30524;中，C# 3.0中新增的LINQ特性只是一种用于操作数据的DSL，它的主要作用也仅仅是针对IEnumerable或是IQueryable的数据操作。事实上，LINQ本身的能力远不止此。LINQ是一种非常简单的语言特性，编译器只是将LINQ查询语句转化为“字面等价”的“LINQ标准方法”调用（如Where，Select等等）和“和Lambda表达式”参数（如x =&amp;gt; x &amp;gt; 0）而已。但是这里的关键便是“字面等价”四个字，LINQ本身并不规定“LINQ标准方法”是对象的实例方法还是扩展方法，“Lambda表达式”是构造出一个匿名函数还是表达式树，这一切都是由利用LINQ的类库来决定的。因此，微软能够基于LINQ实现了PLINQ这样的并行类库。直到最近的访谈中，LINQ的设计者Erik
 Meijer依旧认为LINQ还是被低估了，他们自己也还在继续挖掘LINQ的更多能力。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
虽然LINQ本身在语法上只是一些方法调用，但是它在语义上是针对数据流的一系列操作，因此LINQ to Object，LINQ to SQL以及PLINQ可以认为是最自然，最符合LINQ语义的应用。如今，微软的“云编程能力团队（Cloud Programmability Team）”在其“响应式框架（Reactive Framework，简称Rx）”提供了LINQ to Observable，这又是另一个LINQ的经典使用案例。IObservable本身可以被认为是一股“推送数据”的数据流，因此也可以对其进行“过滤”或是“投影”等操作，这便是LINQ的应用场景，LINQ
 to Observable是对IObservable接口实现的一系列LINQ标准方法。因此，我们可以认为，LINQ to Observable是一套与LINQ to Object对偶的类库，事实上在响应式框架中，还有一套与LINQ to Queryable对偶的LINQ to Qbservable，请注意第一个字母是Q，我们可以把它看作是LINQ to Observable的“远程查询”版本。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
利用LINQ to Object可以编写出声明式（表示“做什么”）的代码，其可读性往往远高于等价的命令式（表示“怎么做”）代码。LINQ to Observable也有类&amp;#20284;的效果。假设现在有一个需求：利用ADWS键控制小球的位置。传统的写法可能是这样的：&lt;/p&gt;
&lt;pre class=&quot;code&quot; style=&quot;font-size:10pt; line-height:18px; border-top-color:rgb(192,192,192); border-right-color:rgb(192,192,192); border-bottom-color:rgb(192,192,192); border-left-color:rgb(108,226,108); border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:5px; border-top-style:dashed; border-right-style:dashed; border-bottom-style:dashed; border-left-style:solid; padding-top:8px; padding-right:8px; padding-bottom:8px; padding-left:8px; white-space:pre-wrap; word-wrap:break-word; font-family:Consolas,Monaco,'Lucida Console','Liberation Mono','DejaVu Sans Mono','Bitstream Vera Sans Mono','Courier New',宋体; margin-top:10px; margin-bottom:10px&quot;&gt;&lt;span style=&quot;color:blue&quot;&gt;void &lt;/span&gt;OnKeyPress(&lt;span style=&quot;color:blue&quot;&gt;object &lt;/span&gt;sender, &lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;KeyPressEventArgs &lt;/span&gt;e)
{
    // 如果游戏已经开始
    &lt;span style=&quot;color:blue&quot;&gt;if &lt;/span&gt;(isPlaying) &lt;span style=&quot;color:green&quot;&gt;&lt;/span&gt;
    {
        &lt;span style=&quot;color:green&quot;&gt;// 向左且小球没有超出边界&lt;/span&gt;
        &lt;span style=&quot;color:blue&quot;&gt;if &lt;/span&gt;(e.KeyChar == &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;'a'&lt;/span&gt; &amp;amp;&amp;amp; ball.Left &amp;gt; 0)
        {
            ball.Left -= 5;
        }
        &lt;span style=&quot;color:green&quot;&gt;// 向上且小球没有超出边界&lt;/span&gt;
        &lt;span style=&quot;color:blue&quot;&gt;else if &lt;/span&gt;(e.KeyChar == &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;'w'&lt;/span&gt; &amp;amp;&amp;amp; ball.Top &amp;gt; 0)
        {
            ball.Top -= 5;
        }
        &lt;span style=&quot;color:blue&quot;&gt;else &lt;/span&gt;... &lt;span style=&quot;color:green&quot;&gt;&lt;/span&gt;
    }
    &lt;span style=&quot;color:blue&quot;&gt;else &lt;/span&gt;...
}&lt;/pre&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
由于KeyPress事件总是不断触发，因此我们只能它的事件处理器中进行判断各种状态，采取不同措施。而如果我们利用LINQ to Observable，则几乎是另外一种思维方式：&lt;/p&gt;
&lt;pre class=&quot;code&quot; style=&quot;font-size:10pt; line-height:18px; border-top-color:rgb(192,192,192); border-right-color:rgb(192,192,192); border-bottom-color:rgb(192,192,192); border-left-color:rgb(108,226,108); border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:5px; border-top-style:dashed; border-right-style:dashed; border-bottom-style:dashed; border-left-style:solid; padding-top:8px; padding-right:8px; padding-bottom:8px; padding-left:8px; white-space:pre-wrap; word-wrap:break-word; font-family:Consolas,Monaco,'Lucida Console','Liberation Mono','DejaVu Sans Mono','Bitstream Vera Sans Mono','Courier New',宋体; margin-top:10px; margin-bottom:10px&quot;&gt;&lt;span style=&quot;color:green&quot;&gt;// 过滤出isPlaying时的keyPress事件
&lt;/span&gt;&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;keyPress = GetKeyPress().Where(_ =&amp;gt; isPlaying);

&lt;span style=&quot;color:green&quot;&gt;// 过滤出向左移动的事件
&lt;/span&gt;&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;moveLeft = &lt;span style=&quot;color:blue&quot;&gt;from &lt;/span&gt;ev &lt;span style=&quot;color:blue&quot;&gt;in &lt;/span&gt;keyPress
               &lt;span style=&quot;color:blue&quot;&gt;where &lt;/span&gt;ev.EventArgs.KeyChar == &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;'a'
               &lt;/span&gt;&lt;span style=&quot;color:blue&quot;&gt;where &lt;/span&gt;ball.Left &amp;gt; 0
               &lt;span style=&quot;color:blue&quot;&gt;select &lt;/span&gt;ev;
moveLeft.Subscribe(_ =&amp;gt; ball.Left -= 5);

&lt;span style=&quot;color:green&quot;&gt;// 过滤出向上移动的事件
&lt;/span&gt;&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;moveTop = &lt;span style=&quot;color:blue&quot;&gt;from &lt;/span&gt;ev &lt;span style=&quot;color:blue&quot;&gt;in &lt;/span&gt;keyPress
              &lt;span style=&quot;color:blue&quot;&gt;where &lt;/span&gt;ev.EventArgs.KeyChar == &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;'w'
              &lt;/span&gt;&lt;span style=&quot;color:blue&quot;&gt;where &lt;/span&gt;ball.Top &amp;gt; 0
              &lt;span style=&quot;color:blue&quot;&gt;select &lt;/span&gt;ev;
moveTop.Subscribe(_ =&amp;gt; ball.Top -= 5);&lt;/pre&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
我们可以将“KeyPress事件”视为“推送KeyPressEventArgs对象”这一数据流的数据源（由GetKeyPress方法返回），那么如今的代码便是使用LINQ过滤出“需要”的数据，并针对真正需要的那部分进行响应。这么做，便将“条件”与“操作”解耦，显著增强了代码的语义表达能力。事实上，只要补充一些辅助方法，可以利用LINQ表示更为完整复杂的逻辑。例如，微软咨询师Matthew Podwysocki便&lt;a href=&quot;http://codebetter.com/blogs/matthew.podwysocki/archive/2009/11/18/introduction-to-the-reactive-framework-part-v.aspx&quot; style=&quot;outline-style:none; outline-width:initial; outline-color:initial; text-decoration:none; color:rgb(61,129,238); border-bottom-width:1px; border-bottom-style:dashed&quot;&gt;在博客中展示过一段代码&lt;/a&gt;，基于LINQ
 to Observable实现了创建一个WebRequest对象，设置属性，异步发送及下载数据的一系列操作。&lt;/p&gt;
&lt;h1 style=&quot;font-size:26px; margin-top:24px; margin-bottom:12px; padding-top:5px; padding-right:5px; padding-bottom:5px; padding-left:5px; color:white; background-color:gray&quot;&gt;
更多扩展&lt;/h1&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
.NET基础类库针对IEnumerable定义了大量的函数式的辅助方法，开发人员可以直接将它们组合运用在项目中。除了标准的LINQ操作方法之外，响应式框架中同样定义了大量辅助方法，可以配合LINQ to Observable组合使用。例如本文开头所设想的鼠标“拖动及绘图”功能，便可以使用如下代码完成：&lt;/p&gt;
&lt;pre class=&quot;code&quot; style=&quot;font-size:10pt; line-height:18px; border-top-color:rgb(192,192,192); border-right-color:rgb(192,192,192); border-bottom-color:rgb(192,192,192); border-left-color:rgb(108,226,108); border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:5px; border-top-style:dashed; border-right-style:dashed; border-bottom-style:dashed; border-left-style:solid; padding-top:8px; padding-right:8px; padding-bottom:8px; padding-left:8px; white-space:pre-wrap; word-wrap:break-word; font-family:Consolas,Monaco,'Lucida Console','Liberation Mono','DejaVu Sans Mono','Bitstream Vera Sans Mono','Courier New',宋体; margin-top:10px; margin-bottom:10px&quot;&gt;&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;mouseMove = GetMouseMove();
&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;mouseDiff = mouseMove.Zip(mouseMove.Skip(1), (prev, curr) =&amp;gt;
    &lt;span style=&quot;color:blue&quot;&gt;new
    &lt;/span&gt;{
        PrevPos = &lt;span style=&quot;color:blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;Point&lt;/span&gt;(prev.EventArgs.X, prev.EventArgs.Y),
        CurrPos = &lt;span style=&quot;color:blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;Point&lt;/span&gt;(curr.EventArgs.X, curr.EventArgs.Y)
    });

&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;mouseDrag = &lt;span style=&quot;color:blue&quot;&gt;from &lt;/span&gt;_ &lt;span style=&quot;color:blue&quot;&gt;in &lt;/span&gt;GetMouseDown()
                &lt;span style=&quot;color:blue&quot;&gt;from &lt;/span&gt;diff &lt;span style=&quot;color:blue&quot;&gt;in &lt;/span&gt;mouseDiff.TakeUntil(GetMouseUp())
                &lt;span style=&quot;color:blue&quot;&gt;select &lt;/span&gt;diff;
mouseDrag.Subscribe(diff =&amp;gt; DrawLine(diff.PrevPos, diff.CurrPos));&lt;/pre&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
在这段代码中，我们首先将mouseMove事件使用Skip跳开一项，再与自身通过Zip方法组合成mouseDiff，这是一个输出相邻两次MouseMove事件坐标的数据源；接着，我们利用LINQ从触发MouseDown事件开始，向mouseDiff数据源获取每一项diff，直至（TakeUntil）触发MouseUp事件，以此生成最终的mouseDrag；最后再将绘图功能订阅至这个数据源上。您会发现此时我们已经无须手动维护操作过程中的各种状态了，从事件的“开始”到“结束”均使用响应式框架的辅助方法“声明”而来。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
以上便是一个利用了Skip，Zip，TakeUntil等辅助方法的例子。当然，这些辅助方法在IEnumerable上都有语义相同的对应操作，而在响应式框架中还有更多辅助方法是针对特性异步场景的。假设我们现在要编写一个即时翻译功能，同时发起三个请求，将中文分别翻译至英语、法语及西班牙语，并显示最先返回的两个结果（真是个奇怪的需求）。此外，我们不会在用户输入每个字符的时候便发起一个远程请求，而是在用户停止输入0.5秒之后才根据当前的输入框中的文字进行提示。于是我们可以编写这样的代码：&lt;/p&gt;
&lt;pre class=&quot;code&quot; style=&quot;font-size:10pt; line-height:18px; border-top-color:rgb(192,192,192); border-right-color:rgb(192,192,192); border-bottom-color:rgb(192,192,192); border-left-color:rgb(108,226,108); border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:5px; border-top-style:dashed; border-right-style:dashed; border-bottom-style:dashed; border-left-style:solid; padding-top:8px; padding-right:8px; padding-bottom:8px; padding-left:8px; white-space:pre-wrap; word-wrap:break-word; font-family:Consolas,Monaco,'Lucida Console','Liberation Mono','DejaVu Sans Mono','Bitstream Vera Sans Mono','Courier New',宋体; margin-top:10px; margin-bottom:10px&quot;&gt;&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;limit = &lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;TimeSpan&lt;/span&gt;.FromSeconds(0.5);
&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;translate =
    &lt;span style=&quot;color:blue&quot;&gt;from &lt;/span&gt;_ &lt;span style=&quot;color:blue&quot;&gt;in &lt;/span&gt;GetKeyPress().Throttle(limit)
    &lt;span style=&quot;color:blue&quot;&gt;let &lt;/span&gt;text = &lt;span style=&quot;color:blue&quot;&gt;this&lt;/span&gt;.txtInput.Text
    &lt;span style=&quot;color:blue&quot;&gt;where &lt;/span&gt;text.Length &amp;gt; 0
    &lt;span style=&quot;color:blue&quot;&gt;let &lt;/span&gt;english = &lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;Bing&lt;/span&gt;.Translate(text, &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;)
    &lt;span style=&quot;color:blue&quot;&gt;let &lt;/span&gt;french = &lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;Bing&lt;/span&gt;.Translate(text, &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;&amp;quot;fr&amp;quot;&lt;/span&gt;)
    &lt;span style=&quot;color:blue&quot;&gt;let &lt;/span&gt;spanish = &lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;Bing&lt;/span&gt;.Translate(text, &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;&amp;quot;es&amp;quot;&lt;/span&gt;)
    &lt;span style=&quot;color:blue&quot;&gt;from &lt;/span&gt;result &lt;span style=&quot;color:blue&quot;&gt;in &lt;/span&gt;&lt;span style=&quot;color:rgb(43,145,175)&quot;&gt;Observable&lt;/span&gt;.Join(
       english.And(french).Then((en, fr) =&amp;gt;
           &lt;span style=&quot;color:blue&quot;&gt;new &lt;/span&gt;{ English = en, French = fr, Spanish = &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt; }),
       english.And(spanish).Then((en, es) =&amp;gt;
           &lt;span style=&quot;color:blue&quot;&gt;new &lt;/span&gt;{ English = en, French = &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;, Spanish = es }),
       french.And(spanish).Then((fr, es) =&amp;gt;
           &lt;span style=&quot;color:blue&quot;&gt;new &lt;/span&gt;{ English = &lt;span style=&quot;color:rgb(163,21,21)&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;, French = fr, Spanish = es }))
    &lt;span style=&quot;color:blue&quot;&gt;select &lt;/span&gt;result;

translate.Subscribe(...);&lt;/pre&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
这里用到了Throottle方法，它会过滤某个数据源的输出，确保在该数据源“静默”特定时间之后，才将最近的一条数据推送至外部。此外，这里还使用了Observable.Join方法控制多个数据源，根据返回结果的先后获得合适的结果。响应式框架提供了大量针对某种异步场景的辅助方法，例如用于定期推送数据的Interval方法，从一个数据源根据特定条件进行采样的Sample方法，合并多个数据源的ForkJoin方法，以及表示流程控制的For，While，If等等。这些方法内部会维护各种所需要的状态，为我们打理各种复杂的竞争情况，以此节省了开发人员的精力。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
如果这些还不能满足我们的要求，我们也可以根据自己的需要开发特定的辅助方法，就像我们在使用LINQ to Object时为IEnumerable所作的各种扩展那样。响应式框架也提供了一系列Subject类型，简化了IObservable自定义扩展的开发过程。由于响应式框架尚未正式发布，微软目前建立了&lt;a href=&quot;http://rxwiki.wikidot.com/&quot; style=&quot;outline-style:none; outline-width:initial; outline-color:initial; text-decoration:none; color:rgb(61,129,238); border-bottom-width:1px; border-bottom-style:dashed&quot;&gt;一个Wiki&lt;/a&gt;，用于展示关于各辅助方法及Subject类的使用示例及其他相关信息。&lt;/p&gt;
&lt;h1 style=&quot;font-size:26px; margin-top:24px; margin-bottom:12px; padding-top:5px; padding-right:5px; padding-bottom:5px; padding-left:5px; color:white; background-color:gray&quot;&gt;
响应式框架的JavaScript版本&lt;/h1&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
响应式编程的重要使用场景之一便是与用户交互的GUI界面。例如，Silverlight禁止任何阻塞的IO操作，换言之Silverlight中的所有网络操作都是异步的，微软也正是出于简化异步开发的目的才设计了响应式框架（事实上响应式框架已经集成到Silverlight Toolkit中）。不过与Silverlight相比，基于浏览器的原生JavaScript应用程序无疑使用地更为广泛。对于这样的应用程序来说，动画是异步的，AJAX请求也是异步的，我们几乎可以断言，如果有一套面向JavaScirpt应用程序的响应式框架，一定会比面向Silverlight的框架更有意义得多。&lt;/p&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
微软也想到了这一点。之前我们讨论的“响应式框架”，其实只是响应式编程模型的一种实现。更确切地说，我们只是讨论了这套框架的.NET版本，微软还提供了JavaScript版本的响应式框架。JavaScript版本的API与.NET版本几乎完全一致，例如我们之前讨论的拖放操作，使用JavaScript即可写作：&lt;/p&gt;
&lt;pre class=&quot;code&quot; style=&quot;font-size:10pt; line-height:18px; border-top-color:rgb(192,192,192); border-right-color:rgb(192,192,192); border-bottom-color:rgb(192,192,192); border-left-color:rgb(108,226,108); border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:5px; border-top-style:dashed; border-right-style:dashed; border-bottom-style:dashed; border-left-style:solid; padding-top:8px; padding-right:8px; padding-bottom:8px; padding-left:8px; white-space:pre-wrap; word-wrap:break-word; font-family:Consolas,Monaco,'Lucida Console','Liberation Mono','DejaVu Sans Mono','Bitstream Vera Sans Mono','Courier New',宋体; margin-top:10px; margin-bottom:10px&quot;&gt;&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;target = $(&lt;span style=&quot;color:maroon&quot;&gt;&amp;quot;#dragTarget&amp;quot;&lt;/span&gt;);
&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;mouseMove = target.toObservable(&lt;span style=&quot;color:maroon&quot;&gt;&amp;quot;mousemove&amp;quot;&lt;/span&gt;);
&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;mouseDiff = mouseMove.Zip(mouseMove.Skip(1), 
    &lt;span style=&quot;color:blue&quot;&gt;function&lt;/span&gt;(prev, curr) {
        &lt;span style=&quot;color:blue&quot;&gt;return &lt;/span&gt;{
            PrevPos: { x: prev.clientX, y: prev.clientY },
            CurrPos: { x: curr.clientX, y: curr.clientY }
        };
    });

&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;mouseDown = target.toObservable(&lt;span style=&quot;color:maroon&quot;&gt;&amp;quot;mousedown&amp;quot;&lt;/span&gt;);
&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;mouseUp = target.toObservable(&lt;span style=&quot;color:maroon&quot;&gt;&amp;quot;mouseup&amp;quot;&lt;/span&gt;);
&lt;span style=&quot;color:blue&quot;&gt;var &lt;/span&gt;mouseDrag = mouseDown.SelectMany(&lt;span style=&quot;color:blue&quot;&gt;function&lt;/span&gt;() {
    mouseDiff.TakeUntil(mouseUp);
});

mouseDrag.Subscribe(...);&lt;/pre&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
由于没有C#中的LINQ查询语言，我们只能直接使用展开后的方法，如SelectMany来编写逻辑。JavaScript版本的响应式框架还提供了一系列的“胶合”层，能够与jQuery，Dojo，MooTools，Prototype等流行框架同时使用。例如，上一段代码中的toObservable便是在jQuery根对象上扩展的方法。&lt;/p&gt;
&lt;h1 style=&quot;font-size:26px; margin-top:24px; margin-bottom:12px; padding-top:5px; padding-right:5px; padding-bottom:5px; padding-left:5px; color:white; background-color:gray&quot;&gt;
总结&lt;/h1&gt;
&lt;p style=&quot;margin-top:12px; margin-right:auto; margin-bottom:12px; margin-left:auto; line-height:25px&quot;&gt;
异步编程在用户交互式界面及一些云计算场景中尤其重要。微软的云编程能力团队针对.NET平台和JavaScirpt分别提供了一套响应式框架，希望以此简化异步程序的开发。不过，这套响应式框架所表现出的理念是通用的。而且，事实上只要是拥有匿名函数及闭包的语言，例如Scala，Python，Ruby等等，实现这样一套框架其实都不是十分困难的事情。&lt;/p&gt;
&lt;br&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-5-21 23:47:02 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7589215&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：92 评论：1 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7589215#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/640924749/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7589215&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Mon, 21 May 2012 23:47:02 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7589215</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7589215</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/640924749/1166164</fs:itemid></item><item><title>[转][转] 淘宝技术发展</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7554533</link><description>&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:rgb(64,64,64); font-family:verdana,Arial,Helvetica; line-height:19px; background-color:rgb(250,255,255)&quot;&gt;作者:&amp;nbsp;&lt;a href=&quot;http://blog.sina.com.cn/calvinzhaoc&quot; target=&quot;_blank&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;赵超&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:rgb(64,64,64); font-family:verdana,Arial,Helvetica; line-height:19px; background-color:rgb(250,255,255)&quot;&gt;来源：http://blog.sina.com.cn/s/blog_633219970100x9cc.html&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:rgb(64,64,64); font-family:verdana,Arial,Helvetica; line-height:19px; background-color:rgb(250,255,255)&quot;&gt;&lt;br&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:rgb(64,64,64); font-family:verdana,Arial,Helvetica; line-height:19px; background-color:rgb(250,255,255)&quot;&gt;&lt;span style=&quot;color:rgb(35,35,35); font-family:verdana,Arial,Helvetica; font-size:14px; line-height:28px; background-color:rgb(250,255,255)&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　目录&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　一、&lt;a href=&quot;http://kb.cnblogs.com/page/132724/#c1&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;引言&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　二、&lt;a href=&quot;http://kb.cnblogs.com/page/132724/#c2&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;个人网站&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　三、&lt;a href=&quot;http://kb.cnblogs.com/page/132724/#c3&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;Oracle/支付宝/旺旺&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　四、&lt;a href=&quot;http://kb.cnblogs.com/page/132724/#p4&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;淘宝技术发展（Java时代：脱胎换骨）&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　五、&lt;a href=&quot;http://kb.cnblogs.com/page/132724/#p5&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;淘宝技术发展（Java时代：坚若磐石）&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　六、&lt;a href=&quot;http://kb.cnblogs.com/page/132724/#p6&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;淘宝技术发展（Java时代：创造技术-TFS）&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　作者：赵超&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　&lt;a name=&quot;c1&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;&lt;/a&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51)&quot;&gt;&lt;strong&gt;一、引言&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51)&quot;&gt;&lt;strong&gt;　　光棍节的狂欢&lt;/strong&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　“时间到，开抢！”坐在电脑前早已等待多时的小美一看时间已到2011年11月11日零时，便迫不及待地投身于淘宝商城一年一度的大型网购促销活动——“淘宝双11购物狂欢节”。小美打开早已收藏好的宝贝——某品牌的雪地靴，飞快的点击购买，付款，一回头发现3000双靴子已被抢购一空。&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　小美跳起来，大叫一声“欧耶！”&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　小美不知道，就在11日零点过后的这一分钟内，全国有342万人和她一起涌入淘宝商城。当然，她更不知道，此时此刻，在淘宝杭州的一间办公室里，灯火通明，这里是“战时指挥部”，淘宝技术部的一群工程师，正在紧盯着网站的流量和交易数据。白板上是他们刚刚下的注，赌谁能最准确地猜中流量峰&amp;#20540;和全天的交易总额。他们的手边放着充足的食物和各类提神的饮料。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　一阵急促的电话声响起来，是前线部门询问数据的，工程师大声报着：“第1分钟，进入淘宝商城的会员有342万”。过一会工程师主动拿起电话：“交易额超过1亿了，现在是第8分钟。”接下来，“第21分钟，刚突破2亿”。“第32分钟，3亿了”。“第1个小时，4.39亿”。这些数据随后出现在微博上，引起一片惊呼。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　“完蛋了！”突然有人大喝一声，所有的&amp;#30524;睛都紧张的盯着他，只见他挠挠头，嘿嘿的笑道“我赌的少了，20亿轻松就能过了，我再加5亿”，他跑去白板边上把自己的赌注擦去，写上25，接下来有人写上28，有人写上30，有人跑到微博上开下盘口，同事们纷纷转载下注。接下来的这24个小时，战时指挥部的工程师们都不能休息，他们盯着网站的各种监控指标，适时的调整机器和增减功能。顶住第一波高峰之后，这些人开始忙里偷闲的给自己买东西，大家互相交流着哪家买的移动硬盘靠谱，哪家衣服适合自己的女朋友，不时的有人哀嚎宝贝被人抢了、信用卡额度不够了。同时，旁边白板上的赌注越下越大。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;img src=&quot;http://pic001.cnblogs.com/images/2012/1/2012022511094742.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　11月11日，这个棍子最多的日子被网民自我调侃的变成了一个节日——“光棍节”。而淘宝网又用疯狂的折扣促销给它赋予了另外一个意义——“购物狂欢节”。2011年11月11日这一天，淘宝商城与淘宝网交易额之和突破52亿，这个数字是“购物天堂”香港一天零售总额8.5亿的6倍。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　网民感受到的是疯抢的喜悦，而网站的技术人员感受到的却是“压力山大”。就如同你家办酒席，宴请左邻右舍，这个办起来容易。倘若宴请十里八乡所有的人，吃饭的人自然开心，但却不是一般人家能够办得起来的。能办得起来如此盛宴者，需要强大的财力物力、组织能力、技术实力（例如做这么多菜，你的炒锅一定要是“分布式的”、“可复制的”、“可扩展的”，洗菜切菜要有“工作流引擎”，上菜的路径要用图论来计算出来，甚至连厨房的下水道都要重新设计）。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　淘宝能够举办如此盛宴，网站的技术实力可见一斑。淘宝网拥有全国最大的Hadoop分布式计算集群之一，日新增数据50TB，有40PB海量数据存储。分布在全国各地80多个节点的CDN网络，支持的流量超过800Gbps。淘宝的搜索引擎能够对数十亿的商品数据进行实时搜索，另外还拥有自主研发的文件存储系统和缓存系统，以及Java中间件和消息中间件系统，这一切组成了一个庞大的电子商务操作系统。另外从商业数据上来看，Amazon的财报显示2011年完成了大约480亿美金的交易额，eBay 2011年财报全年完成了大约600亿美金的交易额（不包括其独立的汽车交易平台）。不管从交易额、商品数量、同比增速等指标上看，淘宝网均远超于此，是目前全球最大的电子商务平台。（由于淘宝非上市公司，未公布2011年业绩，以上内容来自淘宝网技术副总裁&lt;a href=&quot;http://weibo.com/u/1419403675&quot; target=&quot;_blank&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;@_行癫&lt;/a&gt;&amp;nbsp;的微博）&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　以上这些技术数据可能已经让一些同学产生不适的感觉，为了让更多的人读懂这本书，我们从技术的角度来看，小美访问淘宝网的时候，网站上发生了什么事情。参考资料：《&lt;a href=&quot;http://kb.cnblogs.com/page/132716/&quot; target=&quot;_blank&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;技术普及帖：你刚才在淘宝上买了一件东西&lt;/a&gt;》，来自南京邮电大学孙放同学。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　为了有个更直观的对比，我们说一个同行，他在2011年光棍节之前做促销，流量上去之后，达到12Gbps（他们有这么大的流量，老板很高兴，在微博上面说了这个数据），这时候流量达到了极限，网站几乎挂掉，用户无法下订单。而淘宝网光棍节当天网络的流量最高达到800多Gbps，带给各家银行和快递公司的流量也让他们压力山大，如临大敌（后来，他们以能够撑住淘宝带来的流量为荣而到处宣传）。另外如果你在网上购买过火车票的话，更能体会到网站能支持多大的流量有多重要。但这不是一朝一夕做出来的，也不是有钱就能办到的。&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　以上对比的这些网站，也许读者很容易就猜到是哪一家，这里拿出来作对比，绝对没有嘲笑人家的意思，采用通常的网站技术方案，能做到这种程度已经不错了。任何网站的发展都不是一蹴而就的，在什么样的阶段采用什么样的技术。在发展的过程中网站会遇到各种各样的问题和业务带来的压力，正是这些原因才推动着技术的进步和发展，而技术的发展又会反过来促进业务的更大提升。二者互为因果，相互促进。如今淘宝网的流量已经是全球排名第12、国内排名第3（美国的eBay全球排名23，国内前两名是百度和腾讯）。淘宝网的系统也从使用一台服务器，到采用万台以上的服务器。本书就为大家描述淘宝网在整个发展过程中，所有的主动和被动的技术变革的前因后果，这由很多有趣的故事组成。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　正如同很多人或组织成功了以后，就会为自己的出身编造一个美丽的传说。淘宝网的出身，网上也有非常多的传说，下面我们就从它的出生开始讲起。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51)&quot;&gt;&lt;strong&gt;　　&lt;a name=&quot;c2&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;&lt;/a&gt;二、个人网站&lt;/strong&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　2003年4月7日，马云，在杭州，成立了一个神秘的组织。他叫来十位员工，&lt;/span&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;要他们签了一份协议，这份协议要求他们立刻离开阿里巴巴，去做一个神秘的项目。这个项目要求绝对保密，老马戏称“连说梦话被老婆听到都不行，谁要是透漏出去，我将追杀到天涯海角”。这份协议是英文版的，匆忙之间，大多数人根本来不及看懂，但出于对老马的信任，都卷起铺盖离开了阿里巴巴。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　他们去了一个神秘的据点——湖畔花园小区的一套未装修的房子里，房子的主人是马云。这伙人刚进去的时候，马云给他们布置了一个任务，就是在最短的时间内做出一个个人对个人（C2C）的商品交易的网站。现在出一个问题考考读者，看你适不适合做淘宝的创业团队。亲，要是让你来做，你怎么做？&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　在说出这个答案之前，容我先卖个关子，介绍一下这个创业团队的成员：三个开发工程师（虚竹、三丰、多隆）、一个UED（二当家）、三个运营（小宝、阿珂、破天）、一个经理（财神）、还有就是马云和他的秘书。当时对整个项目组来说压力最大的就是时间，怎么在最短的时间内把一个从来就没有的网站从零开始建立起来？了解淘宝历史的人知道淘宝是在2003年5月10日上线的，这之间只有一个月。要是你在这个团队里，你怎么做？我们的答案就是：买一个来。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　买一个网站显然比做一个网站要省事一些，但是他们的梦想可不是做一个小网站而已，要做大，就不是随便买个就行的，要有比较低的维护成本，要能够方便的扩展和二次开发。那接下来就是第二个问题：买一个什么样的网站？答案是：轻量一点的，简单一点的，于是买了这样一个架构的网站：LAMP(Linux&amp;#43;Apache&amp;#43;MySQL&amp;#43;PHP)。这个直到现在还是一个很常用的网站架构模型。这种架构的优点是：无需编译，发布快速，PHP功能强大，能做从页面渲染到数据访问所有的事情，而且用到的技术都是开源的，免费。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　当时我们是从一个美国人那里买来的一个网站系统，这个系统的名字叫做PHPAuction（他们的官方网站&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;http://www.phpauction.net，&lt;/span&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;这个名字很直白，一&amp;#30524;就看出来这个系统是用什么语言做的、是干什么用的），PHPAuction有好几个版本，我们买的是最高版的，功能比较多，而且最重要的是对方提供了源代码。最高版比较贵，花了我们2000美金（貌&amp;#20284;现在降价了，只要946美元）。买来之后不是直接就能用的，需要很多本地化的修改，例如页面模板改的漂亮一点，页头页脚加上自己的站点简介等，其中最有技术含量的是对数据库进行了一个修改。原来是从一个数据库进行所有的读写操作，拿过来之后多隆把它给拆分成一个主库、两个从库，读写分离。这么做的好处有几点：存储容量增加了，有了备份，使得安全性增加了，读写分离使得读写效率提升了。这样整个系统的架构就如下图所示：&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;img src=&quot;http://pic001.cnblogs.com/images/2012/1/2012022511225985.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　其中Pear DB是一个PHP模块，负责数据访问层。另外也用开源的论坛系统PHPBB（&lt;/span&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;http://www.phpbbchina.com&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;）搭建了一个小的论坛社区，虚竹负责机器采购、配置、架设等，三丰和多隆负责编码，他们把交易系统和论坛系统的用户信息打通，给运营人员开发出后台管理（admin系统）的功能，把交易类型从只有拍卖这一种增加为拍卖、一口价、求购商品、海报商品（意思是还没推出的商品，先挂个海报出来）这四种。（PHPAuction只有拍卖的交易，Auction即拍卖的意思。@_行癫在微博中提到：&lt;/span&gt;今天eBay所有交易中拍卖交易仍然占了40%，而在中国，此种模式在淘宝几乎从一开始就未能占据优势，如今在主流的交易中几乎可以忽略不计。背后的原因一直令人费解。我大致可以给出其中一种解释，eBay基本在发达国家展开业务，制造业外包后，电子商务的基本群体大多只能表现为零散的个体间交易。&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;）&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　在经历了另外一些有趣的事情之后（这些有趣的事情包括“淘宝”这个名字的由来，&lt;/span&gt;&lt;a href=&quot;http://www.neweekly.com.cn/index/newsview.php?id=1263&quot; target=&quot;_blank&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;员工花名的由来&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;等等，由于本书主要描述技术方面的故事，对这些有兴趣的可以去网上找），网站开始上线运行了。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;img src=&quot;http://pic001.cnblogs.com/images/2012/1/2012022511260456.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　在接下来的大半年时间里，这个网站迅速显示出了它的生机。这里有必要提一下当时的市场环境，非典（SARS）的肆虐使得大家都不敢出门，尤其是去商场之类人多的地方。另外在神州大地上最早出现的C2C网站易趣也正忙的不亦乐乎，2002年3月，eBay以3000万美元收购了易趣公司33%的股份，2003年6月以1.5亿美元收购了易趣公司剩余67%的股份。当时淘宝网允许买卖双方留下联系方式，允许同城交易，整个操作过程简单轻松。而eBay为了收取交易佣金，是禁止这么做的，这必然增加了交易过程的难度。而且eBay为了全球统一，把易趣原来的系统替换成了美国eBay的系统，用户体验一下子全变了，操作起来非常麻烦，这等于是把积累的用户拱手送给了淘宝。为了不引起eBay的注意，淘宝网在2003年里一直声称自己是一个“个人网站”。由于这个创业团队强大的市场开拓和运营能力，淘宝网发展的非常迅猛，2003年底就吸引了注册用户&lt;/span&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;XXX&lt;/span&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;，最高每日31万PV，从5月到年底成交额4000万。这没有引起eBay的注意，却引起了阿里巴巴内部很多员工的注意，他们觉得这个网站以后会成为阿里巴巴强劲的对手。甚至有人在内网发帖，忠告管理层要警惕这个刚刚起步的网站，但管理层&amp;#20284;乎无动于衷。（这个团队的保密工作做的真好）&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　在市场和运营的后方，淘宝网的技术团队也在快速的做着系统的改进和创新。这里还有个有趣的故事，eBay和易趣早期都有员工在论坛上响应用户的需求，eBay的论坛用粉红色背景来区分员工的发言，易趣的员工在论坛上昵称都选各种豆豆，例如黄豆豆、蚕豆豆等。淘宝在讨论运营策略的时候提到这个问题，要求所有的员工都去论坛上回答用户的问题。最早回答问题的任务落在小宝头上，那我们用什么名字好呢？“淘淘”？“宝宝”？小宝都不满意，太女性化了。讨论了很久之后，小宝灵光乍现，干脆取个名字叫“小宝”吧，小宝带七个老婆来开店，迎接各位客官，很有故事性。于是很多武侠小说中的人物开始在论坛中行侠仗义，这些昵称下面标志着“淘宝店小二”，他们回答着各种各样的问题，快速响应着用户的各种需求。如果是技术上能解决的，几个人商量一下，马上就开发、测试、发布上线。反过来对比一下，易趣被eBay收购之后，系统更换成了全球通用的版本，响应用户的一个需求需要层层审批，反应速度自然慢了下来。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　当时淘宝第一个版本的系统里面已经包含了商品发布、管理、搜索、商品详情、出价购买、评价投诉、我的淘宝这些功能（现在主流程中也是这些模块。在2003年10月增加了一个功能节点：“安全交易”，这个是支付宝的雏形）。随着用户需求和流量的不断增长，系统上面做了很多的日常改进，服务器由最初的一台变成了三台，一台负责发送email、一台负责运行数据库、一台负责运行Web
 App。过一段时间之后，商品搜索的功能占用数据库资源太大了（用like搜索的，很慢），又从阿里巴巴中文站搬过来他们的搜索引擎iSearch，起初iSearch索引的文件放在硬盘上，随着数据量的增长，又采购了NetApp服务器放置iSearch。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　如此快节奏的工作，其实大家都累得不行，有人就提议大家随时随地的锻炼身体，可是外面SARS横行，在一个一百多方的房子里，怎么锻炼呢？高挑美女阿珂提议大家练习提臀操，这个建议遭到男士的一致反对，后来虚竹就教大家练习倒立，这个大家都能接受。于是这个倒立的传统一直延续至今，和花名文化、武侠文化一并传承了下来。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　随着访问量和数据量的飞速上涨，问题很快就出来了，第一个问题出现在数据库上。MySQL当时是第4版的，我们用的是默认的存储引擎MyISAM，这种类型读数据的时候会把表锁住（我们知道Oracle在写数据的时候会有行锁，读数据的时候是没有的），尤其是主库往从库上面写数据的时候，会对主库产生大量的读操作，使得主库性能急剧下降。这样在高访问量的时候，数据库撑不住了。另外，当年的MySQL不比如今的MySQL，在数据的容量和安全性方面也有很多先天的不足（和Oracle相比）。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　&lt;a name=&quot;c3&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;&lt;/a&gt;三、&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51)&quot;&gt;&lt;strong&gt;Oracle/支付宝/旺旺&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　淘宝网作为个人网站发展的时间其实并不长，由于它太引人注目了，马云在 2003 年 7 月就宣布了这个是阿里巴巴旗下的网站，随后在市场上展开了很成功的运作。最著名的就是利用中小网站来做广告，突围 eBay 在门户网站上对淘宝的广告封锁。上网比较早的人应该还记得那些在右下角的弹窗和网站腰封上一闪一闪的广告。市场部那位到处花钱买广告的家伙，太能花钱了，一出手就是几百万，他被我们称为“大少爷”。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　“大少爷”们做的广告，带来的就是迅速上涨的流量和交易量。在 2003 年底，MySQL 已经撑不住了，技术的替代方案非常简单，就是换成 Oracle。换 Oracle 的原因除了它容量大、稳定、安全、性能高之外，还有人才方面的原因。在 2003 年的时候，阿里巴巴已经有一支很强大的 DBA 团队了，有冯春培、汪海（七公）这样的人物，后来还有冯大辉（@fenng）、陈吉平（拖雷）。这样的人物牛到什么程度呢？Oracle 给全球的技术专家颁发一些头衔，其中最高级别的叫 ACE（就是扑克牌的“尖儿”，够大的吧），被授予这个头衔的人目前全球也只有
 300 多名（名单在这里：&amp;nbsp;&lt;a href=&quot;http://apex.oracle.com/pls/otn/f?p=19297:3&quot; target=&quot;_blank&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;http://apex.oracle.com/pls/otn/f?p=19297:3&lt;/a&gt;&amp;nbsp;），当年全球只有十几名。有如此强大的技术后盾，把
 MySQL 换成 Oracle 是顺理成章的事情。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　但更换数据库不是只换个库就可以的，访问方式，SQL 语法都要跟着变，最重要的一点是，Oracle 并发访问能力之所以如此强大，有一个关键性的设计——连接池。但对于 PHP 语言来说它是放在 Apache 上的，每一个请求都会对数据库产生一个连接，它没有连接池这种功能（Java 语言有 Servlet 容器，可以存放连接池）。那如何是好呢？这帮人打探到 eBay 在 PHP 下面用了一个连接池的工具，是 BEA 卖给他们的。我们知道 BEA 的东西都很贵，我们买不起，于是多隆在网上寻寻觅觅，找到一个开源的连接池代理服务
 SQLRelay（&amp;nbsp;&lt;a href=&quot;http://sourceforge.jp/projects/freshmeat_sqlrelay/&quot; target=&quot;_blank&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;http://sourceforge.jp/projects/freshmeat_sqlrelay&lt;/a&gt;&amp;nbsp;），这个东西能够提供连接池的功能，多隆对它进行了一些功能改进之后就拿来用了。这样系统的架构就变成了如下的样子：&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;img src=&quot;http://pic003.cnblogs.com/2012/1/201202/2012022510245823.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　数据一开始是放在本地的，DBA 们对 Oracle 做调优的工作，也对 SQL 进行调优。后来数据量变大了，本地存储不行了。买了 NAS（NetworkAttached Storage：网络附属存储），NetApp 的 NAS 存储作为了数据库的存储设备，加上 Oracle RAC（Real Application Clusters，实时应用集群）来实现负载均衡。七公说这实际上是走了一段弯路，NAS 的 NFS（Network File System）协议传输的延迟很严重，但那时侯不懂。后来采购了 Dell
 和 EMC 合作的 SAN 低端存储，性能一下子提升了 10 几倍，这才比较稳定了。再往后来数据量更大了，存储的节点一拆二、二拆四，RAC 又出问题了。这才踏上了购买小型机的道路。在那段不稳定的时间里，七公曾经在机房住了 5 天 5 夜。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　替换完数据库，时间到了 2004 年春天，俗话说“春宵一刻&amp;#20540;千金”，但这些人的春宵却不太好过了。他们在把数据的连接放在 SQLRelay 之后就噩梦不断，这个代理服务经常会死锁，如同之前的 MySQL 死锁一样。虽然多隆做了很多修改，但当时那个版本内部处理的逻辑不对，问题很多，唯一解决的办法就是“重启”它的服务。这在白天还好，连接上机房的服务器，把进程杀掉，然后开启就可以了，但是最痛苦的是它在晚上也要死掉，于是工程师们不得不 24 小时开着手机，一旦收到“SQLRelay 进程挂起”的短信，就从春梦中醒来，打开电脑，连上机房，重启服务。后来干脆每天睡觉之前先重启一下。做这事最多的据说是三丰，他现在是淘宝网的总裁。现在我们知道，任何牛B的人物，都有一段苦B的经历。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　微博上有人说“好的架构是进化来的，不是设计来的”。的确如此，其实还可以再加上一句“好的功能也是进化来的，不是设计来的”。在架构的进化过程中，业务的进化也非常迅猛。最早的时候，买家打钱给卖家都是通过银行转账汇款，有些骗子收了钱却不发货，这是一个很严重的问题。然后这伙人研究了 PayPal 的支付方式，发现也不能解决问题。后来这几个聪明的脑袋又想到了“担保交易”这种第三方托管资金的办法。于是在 2003 年 10 月，淘宝网上面上线了一个功能，叫做“安全交易”，卖家选择支持这种功能的话，买家会把钱交给淘宝网，等他收到货之后，淘宝网再把钱给卖家。这就是现在的支付宝，在前两天（2012.2.21）年会上，支付宝公布
 2011 年的交易笔数已经是 PayPal 的两倍。这个划时代的创新，其实就是在不断的思索过程中的一个灵光乍现。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　当时开发“安全交易”功能的是茅十八和他的徒弟苗人凤（茅十八开发到一半去上海读 MBA 去了，苗人凤现在是支付宝的首席业务架构师），开发跟银行网关对接的功能的是多隆。当时多数银行的网站已经支持在线支付了，但多隆告诉我，他们的网关五花八门，用什么技术的都有，必须一家一家去接。而且他们不保证用户付钱了就一定扣款成功、不保证扣款成功了就一定通知淘宝、不保证通知淘宝了就一定能通知到、不保证通知到了就不重复通知。这害苦了苗人凤，他必须每天手工核对账单，对不齐的话就一定是有人的钱找不到地方了，少一分钱都睡不着觉。另外他为了测试这些功能，去杭州所有的银行都办理了一张银行卡。一堆银行卡摆在桌子上，不知道的人还以为这个家伙一定很有钱，其实里面都只是十块八块的。现在我们再一次知道，任何牛B的人物，都必须有一段苦B的经历。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　有人说淘宝打败易趣（eBay 中国）是靠免费，其实这只是原因之一。如果说和易趣过招第一招是免费的话，这让用户没有门槛就愿意来，那第二招就是“安全支付”，这让用户放心付款，不必担心被骗。在武侠小说中真正的高手飞花摘叶即可伤人，他们不会局限于一招两招，一旦出手，连绵不绝。而淘宝的第三招就是“旺旺”，让用户在线沟通。其实淘宝旺旺也不是自己生出来的，是从阿里巴巴的“贸易通”复制过来的。从 2004 年 3 月开始，“叮咚、叮咚”这个经典的声音就回荡在所有淘宝买家和卖家的耳边，“亲，包邮不？”，“亲，把零头去掉行不？”，这亲切的砍价声造就了后来的“淘宝体”。有人说中国人就是爱砍价，虽然笔者体会不到砍价成功后有多少成就感，但每次我去菜市场，看到大妈们砍价砍得天昏地暗，那满足的劲头堪比捡到了钱，我就深刻的理解了淘宝旺旺在交易过程中的价&amp;#20540;。我猜
 eBay 也体会不到砍价的乐趣，他们一直不允许买卖双方在线聊天，收购了 skype 之后也没有用到电子商务中去。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　旺旺在推出来没多久，就惹了一个法律方面的麻烦。有个做雪饼的厂家找上门来，说我们侵权了，他们家的雪饼很好吃，牛奶也做得不错，我们都很喜欢。然后我们就在旺旺的前面加了两个字，叫做“淘宝旺旺”。在那个野蛮生长的阶段，其实很多产品都是想到什么就做什么，例如我们还搭建过一个聊天室，但&amp;#20284;乎淘宝网不是一个闲聊的地方，这个聊天室门可罗雀，一段时间后就关闭掉了。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　SQLRelay 的问题搞得三丰他们很难睡个囫囵觉，那一年开半年会的时候，公司特地给三丰颁了一个奖项，对他表示深切的安慰。但不能总这样啊，于是，2004年的上半年开始，整个网站就开始了一个脱胎换骨的手术。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51)&quot;&gt;&lt;strong&gt;　　&lt;a name=&quot;p4&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;&lt;/a&gt;淘宝技术发展（Java时代：脱胎换骨）&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　我的师父黄裳@岳旭强曾经说过，“好的架构图充满美感”，一个架构好不好，从审美的角度就能看得出来。后来我看了很多系统的架构，发现这个言论基本成立。那么反观淘宝前面的两个版本的架构，你看哪个比较美？&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;img src=&quot;http://pic003.cnblogs.com/2012/1/201204/2012040311224715.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;img src=&quot;http://pic003.cnblogs.com/2012/1/201204/2012040311231311.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　显然第一个比较好看，后面那个显得头重脚轻，这也注定了它不是一个稳定的版本，只存活了不到半年的时间。2004年初，SQL Relay 的问题解决不了，数据库必须要用 Oracle，那从哪里动刀？只有换开发语言了。换什么语言好呢？Java。Java 是当时最成熟的网站开发语言，它有比较良好的企业开发框架，被世界上主流的大规模网站普遍采用，另外有 Java 开发经验的人才也比较多，后续维护成本会比较低。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　到 2004 年上半年，淘宝网已经运行了一年的时间，这一年积累了大量的用户，也快速的开发了很多功能，当时这个网站已经很庞大了，而且新的需求还在源源不断的过来。把一个庞大的网站的开发语言换掉，无异于脱胎换骨，在换的过程中还不能拖慢业务的发展，这无异于边换边跑，对时间和技术能力的要求都非常高。做这样的手术，需要请第一流的专家来主刀。现在再考一下读者，如果你在这个创业团队里面，请什么样的人来做这事？我们的答案是请 Sun 的人。没错，就是创造 Java 语言的那家公司，世界上没有比他们更懂 Java 的了。除此之外，还有一个不为人知的原因，……（此处和谐掉
 200 字，完整版见 aliway）&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　这帮 Sun 的工程师的确很强大，在笔者 2004 年底来淘宝的时候，他们还在，有幸跟他们共事了几个月。现在摆在他们面前的问题是用什么办法把一个庞大的网站从 PHP 语言迁移到 Java？而且要求在迁移的过程中，不停止服务，原来系统的 bugfix 和功能改进不受影响。亲，你要是架构师，你怎么做？有人的答案是写一个翻译器，如同把中文翻译成英文一样，自动翻译。我只能说你这个想法太超前了，换个说法就是“too simple, sometimes naive”。当时没有，现在也没有人能做到。他们的大致方案是给业务分模块，一个模块一个模块的替换。如用户模块，老的
 member.taobao.com 继续维护，不添加新功能，新的功能先在新的模块上开发，跟老的共用一个数据库，开发完毕之后放到不同的应用集群上，另开个域名 member1.taobao.com，同时替换老的功能，替换一个把老的模块上的功能关闭一个，逐渐的把用户引导到 member1.taobao.com，等所有功能都替换完毕之后，关闭 member.taobao.com。后来很长时间里面都是在用 member1 这样奇怪的域名，两年后有另外一家互联网公司开始做电子商务了，我们发现他们的域名也叫 member1.xx.com、auction1.xx.com……　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　说了开发模式，再说说用到的 Java MVC 框架，当时的 struts1.x 是用的比较多的框架，但是用过 webwork 和 struts2 的同学可能知道，struts1.x 在多人协作方面有很多致命的弱点，由于没有一个轻量框架作为基础，因此很难扩展，这样架构师对于基础功能和全局功能的控制就很难做到。而阿里巴巴的 18 个创始人之中，有个架构师，在 Jakarta Turbine 的基础上，做了很多扩展，打造了一个阿里巴巴自己用的 MVC 框架 WebX （&lt;a href=&quot;http://www.openwebx.org/docs/Webx3_Guide_Book.html&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;http://www.openwebx.org/docs/Webx3_Guide_Book.html&lt;/a&gt;），这个框架易于扩展，方便组件化开发，它的页面模板支持
 JSP 和 velocity 等、持久层支持 ibatis 和 hibernate 等、控制层可以用 EJB 和 Spring（Spring 是后来才有的）。项目组选择了这个强大的框架，这个框架如果当时开源了，也许就没有 webwork 和 struts2 什么事了。另外，当时 Sun 在全世界大力推广他们的 EJB，虽然淘宝的架构师认为这个东东用不到，但他们还是极力坚持。在经历了很多次的技术讨论、争论和争吵之后，这个系统的架构就变成了下图的样子：&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; text-align:center&quot;&gt;&lt;img src=&quot;http://pic003.cnblogs.com/2012/1/201204/2012040311284641.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　Java 应用服务器是 Weblogic，MVC 框架是 WebX、控制层用了 EJB、持久层是 iBATIS，另外为了缓解数据库的压力，商品查询和店铺查询放在搜索引擎上面。这个架构图是不是好看了一点了，亲？　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　这帮 Sun 的工程师开发完淘宝的网站之后，又做了一个很牛的网站，叫“支付宝”。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　其实在任何时候，开发语言本身都不是系统的瓶颈，业务带来的压力更多的是压到了数据和存储上。上面一篇也说到，MySQL 撑不住了之后换 Oracle，Oracle 的存储一开始在本机上，后来在 NAS 上，NAS 撑不住了用 EMC 的 SAN 存储，再然后 Oracle 的 RAC 撑不住了，数据的存储方面就不得不考虑使用小型机了。在 2004 年的夏天，DBA 七公、测试工程师郭芙和架构师行癫，踏上了去北京测试小型机的道路。他们带着小型机回来的时候，我们像欢迎领袖一样的欢迎他们，因为那个是我们最&amp;#20540;钱的设备了，价&amp;#26684;表上的数字吓死人。小型机买回来之后我们争相合影，然后
 Oracle 就跑在了小型机上，存储方面从 EMC 低端 cx 存储到 Sun oem hds 高端存储，再到 EMC dmx 高端存储，一级一级的往上跳。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　到现在为止，我们已经用上了 IBM 的小型机、Oracle 的数据库、EMC 的存储，这些东西都是很贵的，那些年可以说是花钱如流水啊。有人说过“钱能解决的问题，就不是问题”，但随着淘宝网的发展，在不久以后，钱已经解决不了我们的问题了。花钱买豪华的配置，也许能支持 1 亿 PV 的网站，但淘宝网的发展实在是太快了，到了 10 亿怎么办？到了百亿怎么办？在N年以后，我们不得不创造技术，解决这些只有世界顶尖的网站才会遇到的问题。后来我们在开源软件的基础上进行自主研发，一步一步的把 IOE（IBM 小型机、Oracle、EMC
 存储）这几个“神器”都去掉了。这就如同在《西游记》里面，妖怪们拿到神仙的兵器会非常厉害，连猴子都能够打败，但最牛的神仙是不用这些神器的，他们挥一挥衣袖、翻一下手掌就威力无比。去 IOE 这一部分会在最后一个章节里面讲，这里先埋个千里伏笔。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　欲知后事如何，且听下回分解。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　&lt;a name=&quot;p5&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;&lt;/a&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51)&quot;&gt;&lt;strong&gt;淘宝技术发展（Java时代：坚若磐石）&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　已经有读者在迫不及待的问怎么去掉了 IOE，别急，在去掉 IOE 之前还有很长的路要走。行癫他们买回来小型机之后，我们用上了 Oracle，七公带着一帮 DBA 在优化 SQL 和存储，行癫带着几个架构师在研究数据库的扩展性。Oracle 本身是一个封闭的系统，用 Oracle 怎么做扩展？用现在一个时髦的说法就是做“分库分表”。&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　我们知道一台 Oracle 的处理能力是有上限的，它的连接池有数量限制，查询速度跟容量成反比。简单的说，在数据量上亿、查询量上亿的时候，就到它的极限了。要突破这种极限，最简单的方式就是多用几个 Oracle 数据库。但一个封闭的系统做扩展，不像分布式系统那样轻松。我们把用户的信息按照 ID 来放到两个数据库里面（DB1/DB2），把商品的信息跟着卖家放在两个对应的数据库里面，把商品类目等通用信息放在第三个库里面(DBcommon)。这么做的目的除了增加了数据库的容量之外，还有一个就是做容灾，万一一个数据库挂了，整个网站上还有一半的数据能操作。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　数据库这么分了之后，应用程序有麻烦了，如果我是一个买家，买的商品有 DB1 的也有 DB2 的，要查看“我已买到的宝贝”的时候，应用程序怎么办？必须到两个数据库里面分别查询出来对应的商品。要按时间排序怎么办？两个库里面“我已买到的宝贝”全部查出来在应用程序里面做合并。还有分页怎么处理？关键字查询怎么处理？这些东西交给程序员来做的话会很悲催，于是行癫在淘宝的第一个架构上的作品就来解决了这个问题，他写了一个数据库路由的框架 DBRoute，这个框架在淘宝的 Oracle 时代一直在使用。后来随着业务的发展，这种分库的第二个目的
 —— 容灾的效果就没有达到。像评价、投诉、举报、收藏、我的淘宝等很多地方，都必须同时连接 DB1 和 DB2，哪个库挂了都会导致整个网站挂掉。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　上一篇说过，采用 EJB 其实是和 Sun 的工程师妥协的结果，在他们走了之后，EJB 也逐渐被冷落了下来。在 05、06年的时候，Spring 大放异彩，正好利用 Spring 的反射（IoC）模式替代了 EJB 的工厂模式，给整个系统精简了很多代码。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　上一篇还说过，为了减少数据库的压力，提高搜索的效率，我们引入了搜索引擎。随着数据量的继续增长，到了 2005 年，商品数有 1663 万，PV 有 8931 万，注册会员有 1390 万，这给数据和存储带来的压力依然山大，数据量大，性能就慢。亲，还有什么办法能提升系统的性能？一定还有招数可以用，这就是缓存和 CDN（内容分发网络）。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　你可以想象，九千万的访问量，有多少是在商品详情页面？访问这个页面的时候，数据全都是只读的（全部从数据库里面读出来，不写入数据库），如果把这些读操作从数据库里面移到内存里，数据库将会多么的感激涕零。在那个时候我们的架构师多隆大神，找到了一个基于 Berkeley DB 的开源的缓存系统，把很多不太变动的只读信息放了进去。其实最初这个缓存系统还比较弱，我们并没有把整个商品详情都放在里面，一开始把卖家的信息放里面，然后把商品属性放里面，商品详情这个字段太大，放进去受不了。说到商品详情，这个字段比较恐怖，有人统计过，淘宝商品详情打印出来平均有
 5 米长，在系统里面其实放在哪里都不招人待见。笔者清楚的记得，我来淘宝之后担任项目经理做的第一个项目就是把商品详情从商品表里面给移出来。这个字段太大了，查询商品信息的时候很多都不需要查看详情，它跟商品的价&amp;#26684;、运费这些放在一个表里面，拖慢了整个表的查询速度。在 05 年的时候，我把商品详情放在数据库的另外一张表里面，再往后这个大字段被从数据库里面请了出来，这也让数据库再一次感激涕零。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　到现在为止，整个商品详情的页面都在缓存里面了，&amp;#30524;尖的读者可能会发现现在的商品详情不全是“只读”的信息了，这个页面上有个信息叫“浏览量”，这个数字每刷新一次页面就要“写入”数据库一次，这种高频度实时更新的数据能用缓存吗？如果不用缓存，一天几十亿的写入，数据库会怎么样？一定会挂掉。那怎么办？亲……先不回答你（下图不是广告，让你看看浏览量这个数据在哪里）&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;img src=&quot;http://pic003.cnblogs.com/2012/1/201204/2012040311503357.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　CDN 这个工作相对比较独立，跟别的系统一样，一开始我们也是采用的商用系统。后来随着流量的增加，商用的系统已经撑不住了，LVS 的创始人章文嵩博士带人搭建了淘宝自己的 CDN 网络。在本文的引言中我说过淘宝的 CDN 系统支撑了 800Gbps 以上的流量，作为对比我们可以看一下国内专业做 CDN 的上市公司 ChinaCache 的介绍 —— “ChinaCache……是中国第一的专业 CDN 服务提供商，向客户提供全方位网络内容快速分布解决方案。作为首家获信产部许可的 CDN 服务提供商，目前 ChinaCache
 在全国 50 多个大中城市拥有近 300 个节点，全网处理能力超过 500Gbps，其 CDN 网络覆盖中国电信、中国网通、中国移动、中国联通、中国铁通和中国教育科研网等各大运营商。” —— 这样你可以看得出淘宝在 CDN 上面的实力，这在全世界都是数一数二的。另外因为 CDN 需要大量的服务器，要消耗很多能源（消耗多少？在前两年我们算过一笔帐，淘宝上产生一个交易，消耗的电足以煮熟 4 个鸡蛋）。这两年章文嵩的团队又在研究低功耗的服务器，在绿色计算领域也做了很多开创性的工作。淘宝 CDN 的发展需要专门一个章节来讲，想先睹为快的可以看一下笔者&lt;a href=&quot;http://qing.weibo.com/1866752224/6f4460e033000jme.html&quot; target=&quot;_blank&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;对章文嵩的专访&lt;/a&gt;。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　回想起刚用缓存那段时间，笔者还是个小菜鸟，有一个经典的错误常常犯，就是数据库的内容更新的时候，忘记通知缓存系统，结果在测试的时候就发现我改过的数据怎么在页面上没变化呢。后来做了一些页面上的代码，修改 CSS 和 JS 的时候，用户本地缓存的信息没有更新，页面上也会乱掉，在论坛上被人说的时候，我告诉他用 Ctrl&amp;#43;F5 刷新页面，然后赶紧修改脚本文件的名称，重新发布页面。学会用 Ctrl&amp;#43;F5 的会员对我佩服的五体投地，我却惭愧的无地自容。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　有些技术的发展是顺其自然的，有些却是突如其来的。到 2007 年的时候，我们已经有几百台应用服务器了，这上面的 Java 应用服务器是 WebLogic，而 WebLogic 是非常贵的，比这些服务器本身都贵。有一段时间多隆研究了一下 JBoss，说我们换掉 WebLogic 吧，于是又省下了不少银两。那一年，老马举办了第一届的“网侠大会”，会上来的大侠中有一位是上文提到的章文嵩，还有一位曾经在 JBoss 团队工作，我们也把这位大侠留下了，这样我们用起 JBoss 更加有底气了。　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　这些杂七杂八的修改，我们对&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51)&quot;&gt;&lt;strong&gt;数据分库、放弃 EJB、引入 Spring、加入缓存、加入 CDN、采用开源的 JBoss&lt;/strong&gt;&lt;/span&gt;，看起来没有章法可循，其实都是围绕着提高容量、提高性能、节约成本来做的，由于这些不算大的版本变迁，我们姑且叫它2.1版吧，这个版本从构图上来看有
 3 只脚，是不是稳定了很多？&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　架构图如下：&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;img src=&quot;http://pic003.cnblogs.com/2012/1/201204/2012040311562659.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　&lt;a name=&quot;p6&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;&lt;/a&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(51,51,51)&quot;&gt;&lt;strong&gt;淘宝技术发展&lt;/strong&gt;&lt;/span&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　在讲淘宝文件系统TFS之前，先回顾一下上面几个版本。1.0版的PHP系统运行了将近一年的时间（2003.05~2004.01）；后来数据库变成Oracle之后（2004.01~2004.05，叫1.1版本吧），不到半年就把开发语言转换为Java系统了（2004.02~2005.03，叫2.0版本）；进行分库、加入缓存、CDN之后我们叫它2.1版本（2004.10~2007.01）。这中间有些时间的重合，因为很多架构的演化并没有明显的时间点，它是逐步进化而来的。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　在描述2.1版本的时候我写的副标题是“坚若磐石”，这个“坚若磐石”是因为这个版本终于稳定下来了，在这个版本的系统上，淘宝网运行了两年多的时间。这期间有很多优秀的人才加入，也开发了很多优秀的产品，例如支付宝认证系统、招财进宝项目、淘宝旅行、淘宝彩票、淘宝论坛等等。甚至在团购网站风起云涌之前，淘宝网在2006年就推出了团购的功能，只是淘宝网最初的团购功能是买家发起的，达到卖家指定的数量之后，享受比一口价更低的价&amp;#26684;，这个功能看起来是结合了淘宝一口价和荷兰拍的另一种交易模式，但不幸没有支撑下去。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　在这些产品和功能的最底层，其实还是商品的管理和交易的管理这两大功能。这两大功能在2.1版本里面都有很大的变化。商品的管理起初是要求卖家选择7天到期还是14天到期，到期之后就要下架，必须重新发布才能上架，上架之后就变成了新的商品信息（ID变过了）。另外如果这个期间内成交了，之后再有新货，必须发布一个新的商品信息。这么做有几个原因，一是参照拍卖商品的时间设置，要在某日期前结束挂牌；二是搜索引擎不知道同样的商品哪个排前面，那就把挂牌时间长的排前面，这样就必须在某个时间把老的商品下架掉，不然它老排在前面；第三是成交信息和商品ID关联，这个商品如果多次编辑还是同一个ID的话，成交记录里面的商品信息会变来变去；还有一个不为人知的原因，我们的存储有限，不能让所有的商品老存放在主库里面。这种处理方式简单粗暴，但还算是公平。不过这样很多需求都无法满足，例如同样的商品，我上一次销售的时候很多好评都没法在下一个商品上体现出来；再例如我买过的商品结束后只看到交易的信息，不知道卖家还有没有再卖了。后来基于这些需求，我们在2006年下半年把商品和交易拆开。一个商家的一种商品有个唯一的ID，上下架都是同一个商品。那么如果卖家改价&amp;#26684;、库存什么的话，已成交的信息怎么处理？那就在买家每交易一次的时候，都记录下商品的快照信息，有多少次交易就有多少个快照。这样买卖双方比较爽了，给系统带来了什么？存储的成本大幅度上升了！&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　存储的成本高到什么程度呢？数据库方面提到过用了IOE，一套下来就是千万级别的，那几套下来就是⋯⋯。另外淘宝网还有很多文件需要存储，我们有哪些文件呢？最主要的就是图片、商品描述、交易快照，一个商品要包含几张图片和一长串的描述信息，而每一张图片都要生成几张规&amp;#26684;不同的缩略图。在2010年，淘宝网的后端系统上保存着286亿个图片文件。图片在交易系统中非常重要，俗话说“一张好图胜千言”、“无图无真相”，淘宝网的商品照片，尤其是热门商品，图片的访问流量是非常大的。淘宝网整体流量中，图片的访问流量要占到90%以上。且这些图片平均大小为17.45KB，小于8K的图片占整体图片数量61%，占整体系统容量的11%。这么多的图片数据、这么大的访问流量，给淘宝网的系统带来了巨大的挑战。众所周知，对于大多数系统来说，最头疼的就是大规模的小文件存储与读取，因为磁头需要频繁的寻道和换道，因此在读取上容易带来较长的延时。在大量高并发访问量的情况下，简直就是系统的噩梦。我们该怎么办？&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　同样的套路，在某个规模以下，采用现有的商业解决方案，达到某种规模之后，商业的解决方案无法满足，只有自己创造解决方案了。对于淘宝的图片存储来说，转折点在2007年。这之前，一直采用的商用存储系统，应用NetApp公司的文件存储系统。随着淘宝网的图片文件数量以每年2倍(即原来3倍)的速度增长，淘宝网后端NetApp公司的存储系统也从低端到高端不断迁移，直至2006年，即使是NetApp公司最高端的产品也不能满足淘宝网存储的要求。从2006年开始，淘宝网决定自己开发一套针对海量小文件存储的文件系统，用于解决自身图片存储的难题。这标志着淘宝网从使用技术到了创造技术的阶段。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　2007年之前的图片存储架构如下图：&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;&lt;img src=&quot;http://pic001.cnblogs.com/images/2012/1/2012042521361474.png&quot; alt=&quot;&quot; width=&quot;630&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　章文嵩博士总结了几点商用存储系统的局限和不足:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　首先是商用的存储系统没有对小文件存储和读取的环境进行有针对性的优化；其次，文件数量大，网络存储设备无法支撑；另外，整个系统所连接的服务器也越来越多，网络连接数已经到达了网络存储设备的极限。此外，商用存储系统扩容成本高，10T的存储容量需要几百万，而且存在单点故障，容灾和安全性无法得到很好的保证。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　&lt;/span&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;谈到在商用系统和自主研发之间的经济效益对比，章文嵩博士列举了以下几点经验：&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　1. 商用软件很难满足大规模系统的应用需求，无论存储还是CDN还是负载均衡，因为在厂商实验室端，很难实现如此大的数据规模测试。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　&lt;/span&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;2.
 研发过程中，将开源和自主开发相结合，会有更好的可控性，系统出问题了，完全可以从底层解决问题，系统扩展性也更高。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;img src=&quot;http://pic001.cnblogs.com/images/2012/1/2012042521381649.png&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　3. 在一定规模效应基础上，研发的投入都是&amp;#20540;得的。上图是一个自主研发和购买商用系统的投入产出比对比，实际上，在上图的交叉点左边，购买商用系统都是更加实际和经济性更好的选择，只有在规模超过交叉点的情况下，自主研发才能收到较好的经济效果。实际上，规模化达到如此程度的公司其实并不多，不过淘宝网已经远远超过了交叉点。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　4. 自主研发的系统可在软件和硬件多个层次不断的优化。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　历史总是惊人的巧合，在我们准备研发文件存储系统的时候，Google走在了前面，2007年他们公布了GFS（ Google File System ）的设计论文，这给我们带来了很多借鉴的思路。随后我们开发出了适合淘宝使用的图片存储系统TFS（Taobao
 File System）。3年之后，我们发现历史的巧合比我们想象中还要神奇，几乎跟我们同时，中国的另外一家互联网公司也开发了他们的文件存储系统，甚至取的名字都一样——TFS，太神奇了！（猜猜是哪家？）&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　2007年6月，TFS正式上线运营。在生产环境中应用的集群规模达到了200台PC Server(146G*6 SAS 15K Raid5)，文件数量达到上亿级别；系统部署存储容量：140TB；实际使用存储容量：
 50TB；单台支持随机IOPS200&amp;#43;，流量3MBps。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　要讲TFS的系统架构，首先要描述清楚业务需求，淘宝对图片存储的需求大概可以描述如下：&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　&lt;/span&gt;&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;文件比较小；并发量高；读操作远大于写操作；访问随机；没有文件修改的操作；要求存储成本低；能容灾能备份。应对这种需求，显然要用分布式存储系统；由于文件大小比较统一，可以采用专有文件系统；并发量高，读写随机性强，需要更少的IO操作；考虑到成本和备份，需要用廉价的存储设备；考虑到容灾，需要能平滑扩容。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　参照GFS并做了适度的优化之后，TFS1.0版的架构图如下：&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35); text-align:center&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;&lt;img src=&quot;http://pic001.cnblogs.com/images/2012/1/2012042521422296.jpg&quot; alt=&quot;&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:verdana,Arial,Helvetica; font-size:12px; color:rgb(35,35,35); border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; border-style:initial; border-color:initial; border-top-style:none; border-right-style:none; border-bottom-style:none; border-left-style:none; border-width:initial; border-color:initial&quot;&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　从上面架构图上看：集群由一对Name Server和多台Data Server构成，Name Server的两台服务器互为双机，就是集群文件系统中管理节点的概念。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　在这个架构中：&lt;/span&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　• 每个Data Server运行在一台普通的Linux主机上&lt;/span&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　• 以block文件的形式存放数据文件(一般64M一个block)&lt;/span&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　• block存多份保证数据安全&lt;/span&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　• 利用ext3文件系统存放数据文件&lt;/span&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　• 磁盘raid5做数据冗余&lt;/span&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; line-height:10px&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　• 文件名内置元数据信息，用户自己保存TFS文件名与实际文件的对照关系–使得元数据量特别小。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　淘宝TFS文件系统在核心设计上最大的取巧的地方就在，传统的集群系统里面元数据只有1份，通常由管理节点来管理，因而很容易成为瓶颈。而对于淘宝网的用户来说，图片文件究竟用什么名字来保存实际上用户并不关心，因此TFS在设计规划上考虑在图片的保存文件名上暗藏了一些元数据信息，例如图片的大小、时间、访问频次等等信息，包括所在的逻辑块号。而在元数据上，实际上保存的信息很少，因此元数据结构非常简单。仅仅只需要一个fileID，能够准确定位文件在什么地方。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　由于大量的文件信息都隐藏在文件名中，整个系统完全抛弃了传统的目录树结构，因为目录树开销最大。拿掉后，整个集群的高可扩展性极大提高。实际上，这一设计理念和目前业界的“对象存储”较为类&amp;#20284;，淘宝网TFS文件系统已经更新到1.3版本，在生产系统的性能已经得到验证，且不断得到了完善和优化，淘宝网目前在对象存储领域的研究已经走在前列。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　在TFS上线之前，淘宝网每个商品只允许上传一张图片，大小限定在120K之内，在商品详情里面的图片必须使用外站的服务。那时侯发布一件商品确实非常麻烦，笔者曾经想卖一台二手电脑，先把照片上传到Google相册，在发布到淘宝网之后发现Google相册被墙了，我的图片别人看不到，当时郁闷的不行。TFS上线后，商品展示图片开放到5张，商品描述里面的图片也可以使用淘宝的图片服务，到现在为止，淘宝网给每个用户提供了1G的图片空间，这下大家都满足了。技术和业务就是这么互相用力的推动着，业务满足不了的时候，技术必须创新，技术创新之后，业务有了更大的发展空间。&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px&quot;&gt;　　1.3版本的架构见阿里味（阿里巴巴内网）⋯⋯&lt;/span&gt;　　&lt;/p&gt;
&lt;p style=&quot;margin-top:5px; margin-right:auto; margin-bottom:5px; margin-left:auto; padding-top:0px; padding-bottom:0px; font-family:verdana,Arial,Helvetica; font-size:14px; color:rgb(35,35,35)&quot;&gt;
　　作者的另一篇：&lt;a href=&quot;http://kb.cnblogs.com/page/132752/&quot; target=&quot;_blank&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; color:rgb(26,100,162); text-decoration:none&quot;&gt;从P1到P7——我在淘宝这7年&lt;/a&gt;&lt;/p&gt;
&lt;br&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-5-10 16:36:26 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7554533&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：411 评论：0 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7554533#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638053023/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7554533&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Thu, 10 May 2012 16:36:26 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7554533</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7554533</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/638053023/1166164</fs:itemid></item><item><title>[转][转]Instagram 架构分析笔记</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7483919</link><description>&lt;p&gt;&lt;span style=&quot;color:rgb(191,191,191); font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; line-height:14px; word-spacing:1px&quot;&gt;作者:&amp;nbsp;&lt;strong&gt;&lt;a href=&quot;http://www.dbanotes.net/&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(191,191,191)&quot;&gt;Fenng&lt;/a&gt;&lt;/strong&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:rgb(191,191,191); font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; line-height:14px; word-spacing:1px&quot;&gt;来源：&lt;a href=&quot;http://www.dbanotes.net/arch/instagram.html&quot;&gt;http://www.dbanotes.net/arch/instagram.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:rgb(110,110,110); font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:14px; line-height:25px; word-spacing:1px&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
Updated: 2012 年4月10日凌晨消息，Instagram 被 Facebook 以10亿美金收购。团队规模：13 人。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;a href=&quot;http://instagr.am/&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;Instagram&lt;/a&gt;&amp;nbsp;团队上个月才迎来第 7 名员工，是的，7个人的团队。作为 iPhone 上最火爆的图片类工具，instagram 用户数量已经超过 1400 万，图片数量超过 1.5 亿张。不得不说，这真他妈是个业界奇迹。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
几天前，只有三个人的 Instagram 工程师团队发布了一篇文章：&lt;a href=&quot;http://instagram-engineering.tumblr.com/post/13649370142/what-powers-instagram-hundreds-of-instances-dozens-of&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;What
 Powers Instagram: Hundreds of Instances, Dozens of Technologies&lt;/a&gt;，披露了 Instagram 架构的一些信息，足够勾起大多数人的好奇心。读罢做点笔记，各种线索还是有一定参考价&amp;#20540;的。能打开原文的建议直接读原文。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;img alt=&quot;Instragram.png&quot; src=&quot;http://www.dbanotes.net/Images/302x84xInstragram.png.pagespeed.ic.OyMTN_wvFd.png&quot; width=&quot;302&quot; height=&quot;84&quot; class=&quot;mt-image-none&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial&quot;&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
Instagram 开发团队&lt;strong&gt;奉行&lt;/strong&gt;的三个核心原则：&lt;/p&gt;
&lt;ul style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:14px; word-spacing:0.1em; list-style-type:disc; list-style-position:initial&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; word-spacing:0.1em&quot;&gt;
Keep it very simple (极简主义)&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; word-spacing:0.1em&quot;&gt;
Don't re-invent the wheel (不重复发明轮子)&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; word-spacing:0.1em&quot;&gt;
Go with proven and solid technologies when you can(能用就用靠谱的技术)&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;strong&gt;&lt;acronym title=&quot;Operating System&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;OS&lt;/acronym&gt;/主机&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
操作系统的选择，在Amazon EC2上跑 Ubuntu Linux 11.04 (Natty Narwhal) ，这个版本经过验证在 EC2 上够稳定。因为只有三名工程师，只有三名工程师，所以自己部署机器到&amp;nbsp;&lt;acronym title=&quot;Internet Data Center&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;IDC&lt;/acronym&gt;&amp;nbsp;是不靠谱的事情。幸好有亚马逊。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;strong&gt;负载均衡&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
此前曾用过两台 Nginx 做&amp;nbsp;&lt;acronym title=&quot;Domain Name System&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;DNS&lt;/acronym&gt;&amp;nbsp;轮询承载前端请求，这样做会有副作用，现在已经迁移到Amazon的ELB(Elastic
 Load Balancer)，起了三个 Nginx 实例，在 ELB 层停掉了&amp;nbsp;&lt;acronym title=&quot;Secure Sockets Layer&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;SSL&lt;/acronym&gt;&amp;nbsp;,
 以缓解&amp;nbsp;&lt;acronym title=&quot;Central Processing Unit&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;CPU&lt;/acronym&gt;&amp;nbsp;压力。DNS
 服务使用 Amazon Route53 服务。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;strong&gt;应用服务器&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
启用了 25 个 Django 实例，运行在 High-&lt;acronym title=&quot;Central Processing Unit&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;CPU&lt;/acronym&gt;&amp;nbsp;Extra-Large
 类型的服务器实例上，之所以用 High-&lt;acronym title=&quot;Central Processing Unit&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;CPU&lt;/acronym&gt;&amp;nbsp;Extra-Large
 实例是因为应用请求是&amp;nbsp;&lt;acronym title=&quot;Central Processing Unit&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;CPU&lt;/acronym&gt;&amp;nbsp;密集型而非&amp;nbsp;&lt;acronym title=&quot;Input Output&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;IO&lt;/acronym&gt;&amp;nbsp;密集型。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
使用&amp;nbsp;&lt;a href=&quot;http://gunicorn.org/&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;Gunicorn&lt;/a&gt;&amp;nbsp;作为 WSGI 服务器。过去曾用过 Apache 下的 mod_wsgi 模块，不过发现 Gunicorn 更容易配置并且节省&amp;nbsp;&lt;acronym title=&quot;Central Processing Unit&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;CPU&lt;/acronym&gt;&amp;nbsp;资源。使用&amp;nbsp;&lt;a href=&quot;http://fabric.readthedocs.org/en/1.3.3/index.html&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;Fabric&lt;/a&gt;&amp;nbsp;加速部署。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;strong&gt;数据存储&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
用户信息、图片元数据、标签等大部分数据存储在 PostgreSQL 中。主要的 Shard 数据库集群有 12个节点。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
实践中发现 Amazon 的网络磁盘系统单位时间内寻道能力不行，所以有必要将数据尽量放到内存中。创建了软&amp;nbsp;&lt;acronym title=&quot;Redundant Array of Independent (or Inexpensive) Disks&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;RAID&lt;/acronym&gt;&amp;nbsp;以提升&amp;nbsp;&lt;acronym title=&quot;Input Output&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;IO&lt;/acronym&gt;&amp;nbsp;能力，使用的&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Mdadm&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;Mdadm&lt;/a&gt;&amp;nbsp;工具进行&amp;nbsp;&lt;acronym title=&quot;Redundant Array of Independent (or Inexpensive) Disks&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;RAID&lt;/acronym&gt;&amp;nbsp;管理。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
管理内存中的数据，&lt;a href=&quot;http://hoytech.com/vmtouch/vmtouch.c&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;vmtouch&lt;/a&gt;&amp;nbsp;这个小工具&amp;#20540;得推荐。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
PostgreSQL 设置为 Master-Replica 方式，流复制模式。利用 EBS 的快照进行数据库备份。使用 XFS 文件系统，以便和快照服务充分配合。 使用&amp;nbsp;&lt;a href=&quot;https://github.com/greg2ndQuadrant/repmgr&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;repmgr&lt;/a&gt;&amp;nbsp;这个小工具做
 PostgreSQL 复制管理器器。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
连接池管理，用了&amp;nbsp;&lt;a href=&quot;http://pgfoundry.org/projects/pgbouncer/&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;Pgbouncer&lt;/a&gt;。&lt;a href=&quot;http://thebuild.com/blog/&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;Christophe
 Pettus&lt;/a&gt;&amp;nbsp;的文章包含了不少&amp;nbsp;&lt;a href=&quot;http://thebuild.com/blog/&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;PostgreSQL&lt;/a&gt;&amp;nbsp;数据库的信息。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
TB 级别的海量图片存储在 Amazon S3 上，CDN 采用的也是 Amazon 的服务，CloudFront。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
Instagram 也是 Redis 的重度用户，Feed 以及 Session 信息都用 Redis 处理，Redis 也是以 Master-Replica 方式部署。在 Replica 节点上进行数据备份。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
使用了 Apache Solr 承担 Geo-search&amp;nbsp;&lt;acronym title=&quot;Application Programming Interface&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;API&lt;/acronym&gt;&amp;nbsp;的工作，Solr
 简单的 JSON 接口也不错。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
缓存使用了 6 个 Memcached 实例，库使用 pylibmc 和 libmemcached。亚马逊也提供缓存服务－Elastic Cache service ，Instagram 也有尝试，不过不便宜。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;strong&gt;任务队列/发布通知&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
队列服务使用&amp;nbsp;&lt;a href=&quot;http://gearman.org/&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;Gearman&lt;/a&gt;&amp;nbsp;，通知系统则使用&lt;a href=&quot;https://github.com/samuraisam/pyapns&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;&amp;nbsp;pyapns&lt;/a&gt;&amp;nbsp;来实现。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;strong&gt;监控&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
前面提及的服务器实例数量加起来，的确有100多个，有效的监控是相当有必要的。使用 Munin 作为主要监控工具 , 也写了不少定制插件，外部监控用&amp;nbsp;&lt;a href=&quot;http://pingdom.com/&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;Pingdom&lt;/a&gt;&amp;nbsp;的服务。通知服务使用&lt;a href=&quot;http://www.pagerduty.com/&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;PagerDuty&lt;/a&gt;。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
对于 Python 的错误报告，使用 Disqus 团队开源的&amp;nbsp;&lt;a href=&quot;http://pypi.python.org/pypi/django-sentry&quot; style=&quot;text-decoration:none; outline-style:none; outline-width:initial; outline-color:initial; color:rgb(0,130,255)&quot;&gt;Sentry&lt;/a&gt;&amp;nbsp;来处理。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
&lt;strong&gt;几个感想&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
0）轻装上阵说起来容易，做起来非常难。这也是 Instagram 团队目前最令人着迷的地方；&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
1）Python 社区已经足够成熟，各个环节上都已经有不错的解决方案了。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
2）如果要问我最大的一个感慨，我要说：&lt;strong&gt;Amazon 真是一家伟大的公司，甚至比 Google 还伟大&lt;/strong&gt;。&lt;/p&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0px; padding-top:4px; padding-bottom:6px; word-spacing:0.1em&quot;&gt;
--&lt;acronym title=&quot;End of File&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:1px; border-left-width:0px; border-style:initial; border-color:initial; border-bottom-style:dotted; border-bottom-color:rgb(187,208,249)&quot;&gt;EOF&lt;/acronym&gt;--&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;/p&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-4-21 11:47:14 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7483919&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：551 评论：1 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7483919#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638053022/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7483919&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Sat, 21 Apr 2012 11:47:14 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7483919</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7483919</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/638053022/1166164</fs:itemid></item><item><title>[转][转]Redis消息通知系统的实现</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7365181</link><description>&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;作者：老王&lt;br&gt;
链接：http://huoding.com/2012/02/29/146&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:rgb(55,55,55); font-family:'Helvetica Neue',Helvetica,Arial,sans-serif; font-size:15px; font-weight:300; line-height:24px&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
最近忙着用Redis实现一个消息通知系统，今天大概总结了一下技术细节，其中演示代码如果没有特殊说明，使用的都是&lt;a href=&quot;https://github.com/nicolasff/phpredis&quot; target=&quot;_blank&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; color:rgb(25,130,209); text-decoration:none&quot;&gt;PhpRedis&lt;/a&gt;扩展来实现的。&lt;/p&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
&lt;span id=&quot;more-146&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; font-weight:bold; margin-top:0px; margin-right:0px; margin-bottom:0.8125em; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; clear:both; color:rgb(0,0,0)&quot;&gt;
内存&lt;/h2&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
比如要推送一条全局消息，如果真的给所有用户都推送一遍的话，那么会占用很大的内存，实际上不管粘性有多高的产品，活跃用户同全部用户比起来，都会小很多，所以如果只处理登录用户的话，那么至少在内存消耗上是相当划算的，至于未登录用户，可以推迟到用户下次登录时再处理，如果用户一直不登录，就一了百了了。&lt;/p&gt;
&lt;h2 style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; font-weight:bold; margin-top:0px; margin-right:0px; margin-bottom:0.8125em; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; clear:both; color:rgb(0,0,0)&quot;&gt;
队列&lt;/h2&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
当大量用户同时登录的时候，如果全部都即时处理，那么很容易就崩溃了，此时可以使用一个队列来保存待处理的登录用户，如此一来顶多是反应慢点，但不会崩溃。&lt;/p&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
Redis的&lt;a href=&quot;http://www.redis.io/commands/#list&quot; target=&quot;_blank&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; color:rgb(25,130,209); text-decoration:none&quot;&gt;LIST&lt;/a&gt;数据类型可以很自然的创建一个队列，代码如下：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;&amp;lt;?php

$redis = new Redis;
$redis-&amp;gt;connect('/tmp/redis.sock');

$redis-&amp;gt;lPush('usr', &amp;lt;USRID&amp;gt;);

while ($usr = $redis-&amp;gt;rPop('usr')) {
    var_dump($usr);
}

?&amp;gt;&lt;/pre&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
出于类&amp;#20284;的原因，我们还需要一个队列来保存待处理的消息。当然也可以使用LIST来实现，但LIST只能按照插入的先后顺序实现类&amp;#20284;FIFO或LIFO形式的队列，然而消息实际上是有优先级的：比如说个人消息优先级高，全局消息优先级低。此时可以使用&lt;a href=&quot;http://www.redis.io/commands/#sorted_set&quot; target=&quot;_blank&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; color:rgb(25,130,209); text-decoration:none&quot;&gt;ZSET&lt;/a&gt;来实现，它里面分数的概念很自然的实现了优先级。&lt;/p&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
不过ZSET没有原生的POP操作，所以我们需要模拟实现，代码如下：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;&amp;lt;?php

class RedisClient extends Redis
{
    const POSITION_FIRST = 0;
    const POSITION_LAST = -1;

    public function zPop($zset)
    {
        return $this-&amp;gt;zsetPop($zset, self::POSITION_FIRST);
    }

    public function zRevPop($zset)
    {
        return $this-&amp;gt;zsetPop($zset, self::POSITION_LAST);
    }

    private function zsetPop($zset, $position)
    {
        $this-&amp;gt;watch($zset);

        $element = $this-&amp;gt;zRange($zset, $position, $position);

        if (!isset($element[0])) {
            return false;
        }

        if ($this-&amp;gt;multi()-&amp;gt;zRem($zset, $element[0])-&amp;gt;exec()) {
            return $element[0];
        }

        return $this-&amp;gt;zsetPop($zset, $position);
    }
}

?&amp;gt;&lt;/pre&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
模拟实现了POP操作后，我们就可以使用ZSET实现队列了，代码如下：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;&amp;lt;?php

$redis = new RedisClient;
$redis-&amp;gt;connect('/tmp/redis.sock');

$redis-&amp;gt;zAdd('msg', &amp;lt;PRIORITY&amp;gt;, &amp;lt;MSGID&amp;gt;);

while ($msg = $redis-&amp;gt;zRevPop('msg')) {
    var_dump($msg);
}

?&amp;gt;&lt;/pre&gt;
&lt;h2 style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; font-weight:bold; margin-top:0px; margin-right:0px; margin-bottom:0.8125em; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; clear:both; color:rgb(0,0,0)&quot;&gt;
推拉&lt;/h2&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
以前微博架构中推拉选择的问题已经被大家讨论过很多次了。实际上消息通知系统和微博差不多，也存在推拉选择的问题，同样答案也是类&amp;#20284;的，那就是应该推拉结合。具体点说：在登陆用户获取消息的时候，就是一个拉消息的过程；在把消息发送给登陆用户的时候，就是一个推消息的过程。&lt;/p&gt;
&lt;h2 style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; font-weight:bold; margin-top:0px; margin-right:0px; margin-bottom:0.8125em; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; clear:both; color:rgb(0,0,0)&quot;&gt;
速度&lt;/h2&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
假设要推送一百万条消息的话，那么最直白的实现就是不断的插入，代码如下：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;&amp;lt;?php

for ($msgid = 1; $msgid &amp;lt;= 1000000; $msgid&amp;#43;&amp;#43;) {
    $redis-&amp;gt;sAdd('usr:&amp;lt;USRID&amp;gt;:msg', $msgid);
}

?&amp;gt;&lt;/pre&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
Redis的速度是很快的，但是借助&lt;a href=&quot;http://redis.io/topics/pipelining&quot; target=&quot;_blank&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; color:rgb(25,130,209); text-decoration:none&quot;&gt;PIPELINE&lt;/a&gt;，会更快，代码如下：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;&amp;lt;?php

for ($i = 1; $i &amp;lt;= 100; $i&amp;#43;&amp;#43;) {
    $redis-&amp;gt;multi(Redis::PIPELINE);
    for ($j = 1; $j &amp;lt;= 10000; $j&amp;#43;&amp;#43;) {
        $msgid = ($i - 1) * 10000 &amp;#43; $j;
        $redis-&amp;gt;sAdd('usr:&amp;lt;USRID&amp;gt;:msg', $msgid);
    }
    $redis-&amp;gt;exec();
}

?&amp;gt;&lt;/pre&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
说明：所谓PIPELINE，就是省略了无谓的折返跑，把命令打包给服务端统一处理。&lt;/p&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
前后两段代码在我的测试里，使用PIPELINE的速度大概是不使用PIPELINE的十倍。&lt;/p&gt;
&lt;h2 style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; font-weight:bold; margin-top:0px; margin-right:0px; margin-bottom:0.8125em; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; clear:both; color:rgb(0,0,0)&quot;&gt;
查询&lt;/h2&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
我们用Redis命令行来演示一下用户是如何查询消息的。&lt;/p&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
先插入三条消息，其&amp;lt;MSGID&amp;gt;分别是1，2，3：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;redis&amp;gt; HMSET msg:1 title title1 content content1
redis&amp;gt; HMSET msg:2 title title2 content content2
redis&amp;gt; HMSET msg:3 title title3 content content3&lt;/pre&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
再把这三条消息发送给某个用户，其&amp;lt;USRID&amp;gt;是123：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;redis&amp;gt; SADD usr:123:msg 1
redis&amp;gt; SADD usr:123:msg 2
redis&amp;gt; SADD usr:123:msg 3&lt;/pre&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
此时如果简单查询用户有哪些消息的话，无疑只能查到一些&amp;lt;MSGID&amp;gt;：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;redis&amp;gt; SMEMBERS usr:123:msg
1) &amp;quot;1&amp;quot;
2) &amp;quot;2&amp;quot;
3) &amp;quot;3&amp;quot;&lt;/pre&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
如果还需要用程序根据&amp;lt;MSGID&amp;gt;再来一次查询无疑有点低效，好在Redis内置的&lt;a href=&quot;http://www.redis.io/commands/sort&quot; target=&quot;_blank&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; color:rgb(25,130,209); text-decoration:none&quot;&gt;SORT&lt;/a&gt;命令可以达到事半功倍的效果，实际上它类&amp;#20284;于SQL中的JOIN：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;redis&amp;gt; SORT usr:123:msg GET msg:*-&amp;gt;title
1) &amp;quot;title1&amp;quot;
2) &amp;quot;title2&amp;quot;
3) &amp;quot;title3&amp;quot;
redis&amp;gt; SORT usr:123:msg GET msg:*-&amp;gt;content
1) &amp;quot;content1&amp;quot;
2) &amp;quot;content2&amp;quot;
3) &amp;quot;content3&amp;quot;&lt;/pre&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
SORT的缺点是它只能GET出字符串类型的数据，如果你想要多个数据，就要多次GET：&lt;/p&gt;
&lt;pre style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:13px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0.75em; padding-right:1.625em; padding-bottom:0.75em; padding-left:1.625em; vertical-align:baseline; background-color:rgb(244,244,244); font:normal normal normal 13px/normal 'Courier 10 Pitch',Courier,monospace; line-height:1.5; overflow-x:auto; overflow-y:auto&quot;&gt;redis&amp;gt; SORT usr:123:msg GET msg:*-&amp;gt;title GET msg:*-&amp;gt;content
1) &amp;quot;title1&amp;quot;
2) &amp;quot;content1&amp;quot;
3) &amp;quot;title2&amp;quot;
4) &amp;quot;content2&amp;quot;
5) &amp;quot;title3&amp;quot;
6) &amp;quot;content3&amp;quot;&lt;/pre&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
很多情况下这显得不够灵活，好在我们可以采用其他一些方法平衡一下利弊，比如说新加一个字段，冗余保存完整消息的序列化，接着只GET这个字段就OK了。&lt;/p&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
实际暴露查询接口的时候，不会使用PHP等程序来封装，因为那会成倍降低RPS，推荐使用&lt;a href=&quot;http://webd.is/&quot; target=&quot;_blank&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; color:rgb(25,130,209); text-decoration:none&quot;&gt;Webdis&lt;/a&gt;，它是一个Redis的Web代理，效率没得说。&lt;/p&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
…&lt;/p&gt;
&lt;p style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-bottom:1.625em; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-bottom:0px; vertical-align:baseline&quot;&gt;
最近&lt;a href=&quot;https://www.tumblr.com/&quot; target=&quot;_blank&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; color:rgb(25,130,209); text-decoration:none&quot;&gt;Tumblr&lt;/a&gt;发表了一篇类&amp;#20284;的文章：&lt;a href=&quot;http://engineering.tumblr.com/post/7819252942/staircar-redis-powered-notifications&quot; target=&quot;_blank&quot; style=&quot;border-top-width:0px; border-right-width:0px; border-bottom-width:0px; border-left-width:0px; border-style:initial; border-color:initial; font-family:inherit; font-size:15px; font-style:inherit; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; outline-width:0px; outline-style:initial; outline-color:initial; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; vertical-align:baseline; color:rgb(25,130,209); text-decoration:none&quot;&gt;Staircar:
 Redis-powered notifications&lt;/a&gt;，介绍了他们使用Redis实现消息通知系统的一些情况，有兴趣的不妨一起看看。&lt;/p&gt;
&lt;br&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-3-17 21:49:01 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7365181&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：678 评论：0 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7365181#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638053021/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7365181&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Sat, 17 Mar 2012 21:49:01 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7365181</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7365181</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/638053021/1166164</fs:itemid></item><item><title>[转][转]Tumblr架构 – 页面浏览量150亿/月并且比Twitter更难拓展</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7365044</link><description>&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;作者：longhao&lt;br&gt;
来源：http://www.longtask.com/blog/?p=736&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:rgb(78,78,78); font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;
 &amp;nbsp; 注：一些内容不熟悉，所以没有翻译。原文地址在&lt;a href=&quot;http://highscalability.com/blog/2012/2/13/tumblr-architecture-15-billion-page-views-a-month-and-harder.html&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; color:rgb(0,113,187); outline-style:none; outline-width:initial; outline-color:initial; text-decoration:none&quot;&gt;这里&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;
 &amp;nbsp;&amp;nbsp;&lt;a href=&quot;http://tumblr.com/&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; color:rgb(0,113,187); outline-style:none; outline-width:initial; outline-color:initial; text-decoration:none&quot;&gt;Tumblr&lt;/a&gt;每个月增长30%
 , 一天5亿网页浏览，40K/sec , 每天3TB的数据存储在1000&amp;#43;的服务器上。最开始只有4名工程师来处理所有事情，当有20多个工程师的时候，才有实力出一些有趣的解决方案。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;
 &amp;nbsp; Tumblr最开始是典型的大型LAMP应用，现在的分布式服务模型使用了Scala, HBase, Redis,&lt;a href=&quot;http://incubator.apache.org/kafka/design.html&quot; style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; color:rgb(0,113,187); outline-style:none; outline-width:initial; outline-color:initial; text-decoration:none&quot;&gt;Kafka&lt;/a&gt;&amp;nbsp;,
 Finagle等，现在在处理PHP应用的问题，开始走向面向服务的设计。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;
 &amp;nbsp; 分布式系统工程师 Blank Matheny讲述Tumblr的架构&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;h3 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:22px; line-height:24px; letter-spacing:-0.02em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;现状&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;每天5亿PV&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;~20
 工程师&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;平均每秒4W请求&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;每天1&amp;#43;
 TB 数据写入到Hadoop集群&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;每天更多TB的数据写入到
 MySQL/HBase/Redis/Memcache&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;每月增长超过30%&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;~1000
 硬件服务器&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;每个工程师每天分摊的PV将近10亿&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;每天提交
 50GB . Follower列表更新每天产生2.7TB 的数据。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Dashboard
 每秒百万的读取和每秒5万的写入, 并且还在增长.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:28px; line-height:30px; letter-spacing:-0.03em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;软件&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;开发使用OS
 X , 服务器使用Linux (CentOS, Scientific)&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Apache&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;PHP,
 Scala, Ruby&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Redis,
 HBase, MySQL&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Varnish,
 HA-Proxy, nginx,&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Memcache,
 Gearman, Kafka,&amp;nbsp;Kestrel, Finagle&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Thrift,
 HTTP&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Func
 – a secure, scriptable remote control framework and API&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Git,
 Capistrano, Puppet, Jenkins&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:28px; line-height:30px; letter-spacing:-0.03em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;硬件&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;500
 web servers&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;200
 database servers (许多服务器是容灾的需要)&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;47
 pools&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;30
 shards&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;30
 memcache servers&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;22
 redis servers&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;15
 varnish servers&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;25
 haproxy nodes&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;8
 nginx&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;14
 job queue servers (kestrel &amp;#43; gearman)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:28px; line-height:30px; letter-spacing:-0.03em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;架构设计&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Tumblr
 相对其他社会网络有不同的使用模式&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;网状的分发结构，每天超过5000万的提交需要分发到用户的Follower
 , 很多用户都有数百个Follower&amp;nbsp;，百万Follower的用户也不是一两个。所以Tumblr的规模极具挑战性。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;由于存在图片和视频，让用户停留时间比较长。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;返回给用户的内容和用户的联系人有关，不是简单的数据流。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;需要做大量的数据分析（用户数量，用户平均活动范围，用户提交的高质量的内容等）&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Tumblr
 运行在托管服务器上 . 设计上需要考虑未来的地理分布。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Tumblr作为一个平台有2部分组成:
 公共Tumblr日志&amp;nbsp;和面板&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;/span&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0.8em; padding-top:0px; padding-bottom:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;/p&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;公共Tumblr日志是一个博客平台&amp;nbsp;.
 容易缓存&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;控制面板类&amp;#20284;&amp;nbsp;Twitter
 时间表 . 需要实时更新用户follower的内容.&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;cache不管用，尤其对活跃的用户&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;需要实时和一致，不应该显示陈旧数据，所以会有每天提交50GB，Follower列表更新需要2.7TB。（多媒体存储在S3上）&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;多数用户把Tumblr作为内容消费工具,
 70%浏览来自面板.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;面板的可用性非常好了，Tumblr日志因为遗留的架构问题导致可用性不好。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;h3 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:22px; line-height:24px; letter-spacing:-0.02em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;老的Tumblr&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Tumblr公司开始托管在Rackspace&amp;nbsp;，他们给每个自定义域blog一个A记录（域名管理方面的内容），当迁出Rackspace的时候需要迁移大量用户，2007年前，使用&amp;nbsp;HAProxy
 and Varnish来负责均衡。许多像这样的遗留问题&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;一个传统的
 LAMP 演进.&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;历史原因，每个工程师都用PHP。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;最开始阶段一台web服务器，一台数据库服务器，一台PHP应用服务器。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;To
 scale they started using memcache, then put in front-end caching, then HAProxy in front of the caches, then MySQL sharding. MySQL sharding has been hugely helpful.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;最开始使用memcache
 ，然后转到前端缓存，使用HAProxy&amp;nbsp;在缓存前，然后使用Mysql水平分区，Mysql水平分区非常有用。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;最开始中心化，过去的几年中采用了2台用C语言写的后端服务器来做2件事情：&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;生成ID
 和 Staircar&lt;/span&gt;&amp;nbsp;，使用Redis来处理面板通知&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;面板采用了&amp;nbsp;scatter-gather&amp;nbsp;的方式，当用户访问他们面板的时候采用事件驱动的方式，由于采用事件顺序，分片方案不是工作的很好。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:22px; line-height:24px; letter-spacing:-0.02em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;新的Tumblr&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;因招聘和开发速度的原因，转向JVM。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;目标是移除PHP的所有应用，采用服务的方式。所有应用是很薄的一层，通过访问服务来鉴权和呈现。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Scala
 and Finagle 的选择&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;内部人员很多回Ruby和PHP，所以Scala语言比较容易接受&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;span style=&quot;&quot;&gt;Finagle&amp;nbsp;是Scala写的，解决了大部分的分布式问题，同时它是免费的。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&amp;nbsp;Finagle
 提供了初始阶段所有想要的东西 (Thrift, ZooKeeper, etc).&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Finagle
 被 Foursquare和Twitter使用 . Meetup在使用Scala&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;喜欢Thrift的应用接口
 ， 主要是高性能方面。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;喜欢Netty,
 但是不喜欢Java , Scala是个不错选择&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;选择
 Finagle 可以通过更少的代码解决分布问题。&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;span style=&quot;&quot;&gt;Node.js不被选择是因为JVM平台更有优势，&lt;/span&gt;Node.js没有开发标准和好的开发策略，没有通过大型系统的代码验证。Scala&amp;nbsp;可以使用java代码，可拓展性好，5毫秒的响应速度，有许多大型java应用可以参考。&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;内部服务从基于C/libevent转向基于&amp;nbsp;Scala/Finagle&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;使用非关系型数据库HBase和Redis
 , &amp;nbsp;但是大半数据存储在Mysql集群，没有使用HBase替代MySQL。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;span style=&quot;&quot;&gt;HBase&amp;nbsp;被用来备份数十亿的短网址和历史数据分析，被用来解决高并发写的问题，例如：每秒百万写级别的面板重置。&lt;/span&gt;HBase&amp;nbsp;没有替代Mysql是因为项目经验少，不能打赌。&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;MySQL和shard(分片数据库）在时序数据上的问题是，一个分片总是热点块，并且由于在slave端的平行插入而导致读端的复制总是落后。&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Created
 a common services framework.&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Spent
 a lot of time upfront solving operations problem of how to manage a distributed system.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Built
 a kind of Rails scaffolding, but for services. A template is used to bootstrap services internally.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;All
 services look identical from an operations perspective. Checking statistics, monitoring, starting and stopping all work the same way for all services.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Tooling
 is put around the build process in SBT&amp;nbsp;(a Scala build tool) using plugins and helpers to take care of common activities like tagging things in git, publishing to the repository, etc. Most developers don’t have to get in the guts of the build system.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;前置层使用
 HAProxy. Varnish ， 40台机器.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;500
 台web服务器上跑着Apache和PHP应用.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;200台数据库服务器，部分服务器是容灾需要；成本考虑，硬件使用MTBF。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;6种后端服务支撑PHP应用。有一个小组专门来开发这种服务，每2,3周都会推出一种新的服务。包括：&amp;nbsp;Includes
 dashboard notifications, dashboard secondary index, URL shortener, and a memcache proxy to handle transparent sharding.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;MySQL足够了，所以没有用MongoDB.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;div style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;&lt;span style=&quot;&quot;&gt;Gearman
 , 一个工作队列系统。用来跑长时间运行的或者无需人工干预的工作。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Availability
 is measured in terms of reach. Can a user reach custom domains or the dashboard? Also in terms of error rate.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;历史最高需求已经被搞定。现在，如果一部分需求不能满足要求，我们会从用户角度和应用角度对错误的模型进行分析和系统的处理来达到成功的目的。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;最初使用了Finagle的Actor模型，后来去掉了。使用了twitter的utility
 library的Futures接口来处理异步的需求。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Scala鼓励不适用共享状态。Finagle&amp;nbsp;在twitter的产品中得到了很好的测试验证，在机器上无状态运行，保证了开发人员不用去担心线程和锁。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;22
 Redis servers. Each server has 8 – 32 instances so 100s of Redis instances are used in production.&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Used
 for backend storage for dashboard notifications.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;A
 notification is something &amp;nbsp;like a user liked your post. Notifications show up in a user’s dashboard to indicate actions other users have taken on their content.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;High
 write ratio made MySQL a poor fit. &amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Notifications
 are ephemeral so it wouldn’t be horrible if they were dropped, so Redis was an acceptable choice for this function.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Gave
 them a chance to learn about Redis and get familiar with how it works.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Redis
 has been completely problem free and the community is great.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;A
 Scala futures based interface for Redis was created. This functionality is now moving into their Cell Architecture.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;URL
 shortener uses Redis as the first level cache and HBase as permanent storage.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Dashboard’s
 secondary index is built around Redis.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Redis
 is used as Gearman’s persistence layer using a memcache proxy built using Finagle.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Slowly
 moving from memcache to Redis. Would like to eventually settle on just one caching service. Performance is on par with memcache.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;h3 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:22px; line-height:24px; letter-spacing:-0.02em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;内部的Firehose(通信管道)&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Internally
 applications need access to the activity stream. An activity steam is information about users creating/deleting posts, liking/unliking posts, etc. &amp;nbsp;A challenge is to distribute so much data in real-time. Wanted something that would scale internally and that
 an application ecosystem could reliably grow around. A central point of distribution was needed.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Previously
 this information was distributed using Scribe/Hadoop. Services would log into Scribe and begin tailing and then pipe that data into an app. This model stopped scaling almost immediately, especially at peak where people are creating 1000s of posts a second.
 Didn’t want people tailing files and piping to grep.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;An
 internal firehose was created as a message bus. Services and applications talk to the firehose via Thrift.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;LinkedIn’s
 Kafka is used to store messages. Internally consumers use an HTTP stream to read from the firehose. MySQL wasn’t used because the sharding implementation is changing frequently so hitting it with a huge data stream is not a good idea.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;The
 firehose model is very flexible, not like Twitter’s firehose in which data is assumed to be lost.&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;The
 firehose stream can be rewound in time. It retains a week of data. On connection it’s possible to specify the point in time to start reading.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Multiple
 clients can connect and each client won’t see duplicate data. Each client has a client ID. Kafka supports a consumer group idea. Each consumer in a consumer group gets its own messages and won’t see duplicates. Multiple clients can be created using the same
 consumer ID and clients won’t see duplicate data. This allows data to be processed independently and in parallel. Kafka uses ZooKeeper to periodically checkpoint how far a consumer has read.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;h3 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:22px; line-height:24px; letter-spacing:-0.02em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Cell
 Design for Dashboard Inbox(业务方面的实现，未翻译)&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;The
 current scatter-gather model for providing Dashboard functionality has very limited runway. It won’t last much longer.&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;The
 solution is to move to an inbox model implemented using a Cell Based Architecture that is similar to&amp;nbsp;Facebook Messages.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;An
 inbox is the opposite of scatter-gather. A user’s dashboard, which is made up posts from followed users and actions taken by other users, &amp;nbsp;is logically stored together in time order.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Solves
 the scatter gather problem because it’s an inbox. You just ask what is in the inbox so it’s less expensive then going to each user a user follows. This will scale for a very long time.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Rewriting
 the Dashboard is difficult. The data has a distributed nature, but it has a transactional quality, it’s not OK for users to get partial updates.&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;The
 amount of data is incredible. Messages must be delivered to hundreds of different users on average which is a very different problem than Facebook faces. Large date &amp;#43; high distribution rate &amp;#43; multiple datacenters.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Spec’ed
 at a million writes a second and 50K reads a second. The data set size is 2.7TB of data growth with no replication or compression turned on. The million writes a second is from the 24 byte row key that indicates what content is in the inbox.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Doing
 this on an already popular application that has to be kept running.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Cells&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;A
 cell is a self-contained installation that has all the data for a range of users. All the data necessary to render a user’s Dashboard is in the cell.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Users
 are mapped into cells. Many cells exist per data center.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Each
 cell has an HBase cluster, service cluster, and Redis caching cluster.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Users
 are homed to a cell and all cells consume all posts via firehose updates.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Each
 cell is Finagle based and populates HBase via the firehose and service requests over Thrift.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;A
 user comes into the Dashboard, users home to a particular cell, a service node reads their dashboard via HBase, and passes the data back.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Background
 tasks consume from the firehose to populate tables and process requests.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;A
 Redis caching layer is used for posts inside a cell.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Request
 flow: a user publishes a post, the post is written to the firehose, all of the cells consume the posts and write that post content to post database, the cells lookup to see if any of the followers of the post creator are in the cell, if so the follower inboxes
 are updated with the post ID.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Advantages
 of cell design:&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Massive
 scale requires parallelization and parallelization requires components be isolated from each other so there is no interaction. Cells provide a unit of parallelization that can be adjusted to any size as the user base grows.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Cells
 isolate failures. One cell failure does not impact other cells.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Cells
 enable nice things like the ability to test upgrades, implement rolling upgrades, and test different versions of software.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;The
 key idea that is easy to miss is:&amp;nbsp;&amp;nbsp;all posts are replicated to all cells.&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Each
 cell stores a single copy of all posts. Each cell can completely satisfy a Dashboard rendering request. Applications don’t ask for all the post IDs and then ask for the posts for those IDs. It can return the dashboard content for the user. Every cell has all
 the data needed to fulfill a Dashboard request without doing any cross cell communication.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Two
 HBase tables are used: one that stores a copy of each post. That data is small compared to the other table which stores every post ID for every user within that cell. The second table tells what the user’s dashboard looks like which means they don’t have to
 go fetch all the users a user is following. It also means across clients they’ll know if you read a post and viewing a post on a different device won’t mean you read the same content twice. With the inbox model state can be kept on what you’ve read.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Posts
 are not put directly in the inbox because the size is too great. So the ID is put in the inbox and the post content is put in the cell just once. This model greatly reduces the storage needed while making it simple to return a time ordered view of an users
 inbox. The downside is each cell contains a complete copy of call posts. Surprisingly posts are smaller than the inbox mappings. Post growth per day is 50GB per cell, inbox grows at 2.7TB a day. Users consume more than they produce.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;A
 user’s dashboard doesn’t contain the text of a post, just post IDs, and the majority of the growth is in the IDs.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;As
 followers change the design is safe because all posts are already in the cell. If only follower posts were stored in a cell then cell would be out of date as the followers changed and some sort of back fill process would be needed.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;An
 alternative design is to use a separate post cluster to store post text. The downside of this design is that if the cluster goes down it impacts the entire site. &amp;nbsp;Using the cell design and post replication to all cells creates a very robust architecture.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;A
 user having millions of followers who are really active is handled by selectively materializing user feeds by their access model (see Feeding Frenzy).&lt;/span&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Different
 users have different access models and distribution models that are appropriate. Two different distribution modes: one for popular users and one for everyone else.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Data
 is handled differently depending on the user type. Posts from active users wouldn’t actually be published, posts would selectively materialized.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Users
 who follow millions of users are treated similarly to users who have millions of followers.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Cell
 size is hard to determine. The size of cell is the impact site of a failure. The number of users homed to a cell is the impact. There’s a tradeoff to make in what they are willing to accept for the user experience and how much it will cost.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Reading
 from the firehose is the biggest network issue. Within a cell the network traffic is manageable.&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;As
 more cells are added cells can be placed into a cell group that reads from the firehose and then replicates to all cells within the group. A hierarchical replication scheme. This will also aid in moving to multiple datacenters.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:22px; line-height:24px; letter-spacing:-0.02em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;团队结构&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Teams:
 技术设施, 平台开发，架构, SRE （侧重可靠性和可拓展性方面的问题解决）, 产品, 测试, services（趋向于战略研究）.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:22px; line-height:24px; letter-spacing:-0.02em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;软件部署&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;开发一套rsync脚本来部署PHP，当机器超过200台的时候出现各种状态问题。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;接下来，使用Capistrano（一个开源工具，可以在多台服务器上运行脚本）在服务堆栈中构建部署进程（开发、分期、生产）。在几十台机器上部署可以正常工作，但当通过SSH部署到数百台服务器时，再次失败。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;现在，所有的机器上运行一个协调软件。基于Redhat
 Func（一个安全的、脚本化的远程控制框架和接口）功能，一个轻量级的API用于向主机发送命令，以构建扩展性。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;建立部署是在Func的基础上向主机发送命令，避免了使用SSH。比如，想在组A上部署软件，控制主机就可以找出隶属于组A的节点，并运行部署命令。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;部署命令使用Capistrano来实现。使用http的方式从git从库上来检出和上传。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Func
 API用于返回状态报告，报告机器上的软件版本号&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;安全重启任何服务，因为他们先关闭连接，然后重启。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;所有功能在激活前都运行dark
 mode下&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:22px; line-height:24px; letter-spacing:-0.02em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;开发&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;从哲学上将，任何人都可以使用自己想要的任意工具。但随着团队的发展壮大，这些工具出现了问题。新员工想要更好地融入团队，快速地解决问题，必须以他们为中心，建立操作的标准化。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;过程类&amp;#20284;于Scrum（一种敏捷管理框架），非常敏捷。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;每个开发人员都有一台预配置的开发机器，并按照控制更新。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;开发机会出现变化，测试，分期，乃至用于生产。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;开发者使用VIM和TextMate。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;测试是对PHP程序进行代码审核。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;在服务方面，他们已经实现了一个与提交相挂钩的测试基础架构，接下来将继承并内建通知机制。&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:22px; line-height:24px; letter-spacing:-0.02em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;招聘流程&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;面试通常避免数学、猜谜、脑筋急转弯等问题，看重实际工作技能。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;编程能力是重中之重。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;找到合适的人，不是比较人&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;挑战在于找到具有可用性、扩展性经验的人才，以应对Tumblr面临的网络拥塞。&lt;br style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif&quot;&gt;
&lt;/span&gt;
&lt;p style=&quot;margin-top:0px; margin-bottom:0.8em; padding-top:0px; padding-bottom:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;/p&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Example,
 for a new ID generator they needed A JVM process to generate service responses in less the 1ms at a rate at 10K requests per second with a 500 MB RAM limit with High Availability. They found the serial collector gave the lowest latency for this particular
 work load. Spent a lot of time on JVM tuning.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;h2 dir=&quot;ltr&quot; style=&quot;margin-top:0.7em; margin-right:0px; margin-bottom:0.2em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:28px; line-height:30px; letter-spacing:-0.03em&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Lessons
 learned&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;margin-top:0.4em; margin-right:0px; margin-bottom:1em; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; line-height:21px&quot;&gt;
&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;无处不在的自动化。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;MySQL
 添加水平分区, 应用则不需要。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Redis是惊人的（是不是提醒大家用一下）。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;Scala应用程序执行效率和出色。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;取消不能工作的项目。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;雇佣的人不要因为他们有对团队无用的技能，雇佣的人应该适应团队和工作。&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;找到帮你找到合适人的stack&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;围绕团队技能开展工作&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;阅读论文和博客&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;多与同行交流&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:2.5em; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; list-style-position:outside&quot;&gt;
&lt;span style=&quot;margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:0px; font-family:'Segoe UI',Calibri,'Myriad Pro',Myriad,'Trebuchet MS',Helvetica,Arial,sans-serif; font-size:14px&quot;&gt;技术追求需要循序渐进。在正式投入使用前，Tumblr用心研究HBase和Redis
 ， 这样可以降低线上服务风险。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br&gt;
&lt;p&gt;&lt;/p&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-3-17 20:48:29 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7365044&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：394 评论：0 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7365044#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638053020/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7365044&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Sat, 17 Mar 2012 20:48:29 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7365044</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7365044</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/638053020/1166164</fs:itemid></item><item><title>[转][转]使用Go语言一段时间的感受</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7364931</link><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;作者：&lt;span style=&quot;&quot;&gt;Windstorm&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;来源：&lt;a href=&quot;http://www.kunli.info/2012/03/03/golang-feeling/&quot;&gt;http://www.kunli.info/2012/03/03/golang-feeling/&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;&quot;&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;有一段时间没更新了。最近在忙一个Server&amp;#43;Client的项目，Client是Android手机，大概也就是几十的规模。Server是纯Golang实现，没有apache或者ngix这种web server，也没有数据库，自己写了个文件管理module，handle这种小规模的服务没问题。算下来接触Golang也有四个多月了，断断续续写了一些东西，这里纪录一下心得吧&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;先大概说下为什么用Golang。我是一个对语言有洁癖的人，曾经是一个c&amp;#43;Python的坚定呐喊者，最常说的一句话就是，只要熟练这两种，什么情况都能应付，根本不用Java和C&amp;#43;&amp;#43;(纯指我所在的领域）。核心代码用c，速度快，需要记的语言细节少；外围用Python glue，灵活，简洁，任何模块都容易上手，绝配。Java的繁琐，C&amp;#43;&amp;#43;的无数无用的特性，都让我只在不得不用的时候才去用。Objective-C是另一个我欣赏的语言，问题是不跨平台，过于封闭。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;&lt;span id=&quot;more-1652&quot;&gt;&lt;/span&gt;&lt;br&gt;
可惜的是，在这个节奏极快的时代，不是所有情况下都适合上c。之前有一个项目也是类&amp;#20284;的架构和规模，为了节省时间，当初几乎没有服务器平台编程经验的我，在服务器端选择用Django&amp;#43;Apache&amp;#43;MySQL做，成熟，社区活跃，又是python作为主要开发语言，这些都是这个选择的原因。说实话，几个月过去后，回首看，这不是一个愉快的经历。Django是一个好架构，大而全，而大而全有时也就意味着臃肿，五花八门的配置，过紧的模块耦合对引入第三方工具限制颇多，自带的ORM又不好用。之前从来没有搞过服务器配置的我，对Apache的配置和效率所带来的琐碎的东西也头疼。总的来说这个部分花了我很多时间，有新手学习服务器编程的必经过程，也有折腾Django和Apache没必要的时间浪费，很大部分上抵消了Python带来的快速开发的灵活性。而一旦服务器上线，动态语言带来的一些bug又会让人头疼。对于普通高校实验室这种没有完善的服务器调试的条件，基本就是改了就上线用，有些隐蔽bug到某些条件分支才会触发，一旦在运行中途出问题，改起来也麻烦。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;从那时起，我就特别想，要是有一种语言能把c和Python的优点结合起来，也就是说&lt;/p&gt;
&lt;ul style=&quot;list-style-position:outside; padding-bottom:2px; margin:5px 20px; padding-left:2px; padding-right:2px; padding-top:2px&quot;&gt;
&lt;li style=&quot;margin:2px 0px&quot;&gt;速度快，高性能&lt;/li&gt;&lt;li style=&quot;margin:2px 0px&quot;&gt;简洁明了，需要记的语言细节少，开发迅速(c)&lt;/li&gt;&lt;li style=&quot;margin:2px 0px&quot;&gt;灵活，开发快速，类Python的list，map等常用数据结构支持(Python)&lt;/li&gt;&lt;li style=&quot;margin:2px 0px&quot;&gt;完善的模块支持，模块也容易上手(Python)&lt;/li&gt;&lt;li style=&quot;margin:2px 0px&quot;&gt;对程序员友好的并行架构(Erlang)&lt;/li&gt;&lt;li style=&quot;margin:2px 0px&quot;&gt;安全，绝大部分问题能消灭在compile time中(C minus pointer)&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;那基本就是系统级和网络级编程最对我胃口的语言了。然后我就找到了&lt;a href=&quot;http://golang.org/&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;Go&lt;/a&gt;。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;Golang是一个新语言，截至目前为止，第一版正式版还没有发布。Golang的设计者是Robert Griesemer, Rob Pike和Ken Thompson，当年设计C和Unix，后来的Plan9团队中的人 。Golang的设计理念很明确，就是将动态类型语言的编程容易度和静态类型语言的安全效率结合起来。如果你想更深入了解Golang的发展历史以及完整的目标，请参考&lt;a href=&quot;http://golang.org/doc/go_faq.html#What_is_the_purpose_of_the_project&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;Golang
 FAQ&lt;/a&gt;。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;当然，Golang吸引我的地方，不是因为其是Google出品，也不是因为其设计者皆为大牛，而是因为，Golang真的做到了它所宣称的目标。Golang就如同C和Python中间的完美结合，如果你是Python爱好者，又追求代码的速度和并行化，那么简单说，Golang就是为你设计的。Golang有很浓厚的C的遗风，尽量屏蔽C&amp;#43;&amp;#43;和Java的影响，比如没有独立的OO体系（并不是说不能OO），一切以struct为中心，没有exceptions(Oh
 yes!)，仍然有指针，等等。但是，Golang又吸取了很多新语言的精华，并带有自己独特的设计。比如&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;1. 保留但大幅度简化指针&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;Golang保留着C中&amp;#20540;和指针的区别，但是对于指针繁琐用法进行了大量的简化，引入引用的概念。所以在Golang中，你几乎不用担心会因为直接操作内寸而引起各式各样的错误。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;2. 多参数返回&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;还记得在C里面为了回馈多个参数，不得不开辟几段指针传到目标函数中让其操作么？在Go里面这是完全不必要的。而且多参数的支持让Go无需使用繁琐的exceptions体系，一个函数可以返回期待的返回&amp;#20540;加上error，调用函数后立刻处理错误信息，清晰明了。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;3. Array，slice，map等内置基本数据结构&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;如果你习惯了Python中简洁的list和dict操作，在Golang中，你不会感到孤单。一切都是那么熟悉，而且更加高效。如果你是C&amp;#43;&amp;#43;程序员，你会发现你又找到了STL的vector 和 map这对朋友。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;4. Interface&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;Golang最让人赞叹不易的特性，就是&lt;a href=&quot;http://research.swtch.com/interfaces&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;interface的设计&lt;/a&gt;。任何数据结构，只要实现了interface所定义的函数，自动就implement了这个interface，没有像Java那样冗长的class申明，提供了&lt;a href=&quot;http://golangtutorials.blogspot.com/2011/06/interfaces-in-go.html&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;灵活太多的设计度和OO抽象度&lt;/a&gt;，让你的代码也非常干净。千万不要以为你习惯了Java那种一条一条加implements的方式，感觉还行，等接口的设计越来越复杂的时候，无数Bug正在后面等着你。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;同时，正因为如此，Golang的interface可以用来表示任何generic的东西，比如一个空的interface，可以是string可以是int，可以是任何数据类型，因为这些数据类型都不需要实现任何函数，自然就满足空interface的定义了。加上Golang的type assertion，可以提供一般动态语言才有的duck typing特性， 而仍然能在compile中捕捉明显的错误。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;5. OO&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;Golang本质上不是面向对象语言，它还是过程化的。但是，在Golang中， 你可以很轻易的做大部分你在别的OO语言中能做的事，用更简单清晰的逻辑。是的，在这里，不需要class，仍然可以继承，仍然可以多态，但是速度却快得多。因为本质上，OO在Golang中，就是&lt;a href=&quot;http://golangtutorials.blogspot.com/2011/06/structs-in-go-instead-of-classes-in.html&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;普通的struct操作&lt;/a&gt;。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;6. Goroutine&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;这个几乎算是Golang的招牌特性之一了，我也不想多提。如果你完全不了解Goroutine，那么你只需要知道，这玩意是超级轻量级的类&amp;#20284;线程的东西，但通过它，你不需要复杂的线程操作锁操作，不需要care调度，就能玩转基本的并行程序。在Golang里，触发一个routine和erlang spawn一样简单。基本上要掌握Golang，以Goroutine和channel为核心的&lt;a href=&quot;http://golang.org/doc/go_mem.html&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;内存模型&lt;/a&gt;是必须要懂的。不过请放心，真的非常简单。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;7. 更多现代的特性&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;和C比较，Golang完全就是一门现代化语言，原生支持的Unicode, garbage collection, Closures(是的，和functional programming language类&amp;#20284;), function是first class object，等等等等。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;看到这里，你可能会发现，我用了很多轻易，简单，快速之类的形容词来形容Golang的特点。我想说的是，一点都不夸张，连Golang的入门学习到提高，都比别的语言门槛低太多太多。在大部分人都有C的背景的时代，对于Golang，从入门到能够上手做项目，最多不过半个月。Golang给人的感觉就是太直接了，什么都直接，读源代码直接，写自己的代码也直接。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;有朋友要抗议了，你把Golang吹的这么好，难道它就没有缺点？有，当然有，不过和它的优点比，我觉得很多缺点都是因为整个语言太新，不成熟，随着时间的推移都能得到解决，相比之下都能忍了。如果你希望进一步了解Golang的优缺点，可以参考以下yufeng写的这篇文章，系统编程语言明日之星—Go（http://blog.yufeng.info/Go.pdf。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;还有朋友要说，Golang这么好，为什么没人用？我想说，&amp;#30524;界放开点，这个世界精彩的东西比你想象的多。Golang被Google用于&lt;a href=&quot;http://code.google.com/p/vitess/&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;Youtube的数据库&lt;/a&gt;，被&lt;a href=&quot;http://go-lang.cat-v.org/organizations-using-go&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;越来越多的国外公司&lt;/a&gt;(大部分创业公司)用于后端开发，甚至在天朝，也有完全用Golang做服务开发的&lt;a href=&quot;https://qbox.me/&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;云应用公司&lt;/a&gt;了。可以说，随着Go
 1即将到来的正式推出，Golang的使用范围，应该会越来越广。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;好，总结时间&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;如果你是Python和动态语言狂热爱好者，Go不一定能给你带来很大的惊喜，这纯粹取决于你得项目性质，考虑到Python目前在很多地方都用C做核心运算，速度在大部分情况下都不是大问题。scalability是一个问题，但并不是人人都会遇到的。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;如果你是C爱好者，强烈建议你学习和使用Go。Go可以调用C/C&amp;#43;&amp;#43;程序，又提供了太多的便利，速度上稍有牺牲，但并不大。在绝大部分场景下Go能给你带来媲美C的性能，而对于某些确实性能过于关键的场合，也可以通过cgo让Go和C搭配。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;如果你是Java爱好者，除非你是做Android这种不得不用Java的平台，否则也建议你尝试学习Go，这个开发上感觉的差异如同比较开载着1吨石头的拖拉机和开保时捷911那么明显，而Java能给你的，Go能给得更好。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;如果你是C&amp;#43;&amp;#43;爱好者，!@#$%^&amp;amp;*，恭喜你，至少你的智商应该是没问题的。人生苦短，赶紧脱离C&amp;#43;&amp;#43;这个苦海吧。你用来学89个C&amp;#43;&amp;#43;高级特性的时间，估计已经用Go写了64个开源项目了。&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;如果你是像我一样的C和Python的爱好者，对动态语言又没有特殊的热爱……我还需要说什么呢？&lt;/p&gt;
&lt;p style=&quot;font-style:normal; font-size:1.15em&quot;&gt;让我们荡起双桨，去遨游&lt;a href=&quot;http://golang.org/doc/install.html&quot; style=&quot;color:rgb(153,51,0); text-decoration:underline&quot;&gt;Golang的海洋&lt;/a&gt;吧。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-3-17 20:04:54 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7364931&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：486 评论：0 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7364931#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638053019/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7364931&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Sat, 17 Mar 2012 20:04:54 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7364931</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7364931</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/638053019/1166164</fs:itemid></item><item><title>[转][转]使用 PHP 直接在共享内存中存储数据集</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7363828</link><description>&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size:13px&quot;&gt;来源：http://www.ibm.com/developerworks/cn/opensource/os-php-shared-memory/&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size:13px&quot;&gt;&lt;br&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family:Simsun; font-size:13px&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;Overview&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;概述&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;共享内存是一种在相同机器中的应用程序之间交换数据的有效方式。一个进程可创建一个可供其他进程访问的内存段，只要它分配了正确的权限。每个内存段拥有一个惟一的 ID（称为&amp;nbsp;&lt;em&gt;shmid&lt;/em&gt;），这个 ID 指向一个物理内存区域，其他进程可在该区域操作它。创建并提供了合适的权限之后，同一台机器中的其他进程就可以操作这些内存段：读取、写入和删除。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;这表明使用 C 语言编写的应用程序可与使用其他语言（比如 Java™ 或 PHP）编写的应用程序共享信息。它们都可以共享信息，只要它们可访问和理解该信息。共享内存在针对大部分语言的实现中得到了广泛使用，所以访问应该不是问题。要理解信息，我们可以使用一种标准&amp;#26684;式，比如 XML 或 JSON。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;共享内存的使用是一种在进程之间交换数据的快速方法，主要因为在创建内存段之后传递数据，不会涉及内核。这种方法常常称为进程间通信 (IPC)。其他 IPC 方法包括管道、消息队列、RPC 和套接字。当使用需要彼此通信的应用程序的生态系统时，这种在应用程序之间快速、可靠地交换数据的能力非常有用。取决于生态系统的大小，使用数据库在应用程序之间交换信息的常用方法常常会导致查询缓慢，甚至 I/O 阻塞。使用共享内存，没有 I/O 会减缓开发人员的进度。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;本文的提议非常简单，学习如何使用 PHP 创建和操作共享内存段，使用它们存储可供其他应用程序使用的数据集。即使没有使用共享内存交换数据的计划，它本身也在许多好处，因为它使应用程序能够远离 I/O 问题。将数据集直接存储在内存中具有诸多优势，从 Web 服务数据缓存到会话共享。它是一个非常有用的概念，每个 PHP 开发人员都应该知道。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;Shared memory and PHP&quot;&gt;&lt;span class=&quot;smalltitle&quot; style=&quot;font-size:1.2em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;共享内存和 PHP&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;PHP 拥有丰富的可用扩展，共享内存也一样。使用一些共享的函数，无需安装任何扩展，开发人员就能够轻松操作内存段。&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;background-color:rgb(255,255,255); height:1px; clear:both&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;text-align:right; padding-bottom:5px; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; height:15px; clear:both; font-size:0.76em; padding-top:5px&quot;&gt;
&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/opensource/os-php-shared-memory/#ibm-pcon&quot; style=&quot;padding-bottom:0px; margin:0px; padding-left:18px; padding-right:0px; display:inline; color:rgb(76,110,148); font-weight:bold; text-decoration:none; padding-top:0px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;回页首&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;Create segments&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;创建内存段&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;共享内存函数类&amp;#20284;于文件操作函数，但无需处理一个流，您将处理一个共享内存访问 ID。第一个示例就是&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_open&lt;/code&gt;&amp;nbsp;函数，它允许您打开一个现有的内存段或创建一个新内存段。此函数非常类&amp;#20284;于经典的&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;fopen&lt;/code&gt;&amp;nbsp;函数，后者打开用于文件操作的流，返回一个资源供其他希望读取或写入该打开的流的函数使用。让我们看看清单
 1 中的&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_open&lt;/code&gt;。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing1&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 1.&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_open&lt;/code&gt;&amp;nbsp;函数&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				
&amp;lt;?php

$systemid = 864; // System ID for the shared memory segment
$mode = &amp;quot;c&amp;quot;; // Access mode
$permissions = 0755; // Permissions for the shared memory segment
$size = 1024; // Size, in bytes, of the segment

$shmid = shmop_open($systemid, $mode, $permissions, $size);

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;该函数中出现的第一个事物是系统 ID 参数。这是标识系统中的共享内存段的数字。第二个参数是访问模式，它非常类&amp;#20284;于&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;fopen&lt;/code&gt;&amp;nbsp;函数的访问模式。您可以在 4 种不同的模式下访问一个内存段：&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;padding-bottom:5px; margin-top:0px; padding-right:5px; margin-bottom:0px; font-size:0.76em; padding-top:0px&quot;&gt;
&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;模式 “a”，它允许您访问只读内存段&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;模式 “w”，它允许您访问可读写的内存段&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;模式 “c”，它创建一个新内存段，或者如果该内存段已存在，尝试打开它进行读写&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;模式 “n”，它创建一个新内存段，如果该内存段已存在，则会失败&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;第三个参数是内存段的权限。您必须在这里提供一个八进制&amp;#20540;。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;第四个参数提供内存段大小，以字节为单位。在写入一个内存段之前，您必须在它之上分配适当的字节数。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;请注意，此函数返回一个 ID 编号，其他函数可使用该 ID 编号操作该共享内存段。这个 ID 是共享内存访问 ID，与系统 ID 不同，它以参数的形式传递。请注意不要混淆这两者。如果失败，&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_open&lt;/code&gt;&amp;nbsp;将返回 FALSE。&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;background-color:rgb(255,255,255); height:1px; clear:both&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;text-align:right; padding-bottom:5px; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; height:15px; clear:both; font-size:0.76em; padding-top:5px&quot;&gt;
&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/opensource/os-php-shared-memory/#ibm-pcon&quot; style=&quot;padding-bottom:0px; margin:0px; padding-left:18px; padding-right:0px; display:inline; color:rgb(76,110,148); font-weight:bold; text-decoration:none; padding-top:0px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;回页首&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;Write in to segments&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;向内存段写入数据&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_write&lt;/code&gt;&amp;nbsp;函数向共享内存块写入数据。此函数的使用很简单，它仅接受 3 个参数，如清单 2 所示。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing2&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 2. 使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_write&lt;/code&gt;&amp;nbsp;向共享内存块写入数据&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				
&amp;lt;?php

$shmid = shmop_open(864, 'c', 0755, 1024);
shmop_write($shmid, &amp;quot;Hello World!&amp;quot;, 0);

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;这个函数类&amp;#20284;于&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;fwrite&lt;/code&gt;&amp;nbsp;函数，后者有两个参数：打开的流资源（由&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;fopen&lt;/code&gt;&amp;nbsp;返回）和您希望写入的数据。&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_write&lt;/code&gt;&amp;nbsp;函数也执行此任务。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;第一个参数是&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_open&lt;/code&gt;&amp;nbsp;返回的 ID，它识别您操作的共享内存块。第二个参数是您希望存储的数据，最后的第三个参数是您希望开始写入的位置。默认情况下，我们始终使用 0 来表示开始写入的位置。请注意，此函数在失败时会返回 FALSE，在成功时会返回写入的字节数。&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;background-color:rgb(255,255,255); height:1px; clear:both&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;text-align:right; padding-bottom:5px; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; height:15px; clear:both; font-size:0.76em; padding-top:5px&quot;&gt;
&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/opensource/os-php-shared-memory/#ibm-pcon&quot; style=&quot;padding-bottom:0px; margin:0px; padding-left:18px; padding-right:0px; display:inline; color:rgb(76,110,148); font-weight:bold; text-decoration:none; padding-top:0px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;回页首&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;Read from segments&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;从内存段读取数据&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;从共享内存段读取数据很简单。您只需要一个打开的内存段和&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_read&lt;/code&gt;&amp;nbsp;函数。此函数接受一些参数，工作原理类&amp;#20284;于&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;fread&lt;/code&gt;。参见清单 3，读取一个 PHP 文件的内容。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing3&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 3. 使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_read&lt;/code&gt;&amp;nbsp;读取一个文件的内容&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				
&amp;lt;?php

$stream = fopen('file.txt', 'r&amp;#43;');
fwrite($stream, &amp;quot;Hello World!&amp;quot;);
echo fread($stream, 11);

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;读取共享内存段的内容的过程与此类&amp;#20284;，如清单 4 所示：&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing4&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 4. 读取共享内存段的内容&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				
&amp;lt;?php

$shmid = shmop_open(864, 'c', 0755, 1024);
shmop_write($shmid, &amp;quot;Hello World!&amp;quot;, 0);
echo shmop_read($shmid, 0, 11);

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;请留意这里的参数。&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_read&lt;/code&gt;&amp;nbsp;函数将接受&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_open&lt;/code&gt;&amp;nbsp;返回的 ID，我们已知道它，不过它还接受另外两个参数。第二个参数是您希望从内存段读取的位置，而第三个是您希望读取的字节数。第二个参数可以始终为
 0，表示数据的开头，但第三个参数可能存在问题，因为我们不知道我们希望读取多少字节。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;这非常类&amp;#20284;于我们在&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;fread&lt;/code&gt;&amp;nbsp;函数中的行为，该函数接受两个参数：打开的流资源（由&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;fopen&lt;/code&gt;&amp;nbsp;返回）和您希望从该流读取的字节数。使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;filesize&lt;/code&gt;&amp;nbsp;函数（它返回一个文件中的字节数）来完整地读取它。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;幸运的是，当使用共享内存段时，&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_size&lt;/code&gt;&amp;nbsp;函数返回一个内存段的大小（以字节为单位），类&amp;#20284;于&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;filesize&lt;/code&gt;&amp;nbsp;函数。参见清单 5。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing5&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 5.&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_size&lt;/code&gt;&amp;nbsp;函数返回内存段大小，以字节为单位&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				
&amp;lt;?php

$shmid = shmop_open(864, 'c', 0755, 1024);
shmop_write($shmid, &amp;quot;Hello World!&amp;quot;, 0);

$size = shmop_size($shmid);
echo shmop_read($shmid, 0, $size);

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;background-color:rgb(255,255,255); height:1px; clear:both&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;text-align:right; padding-bottom:5px; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; height:15px; clear:both; font-size:0.76em; padding-top:5px&quot;&gt;
&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/opensource/os-php-shared-memory/#ibm-pcon&quot; style=&quot;padding-bottom:0px; margin:0px; padding-left:18px; padding-right:0px; display:inline; color:rgb(76,110,148); font-weight:bold; text-decoration:none; padding-top:0px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;回页首&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;Remove a segment&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;删除内存段&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;我们学习了如何打开、写入和读取共享内存段。要完成我们的 CRUD 类，我们还需要学习如何删除内存段。该任务可使用&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_delete&lt;/code&gt;&amp;nbsp;函数轻松完成，该函数仅接受一个参数：我们希望删除的共享内存 ID。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing6&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 6.&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_delete&lt;/code&gt;&amp;nbsp;标记要删除的内存段&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				
&amp;lt;?php

$shmid = shmop_open(864, 'c', 0755, 1024);
shmop_write($shmid, &amp;quot;Hello World!&amp;quot;, 0);
shmop_delete($shmid);

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;这不会实际删除该内存段。它将该内存段标记为删除，因为共享内存段在有其他进程正在使用它时无法被删除。&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_delete&lt;/code&gt;&amp;nbsp;函数将该内存段标记为删除，阻止任何其他进程打开它。要删除它，我们需要关闭该内存段。&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;background-color:rgb(255,255,255); height:1px; clear:both&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;text-align:right; padding-bottom:5px; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; height:15px; clear:both; font-size:0.76em; padding-top:5px&quot;&gt;
&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/opensource/os-php-shared-memory/#ibm-pcon&quot; style=&quot;padding-bottom:0px; margin:0px; padding-left:18px; padding-right:0px; display:inline; color:rgb(76,110,148); font-weight:bold; text-decoration:none; padding-top:0px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;回页首&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;Close a segment&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;关闭内存段&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;打开一个共享内存段会 “附加” 到它。附加该内存段之后，我们可在其中进行读取和写入，但完成操作后，我们必须从它解除。这使用清单 7 中的&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_close&lt;/code&gt;&amp;nbsp;函数来完成。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;这非常类&amp;#20284;于处理文件时的&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;fclose&lt;/code&gt;&amp;nbsp;函数。打开包含一个文件的流并在其中读取或写入数据后，我们必须关闭它，否则将发生锁定。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing7&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 7. 使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_close&lt;/code&gt;&amp;nbsp;与一个内存段分开&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				
&amp;lt;?php

$shmid = shmop_open(864, 'c', 0755, 1024);
shmop_write($shmid, &amp;quot;Hello World!&amp;quot;, 0);
shmop_delete($shmid);
shmop_close($shmid);

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;background-color:rgb(255,255,255); height:1px; clear:both&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;text-align:right; padding-bottom:5px; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; height:15px; clear:both; font-size:0.76em; padding-top:5px&quot;&gt;
&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/opensource/os-php-shared-memory/#ibm-pcon&quot; style=&quot;padding-bottom:0px; margin:0px; padding-left:18px; padding-right:0px; display:inline; color:rgb(76,110,148); font-weight:bold; text-decoration:none; padding-top:0px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;回页首&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;storage option&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;使用共享内存作为一个存储选项&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;有了共享内存和共享内存段上基本 CRUD 操作的基本知识，是时候应用此知识了。我们可以使用共享内存作为一种独特的存储选项，提供快速读/写操作和进程互操作性等优势。对于 Web 应用程序，这意味着：&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;padding-bottom:5px; margin-top:0px; padding-right:5px; margin-bottom:0px; font-size:0.76em; padding-top:0px&quot;&gt;
&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;缓存存储（数据库查询、Web 服务数据、外部数据）&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;会话存储&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;应用程序之间的数据交换&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;在继续之前，我想介绍一个名为 SimpleSHM 小型库。SimpleSHM 是一个较小的抽象层，用于使用 PHP 操作共享内存，支持以一种面向对象的方式轻松操作内存段。在编写使用共享内存进行存储的小型应用程序时，这个库可帮助创建非常简洁的代码。要了解 SimpleSHM，请访问&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/klaussilveira/SimpleSHM&quot; style=&quot;color:rgb(76,110,148)&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;GitHub
 页面&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-size:13px&quot;&gt;。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;您可以使用 3 个方法进行处理：读、写和删除。从该类中简单地实例化一个对象，可以控制打开的共享内存段。清单 8 展示了基本用途。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing8&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 8. SimpleSHM 基本用途&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				
&amp;lt;?php

$memory = new SimpleSHM;
$memory-&amp;gt;write('Sample');
echo $memory-&amp;gt;read();

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;请注意，这里没有为该类传递一个 ID。如果没有传递 ID，它将随机选择一个编号并打开该编号的新内存段。我们可以以参数的形式传递一个编号，供构造函数打开现有的内存段，或者创建一个具有特定 ID 的内存段，如清单 9 所示。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing9&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 9. 打开一个特定的内存段&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				

&amp;lt;?php

$new = new SimpleSHM(897);
$new-&amp;gt;write('Sample');
echo $new-&amp;gt;read();

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;神奇的方法&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;__destructor&lt;/code&gt;&amp;nbsp;负责在该内存段上调用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;shmop_close&lt;/code&gt;&amp;nbsp;来取消设置对象，以与该内存段分离。我们将这称为 “SimpleSHM 101”。现在让我们将此方法用于更高级的用途：使用共享内存作为存储。存储数据集需要序列化，因为数组或对象无法存储在内存中。尽管这里使用了
 JSON 来序列化，但任何其他方法（比如 XML 或内置的 PHP 序列化功能）也已足够。清单 10 给出了一个示例。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing10&quot;&gt;&lt;span style=&quot;font-family:arial,sans-serif; font-size:13px; padding-bottom:0.7em; padding-left:5px; padding-right:5px; font-size:0.76em; padding-top:0.3em&quot;&gt;清单 10. 使用共享内存作为存储&lt;/span&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size:0.8em&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;border-bottom:rgb(204,204,204) 1px solid; border-left:rgb(204,204,204) 1px solid; padding-bottom:5px; background-color:rgb(247,247,247)!important; padding-left:2px; padding-right:2px; font-family:arial,nsimsun,sans-serif; border-top:rgb(204,204,204) 1px solid; border-right:rgb(204,204,204) 1px solid; padding-top:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; margin-top:0px; width:694px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; margin-bottom:0px; color:rgb(0,0,0); font-size:11px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;				
&amp;lt;?php

require('SimpleSHM.class.php');

$results = array(
	'user' =&amp;gt; 'John',
	'password' =&amp;gt; '123456',
	'posts' =&amp;gt; array('My name is John', 'My name is not John')
);

$data = json_encode($results);

$memory = new SimpleSHM;
$memory-&amp;gt;write($data);
$storedarray = json_decode($memory-&amp;gt;read());

print_r($storedarray);

?&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;我们成功地将一个数组序列化为一个 JSON 字符串，将它存储在共享内存块中，从中读取数据，去序列化 JSON 字符串，并显示存储的数组。这看起来很简单，但请想象一下这个代码片段带来的可能性。您可以使用它存储 Web 服务请求、数据库查询或者甚至模板引擎缓存的结果。在内存中读取和写入将带来比在磁盘中读取和写入更高的性能。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;使用此存储技术不仅对缓存有用，也对应用程序之间的数据交换也有用，只要数据以两端都可读的&amp;#26684;式存储。不要低估共享内存在 Web 应用程序中的力量。可采用许多不同的方式来巧妙地实现这种存储，惟一的限制是开发人员的创造力和技能。&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;background-color:rgb(255,255,255); height:1px; clear:both&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;text-align:right; padding-bottom:5px; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; height:15px; clear:both; font-size:0.76em; padding-top:5px&quot;&gt;
&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/opensource/os-php-shared-memory/#ibm-pcon&quot; style=&quot;padding-bottom:0px; margin:0px; padding-left:18px; padding-right:0px; display:inline; color:rgb(76,110,148); font-weight:bold; text-decoration:none; padding-top:0px&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;回页首&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;Conclusion&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;结束语&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;本文介绍了用于操作共享内存段的 PHP 工具包中的大部分工具，解释了共享内存的工作原理。此外，还提供了改进 Web 应用程序的建议，列出了在为 Web 应用程序问题创建解决方案时要考虑的一些因素。这些概念和实现指南可帮助您建立一个起点。我们构建的早期模型可帮助您构想更复杂的特性和解决方案。&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;next&quot;&gt;&lt;span class=&quot;smalltitle&quot; style=&quot;font-size:1.2em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;未来计划&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;我们列出了共享内存中最可能实现的一些常见问题，比如缓存、会话共享和应用程序之间的常见数据交换。此篇共享内存简介为您就常见问题而探索更佳解决方案提供机会。您可以自由扩展当前的 SimpleSHM 实现，以匹配您的需要和将更改贡献给该项目。&lt;/span&gt;&lt;/p&gt;
&lt;br&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;a name=&quot;resources&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;参考资料&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;padding-bottom:0.7em; margin-top:0px; padding-left:5px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; font-size:0.76em; padding-top:0.3em&quot;&gt;
&lt;strong&gt;&lt;span style=&quot;font-size:13px&quot;&gt;学习&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul style=&quot;padding-bottom:5px; margin-top:0px; padding-right:5px; margin-bottom:0px; font-size:0.76em; padding-top:0px&quot;&gt;
&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;Michael Kerrisk 撰写的&amp;nbsp;&lt;em&gt;&lt;a href=&quot;http://nostarch.com/tlpi&quot; style=&quot;color:rgb(76,110,148)&quot;&gt;The Linux Programming Interface&lt;/a&gt;&lt;/em&gt;&amp;nbsp;一书非常好地介绍了进程间的通信，其中第 45 到 48 章专门介绍了 System V IPC。&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;Dave Marshall 的 “&lt;/span&gt;&lt;a href=&quot;http://www.cs.cf.ac.uk/Dave/C/node27.html&quot; style=&quot;color:rgb(76,110,148)&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;IPC:Shared Memory&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-size:13px&quot;&gt;” 文章介绍了在 C 语言中使用共享内存函数的一种有趣且实用的方法。&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;padding-bottom:3px; margin-top:0px; padding-right:5px; font-family:arial,nsimsun,sans-serif; margin-bottom:0px; padding-top:0px&quot;&gt;
&lt;span style=&quot;font-size:13px&quot;&gt;Richard Stevens 的&amp;nbsp;&lt;em&gt;&lt;a href=&quot;http://www.kohala.com/start/unpv22e/unpv22e.html&quot; style=&quot;color:rgb(76,110,148)&quot;&gt;UNIX Network Programming&lt;/a&gt;&lt;/em&gt;&amp;nbsp;提供了优秀的技术内容和多个 C 语言实现。请查阅&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://www.kohala.com/start/unpv22e/unpv22e.chap12.pdf&quot; style=&quot;color:rgb(76,110,148)&quot;&gt;&lt;span style=&quot;font-size:13px&quot;&gt;示例章节&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-size:13px&quot;&gt;。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;br&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-3-17 11:59:17 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7363828&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：455 评论：1 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7363828#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638053018/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7363828&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Sat, 17 Mar 2012 11:59:17 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7363828</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7363828</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/638053018/1166164</fs:itemid></item><item><title>[转][转]Linux 平台相关代码的 C++ 解决方案</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7363820</link><description>&lt;p&gt;&lt;a name=&quot;major1&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;&lt;br&gt;
作者：温冠华&lt;br&gt;
来源：http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;major1&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;Linux 平台相关代码带来的问题&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;目前市场上存在着许多不同的 Linux 平台（例如：RedHat, Ubuntu, Suse 等），各大厂商和社区都在针对自己支持的平台进行优化，为使用者带来诸多方便的同时也对软件研发人员在进行编码时带来不少问题：&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;由于程序中不可避免的存在平台相关代码（系统调用等），软件研发人员为了保证自己的产品在各个 Linux 平台上运行顺畅，一般都需要在源代码中大量使用预编译参数，这样会大大降低程序的可读性和可维护性。
&lt;/li&gt;&lt;li&gt;接口平台无关性的原则是研发人员必须遵循的准则。但是在处理平台相关代码时如果处理不当，此原则很有可能被破坏，导致不良的编码风&amp;#26684;，影响代码的扩展和维护。 &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;本文将针对这两个问题循序渐进依次提出解决方案。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot;&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot;&gt;&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/#ibm-pcon&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;major2&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;通过设置预编译选项来处理平台相关代码&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;通过为每个平台设置相关的预编译宏能够解决 Linux 平台相关代码的问题，实际情况下，很多软件开发人员也乐于单独使用这种方法来解决问题。&lt;/p&gt;
&lt;p&gt;假设现有一动态库 Results.so，SomeFunction() 是该库的一个导出函数，该库同时为 Rhel,Suse,Ubuntu 等三个平台的 Linux 上层程序服务。（后文例子均基于此例并予以扩展。）&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing1&quot;&gt;&lt;strong&gt;清单 1. 设置预编译选项示例代码如下：&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot;&gt;
&lt;pre class=&quot;displaycode&quot;&gt;				
 // Procedure.cpp 
 void SomeFunction() 
 { 
    //Common code for all linux 
    ...... 
    ...... 
 #ifdef RHEL 
    SpecialCaseForRHEL(); 
 #endif 

 #ifdef SUSE 
    SpecialCaseForSUSE(); 
 #endif 

 #ifdef UBUNTU 
    SpecialCaseForUBUNTU(); 
 #endif 

    //Common code for all linux 
    ...... 
    ...... 

 #ifdef RHEL 
    SpecialCase2ForRHEL(); 
 #endif 

 #ifdef SUSE 
    SpecialCase2ForSUSE(); 
 #endif 

 #ifdef UBUNTU 
    SpecialCase2ForUBUNTU(); 
 #endif 

    //Common code for all linux 
 ...... 
 ...... 
 } 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p&gt;开发人员可以通过设置 makefile 宏参数或者直接设置 gcc 参数来控制实际编译内容。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot;&gt;
&lt;pre class=&quot;displaycode&quot;&gt; gcc -D RHEL Procedure.cpp -o Result.so -lstdc&amp;#43;&amp;#43;   // Use RHEL marco 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p&gt;SpecialCaseForRHEL()，SpecialCaseForSUSE()，SpecialCaseForUBUNTU() 分别在该库 (Results.so) 的其他文件中予以实现。&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;fig1&quot;&gt;&lt;strong&gt;图 1. 清单 1 代码的结构图&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;img alt=&quot;图 1. 清单 1 代码的结构图&quot; src=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/image001.jpg&quot; width=&quot;220&quot; height=&quot;166&quot;&gt;
&lt;br&gt;
&lt;p&gt;&lt;a name=&quot;minor2.1&quot;&gt;&lt;span class=&quot;smalltitle&quot;&gt;带来的问题&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;SomeFunction() 函数代码冗余，&amp;#26684;式混乱。本例仅涉及三个预编译选项，但实际情况中由于 Linux 版本众多并且可能涉及操作系统位数的问题，增加对新系统的支持会导致预编译选项不断增多，造成 SomeFunction() 函数结构十分混乱。
&lt;/li&gt;&lt;li&gt;新增其他平台相关接口（例如：增加 &lt;a name=&quot;OLE_LINK1&quot;&gt;&lt;/a&gt;&lt;a name=&quot;OLE_LINK2&quot;&gt;SpecialCase3ForRHEL()，SpecialCase3ForSUSE()，SpecialCase3ForUBUNTU），会成倍增加代码中预编译宏的数量。
&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name=&quot;OLE_LINK2&quot;&gt;破坏了接口平台无关性的原则。SpecialCaseForRHEL()，SpecialCaseForSUSE()，SpecialCaseForUBUNTU() 只是同一功能各个平台的不同实现，属于封装内容，不应该分开暴露给调用者。
&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;a name=&quot;OLE_LINK2&quot;&gt;&lt;/a&gt;
&lt;p&gt;可见，简单利用预编译宏来解决平台相关代码产生的问题不是一个好的方法，并没有解决本文开始提出的两个问题。后文将通过三个方案依次解决这些问题。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot;&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot;&gt;&lt;a name=&quot;OLE_LINK2&quot;&gt;&lt;/a&gt;&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/#ibm-pcon&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;major3&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;解决方案 1：根据接口平台无关性原则进行优化&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;实质上，SpecialCaseForRHEL()，SpecialCaseForSUSE()，SpecialCaseForUBUNTU() 只是同一功能在不同平台上的实现，SpecialCase2ForRHEL()，SpecialCase2ForSUSE()，SpecialCase2ForUBUNTU() 亦如此。对于调用者，应该遵循接口平台无关性的原则，使用统一的接口进行调用，这样才能简化代码，使代码易于维护。&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing2&quot;&gt;&lt;strong&gt;清单 2. 解决方案 1 示例代码如下：&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot;&gt;
&lt;pre class=&quot;displaycode&quot;&gt;				
 // Procedure.cpp 
 void SomeFunction() 
 { 
    //Common code for all linux 
    ...... 
    ...... 
    SpecialCase(); 

    //Common code for all linux 
    ...... 
    ...... 

    SpecialCase2(); 

    //Common code for all linux 
    ...... 
    ...... 
 } 

 void SpecialCase() 
 { 
    //Common code for all linux 
    ...... 
    ...... 
 #ifdef RHEL 
    SpecialCaseForRHEL(); 
 #endif 

 #ifdef SUSE 
    SpecialCaseForSUSE(); 
 #endif 

 #ifdef UBUNTU 
    SpecialCaseForUBUNTU(); 
 #endif 

    //Common code for all linux 
    ...... 
    ...... 
 } 

 void Special2Case() 
 { 
    //Common code for all linux 
    ...... 
    ...... 
 #ifdef RHEL 
    SpecialCase2ForRHEL(); 
 #endif 

 #ifdef SUSE 
    SpecialCase2ForSUSE(); 
 #endif 

 #ifdef UBUNTU 
    SpecialCase2ForUBUNTU(); 
 #endif 

    //Common code for all linux 
    ...... 
    ...... 
 } 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p&gt;&lt;a name=&quot;minor3.1&quot;&gt;&lt;span class=&quot;smalltitle&quot;&gt;此方案的优点：&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;遵循了接口平台无关性原则，同样的功能只提供一个接口，每个平台的实现属于实现细节，封装在接口内部。此方案提供了一定的封装性，简化了调用者的操作。&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;minor3.2&quot;&gt;&lt;span class=&quot;smalltitle&quot;&gt;此方案的缺点：&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;预编译宏泛滥的问题仍然没有解决，每次新增功能函数，就会成倍增加预编译宏的数量。同样每次增加对已有功能新平台的支持，也会不断增加预编译宏的数量。&lt;/p&gt;
&lt;p&gt;可见，此方案部分解决了本文开始提出的两个问题中的一个，但仍有问题需要继续解决。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot;&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot;&gt;&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/#ibm-pcon&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;major4&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;解决方案 2： 通过分层对进行优化&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;换一个角度来思考，可以在二进制层面对平台相关代码进行优化。通过对库的结构进行分层来优化，为每个 Linux 平台提供单独的实现库，并且把调用端独立提取出来。如下图所示：&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;fig2&quot;&gt;&lt;strong&gt;图 2： 方案 2 的结构图&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;img alt=&quot;图 2： 方案 2 的结构图&quot; src=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/image002.jpg&quot; width=&quot;557&quot; height=&quot;182&quot;&gt;
&lt;br&gt;
&lt;p&gt;此方案单独将调用端抽象出来，将每个平台实现端的相关代码提取出来做成一个单独的库（Rhel.so，Suse.so，Ubuntu.so）。SpecialCase() 为同一功能在不同平台的实现，采用相同接口名。底层库需要与 Results.so 库同时发布，也就是说，Redhat 版本发布时需同时打包 Results.so 和 Rhel.so，其他版本亦然。&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;minor4.1&quot;&gt;&lt;span class=&quot;smalltitle&quot;&gt;此方案的优点：&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;解决了预编译宏泛滥的问题，通过二进制分层可以将代码里的所有预编译选项去掉。遵循了接口平台无关性的原则。&lt;/p&gt;
&lt;p&gt;可见，此方案很好地解决了本文开始提出的两个问题。&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;minor4.2&quot;&gt;&lt;span class=&quot;smalltitle&quot;&gt;此方案的缺点：&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;每次发布 Results.so 的时候，底层库需要伴随一起发布，导致可执行包文件数量成倍增加。而且很多小程序，小工具的发布往往采取单独的二进制文件，不允许有底层库的存在。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot;&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot;&gt;&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/#ibm-pcon&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;major5&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;解决方案 3： 结合代理模式，桥接模式和单例模式进行优化&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;现在针对原始问题继续进行优化，摈弃方案 2 采用的分层手法，在单一库的范围内利用 C&amp;#43;&amp;#43; 多态特性和设计模式进行优化。&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;minor5.1&quot;&gt;&lt;span class=&quot;smalltitle&quot;&gt;目标效果：&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;源代码中尽可能减少预编译选项出现的频率，避免因功能扩展和平台支持的增加导致预编译宏数量爆炸。 &lt;/li&gt;&lt;li&gt;完全遵循接口平台无关性的原则。 &lt;/li&gt;&lt;/ol&gt;
&lt;br&gt;
&lt;a name=&quot;listing3&quot;&gt;&lt;strong&gt;清单 3. 解决方案 3 调用端示例代码如下：&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot;&gt;
&lt;pre class=&quot;displaycode&quot;&gt;				
 // Procedure.cpp 
 void SomeFunction() 
 { 
    //Common code for all linux 
    ...... 
    ...... 
    XXHost::instance()-&amp;gt;SpecialCase1(); 

    //Common code for all linux 
    ...... 
 ...... 

 XXHost::instance()-&amp;gt;SpecialCase2(); 

    //Common code for all linux 
    ...... 
 ...... 
 } 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a name=&quot;fig3&quot;&gt;&lt;strong&gt;图 3：方案 3 的具体实现类图&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;img alt=&quot;图 3：方案 3 的具体实现类图&quot; src=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/image003.jpg&quot; width=&quot;567&quot; height=&quot;220&quot;&gt;
&lt;br&gt;
&lt;p&gt;此方案结合改进的代理模式（Proxy），桥接模式（Bridge）和单件模式（Singleton），并利用 C&amp;#43;&amp;#43; 封装、继承和多态特性予以实现。&lt;/p&gt;
&lt;p&gt;IHost 是顶层抽象接口类，声明了实现端需要实现的功能函数以及调用端需要调用的接口函数。&lt;/p&gt;
&lt;p&gt;图 3 右半部分派生自 IHost 的各个类为实现端，在实现端，&lt;/p&gt;
&lt;p&gt;为每个 Linux 系统单独实现了一个类，相互之间无关联性。该类实现了该操作系统平台相关的功能（SpecialCase1() 和 SpecialCase2()），即实现了平台相关代码。每个实现类采取单件模式。&lt;/p&gt;
&lt;p&gt;Init() 和 terminate() 用来初始化和清理操作。Init() 函数首先创建自己（单件模式），其次创建左侧代理类（单件模式，见下段描述），最后将自己的内存地址通过 SetHost() 函数交给左侧代理方。&lt;/p&gt;
&lt;p&gt;图 3 左半部分派生自 Host 的各个类为调用端，在调用端，&lt;/p&gt;
&lt;p&gt;Host 类做了一层封装，RhelHost 等派生类为实际的代理者（调用者），每个 Host 的派生类分别代表一种需求（调用方），是右侧实现类的一个代理，例如 RhelHost 是 RhelOS 的代理，SuseHost 是 SuseOS 的代理，UbuntuHost 是 UbuntuOS 的代理。每个 Host 的派生类采取单件模式。&lt;/p&gt;
&lt;p&gt;Host 类和 HostImp 类之间采用桥接的设计模式，利用 C&amp;#43;&amp;#43; 多态特性，最后通过 HostImp 类调用实现端类的实现。调用端的调用过程如下：&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;通过 RhelHost 的指针调用 SpecialCase()，由于 RhelHost::SpecialCase() 没有覆盖基类虚函数的实现，实际调用的是 Host::SpecialCase()。
&lt;/li&gt;&lt;li&gt;Host 的所有调用被桥接到 HostImp 对应的函数。 &lt;/li&gt;&lt;li&gt;由 HostImp 类调用确定的实现端的某一个对象的对应实现函数（HostImp 类的 SetHost() 函数记录了右侧类的对象内存地址）。 &lt;br&gt;
&lt;br&gt;
&lt;a name=&quot;listing4&quot;&gt;&lt;strong&gt;清单 4. 解决方案 3 框架主要源代码如下：&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot;&gt;
&lt;pre class=&quot;displaycodeliquid&quot;&gt;				
 // Host.h 
 class IHost 
 { 
 public: 
    virtual void SpecialCase1() = 0; 
    virtual void SpecialCase2() = 0; 
 }; 

 class Host : public IHost 
 { 
 public: 
    virtual ~Host() {}; 
    void setHost(IHost* pHost) 
    { 
        m_pImp-&amp;gt;setHost(pHost); 
    } 
    virtual void SpecialCase1() 
    { 
        m_pImp-&amp;gt;SpecialCase1(); 
    }; 
    virtual void SpecialCase2() 
    { 
        m_pImp-&amp;gt;SpecialCase2(); 
    }; 

 protected: 
    Host(HostImp * pImp); 

 private: 
    HostImp* m_pImp; 
    friend class HostImp; 
 }; 

 class RhelHost : public Host 
 { 
 public: 
    static RhelHost* instance(); 
 private: 
    RhelHost(HostImp* pImp); 
 }; 

 RhelHost * RhelHost::instance() 
 { 
    static RhelHost * pThis = new RhelHost (new HostImp()); 
    return pThis; 
 } 

 RhelHost:: RhelHost (HostImp* pImp) 
 : Host(pImp) 
 { 
 } 

 class RhelOS : public IHost 
 { 
 public: 
    static void init() 
    { 
        static RhelOS me; 
        RhelHost::instance()-&amp;gt;setHost(&amp;amp;me); 
    } 
    static void term() 
    { 
        RhelHost::instance()-&amp;gt;setHost(NULL); 
    } 
 private: 
    virtual void SpecialCase1() 
    { 
        /* Real Operation */ 
    }; 
    virtual void SpecialCase2() 
    { 
        /* Real Operation */ 
    }; 

 }; 

 // HostImp.h 
 class HostImp : public IHost 
 { 
 private: 
    HostImp(const HostImp&amp;amp;); 

 public: 
    HostImp(); 
    virtual ~HostImp() {}; 
    void setHost(IHost* pHost) 
    { 
        m_pHost = pHost; 
    }; 
    virtual void SpecialCase1() 
    { 
        if(m_pHost != NULL) 
            m_pHost-&amp;gt;SpecialCase1() 
    } 
    virtual void SpecialCase2() 
    { 
        if(m_pHost != NULL) 
            m_pHost-&amp;gt;SpecialCase2() 
    } 

 private: 
    IHost* m_pHost; 
 }; 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;a name=&quot;minor5.2&quot;&gt;&lt;span class=&quot;smalltitle&quot;&gt;此方案的优点：&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;遵循接口平台无关性原则。此方案将各平台通用接口提升到最高的抽象层，易于理解和修改。 &lt;/li&gt;&lt;li&gt;最大限度地降低预编译选项在源代码中的使用，实际上，本例中只需要在一处使用预编译宏，示例代码如下：
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot;&gt;
&lt;pre class=&quot;displaycodeliquid&quot;&gt; void Init() 
 { 
 #ifdef RHEL 
    RhelOS::init(); 
 #endif 

 #ifdef SUSE 
    SuseOS::init(); 
 #endif 

 #ifdef UBUNTU 
    UbuntuOS::init(); 
 #endif 
 } 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p&gt;源代码其他地方不需要添加预编译宏。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;实现端和调用端都通过类的形式进行封装，而且实现端类和调用端类都可以自己单独扩展，完成一些各自需要完成的任务，所要保持一致的只是接口层函数。扩展性和封装性很好。
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;由此可见，此方案很好地解决了本文开始提出的两个问题，而且代码结构清晰，可维护型好。&lt;/p&gt;
&lt;p&gt;接下来对上述源代码继续进行优化。上例 SuseHost/UbuntuHost/SUSEOS/UBUNTUOS 等类的实现被略去，实际上这些类的实现与 RhelHost 和 RHELOS 相&amp;#20284;，可以利用宏来进一步优化框架代码结构。&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;listing5&quot;&gt;&lt;strong&gt;清单 5. 解决方案 3 框架主要源代码优化：&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; summary=&quot;这一表&amp;#26684;包含代码清单。&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot;&gt;
&lt;pre class=&quot;displaycode&quot;&gt;				
 #define HOST_DECLARE(name) \ 
 class ##nameHost : public Host \ 
 { \ 
 public: \ 
    static ##nameHost* instance(); \ 
 private: \ 
    ##nameHost(HostImp* pImp); \ 
 }; 

 #define HOST_DEFINE(name) \ 
 ##nameHost* ##nameHost::instance() \ 
 { \ 
    static ##nameHost* pThis = new ##nameHost(new HostImp()); \ 
    return pThis; \ 
 } \ 
 ##nameHost::##nameHost(HostImp* pImp) \ 
 : Host(pImp) \ 
 { \ 
 } 

 #define HOST_IMPLEMENTATION(name) \ 
 class ##name##OS : public IHost \ 
 { \ 
 public: \ 
    static void init() \ 
    { \ 
        static ##name##OS me; \ 
        ##nameHost::instance()-&amp;gt;setHost(&amp;amp;me); \ 
    } \ 
    static void term() \ 
    { \ 
        ##nameHost::instance()-&amp;gt;setHost(NULL); \ 
    } \ 
 private: \ 
 virtual void SpecialCase1(); \ 
    virtual void SpecialCase2(); \ 
 }; 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
&lt;p&gt;使用三个宏来处理相&amp;#20284;代码。至此，优化完成。从源代码角度来分析，作为实现端的开发人员，只需要三步就可以完成操作：&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;调用 init() 函数； &lt;/li&gt;&lt;li&gt;使用 #define HOST_IMPLEMENTATION(name)；
&lt;p&gt;例如：#define HOST_IMPLEMENTATION(DEBIAN)&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;实现 DEBIAN::SpecialCase1() 和 DEBIAN::SpecialCase2()。
&lt;p&gt;作为调用端的开发人员，也只需要三步就可以完成操作：&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;使用 #define HOST_DECLARE(name) 进行声明；
&lt;p&gt;例如 : #define HOST_DECLARE(DEBIAN)&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;使用 #define HOST_DEFINE(name) 进行定义；
&lt;p&gt;例如： #define HOST_DEFINE (DEBIAN)&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;调用接口。
&lt;p&gt;例如： DEBIANHost::instance()-&amp;gt;SpecialCase1();&lt;/p&gt;
&lt;p&gt;DEBIANHost::instance()-&amp;gt;SpecialCase2();&lt;/p&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;可见，优化后方案的代码清晰，不失为一个良好的平台相关代码的解决方案。&lt;/p&gt;
&lt;p&gt;由于调用端和实现端往往需要传递参数，可以通过 SpecialCase1() 函数的参数来传递参数，同样的这个参数类可以通过桥接的方式予以实现，本文不再详述，读者可以自己尝试。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot;&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot;&gt;&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/#ibm-pcon&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;major6&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;对方案 3 的扩展&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;minor6.1&quot;&gt;&lt;span class=&quot;smalltitle&quot;&gt;扩展 1：对单一操作系统多对多的扩展&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;对于方案 3 的实现，也许有读者会问，调用端只需要 Host 类不需要其派生类即可完成方案 3 中的功能，的确如此，因为方案 3 中的代理类一直是一对一的关系，即 RhelHost 代理 RhelOS，Redhat 下只存在这一对一的关系。但是实际情况下，单一系统下很可能存在多对多的关系。&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;例如，在单一操作系统中，可能需要同时实现多种风&amp;#26684;的窗口。实际上，变成了多对多的代理关系。&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;fig4&quot;&gt;&lt;strong&gt;图 4：单一操作系统不同 c 风&amp;#26684;窗口的实现类图&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;img alt=&quot;图 4：单一操作系统不同 c 风&amp;#26684;窗口的实现类图&quot; src=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/image004.jpg&quot; width=&quot;567&quot; height=&quot;216&quot;&gt;
&lt;br&gt;
&lt;p&gt;Style1Host 代理 Style1Dialog，Style2Host 代理 Style2Dialog，Style3Host 代理 Style3Dialog，三个窗口同时并存，也就是说左侧三个实现类的实例和右侧三个代理类的实例同时存在。可见，方案 3 的设计模式扩展性良好，实现端和调用端都可以在遵循接口不变性的情况下单独扩展自己的功能。&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;minor6.2&quot;&gt;&lt;span class=&quot;smalltitle&quot;&gt;扩展 2：对多操作系统的扩展&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;方案 3 不仅可以针对 Linux 平台相关代码进行处理，还可以扩展到其他诸多场合。例如，现在的程序库往往需要针对多个操作系统，包括 Windows, Linux, Mac。每个操作系统往往使用不同的 GUI 库，这样在实现窗口操作的时候必然涉及到平台相关代码。同样可以用方案 3 予以实现。&lt;/p&gt;
&lt;br&gt;
&lt;a name=&quot;fig5&quot;&gt;&lt;strong&gt;图 5：多操作系统的实现类图&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;img alt=&quot;图 5：多操作系统的实现类图&quot; src=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/image005.jpg&quot; width=&quot;566&quot; height=&quot;214&quot;&gt;
&lt;div class=&quot;ibm-alternate-rule&quot;&gt;
&lt;hr&gt;
&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot;&gt;&lt;a class=&quot;ibm-anchor-up-link&quot; href=&quot;http://www.ibm.com/developerworks/cn/linux/l-cn-cppoverlinux/#ibm-pcon&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;major7&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;总结&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;本文开始提出平台相关代码造成的两个问题，接着循序渐进提出解决方案。在分析了常用的设置预编译选项方法的利弊的基础上，提出了一种新的利用 C&amp;#43;&amp;#43; 多态特性，结合使用代理模式，桥接模式和单件模式处理平台相关代码的方案，并对这一方案予以扩展，给读者提供了一种新的高效的处理平台相关代码的方法。&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;&lt;a name=&quot;resources&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;参考资料 &lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;学习&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;请参考&lt;a&gt;《设计模式 – 可复用面向对象软件的基础》，机械工业出版社&lt;/a&gt;。 &lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li&gt;在 &lt;a href=&quot;http://www.ibm.com/developerworks/cn/linux/&quot;&gt;developerWorks Linux 专区&lt;/a&gt; 寻找为 Linux 开发人员（包括
&lt;a href=&quot;http://www.ibm.com/developerworks/cn/linux/newto/&quot;&gt;Linux 新手入门&lt;/a&gt;）准备的更多参考资料，查阅我们
&lt;a href=&quot;http://www.ibm.com/developerworks/cn/linux/best2009/index.html&quot;&gt;最受欢迎的文章和教程&lt;/a&gt;。
&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li&gt;在 developerWorks 上查阅所有 &lt;a href=&quot;http://www.ibm.com/developerworks/cn/views/linux/libraryview.jsp?search_by=Linux&amp;#43;%E6%8A%80%E5%B7%A7&quot;&gt;
Linux 技巧&lt;/a&gt; 和 &lt;a href=&quot;http://www.ibm.com/developerworks/cn/views/linux/libraryview.jsp?type_by=%E6%95%99%E7%A8%8B&quot;&gt;
Linux 教程&lt;/a&gt;。 &lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li&gt;随时关注 developerWorks &lt;a href=&quot;http://www.ibm.com/developerworks/cn/offers/techbriefings/&quot;&gt;
技术活动&lt;/a&gt;和&lt;a href=&quot;http://www.ibm.com/developerworks/cn/swi/&quot;&gt;网络广播&lt;/a&gt;。 &lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;讨论&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;加入 &lt;a href=&quot;http://www.ibm.com/developerworks/cn/community/&quot;&gt;developerWorks 中文社区&lt;/a&gt;，developerWorks 社区是一个面向全球 IT 专业人员，可以提供博客、书签、wiki、群组、联系、共享和协作等社区功能的专业社交网络社区。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a name=&quot;author&quot;&gt;&lt;span class=&quot;atitle&quot;&gt;关于作者&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;ibm-container ibm-portrait-module ibm-alternate-two&quot;&gt;
&lt;div class=&quot;ibm-container-body&quot;&gt;
&lt;p&gt;&lt;a name=&quot;author1&quot;&gt;&lt;/a&gt;温冠华，资深软件工程师，2010 年 12 月加入 IBM CSTL，Staff Software Engineer，熟悉 C&amp;#43;&amp;#43;、设计模式，对跨平台代码复用有较深刻理解。&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-3-17 11:56:02 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7363820&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：229 评论：0 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7363820#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638053017/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7363820&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Sat, 17 Mar 2012 11:56:02 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7363820</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7363820</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/638053017/1166164</fs:itemid></item><item><title>[转][转] 被误解的 Node.js</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7235362</link><description>&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;作者：&lt;a class=&quot;dwauthor&quot; rel=&quot;#authortip1&quot; href=&quot;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/index.html#author1&quot; title=&quot;&quot; style=&quot;&quot;&gt;王 群锋&lt;/a&gt;&lt;span style=&quot;&quot;&gt;, 软件工程师, IBM&lt;/span&gt;&lt;br&gt;
来源：&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/index.html&quot;&gt;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/index.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;Node.js 被设计用来开发大规模高并发的网络应用，这种网络应用的瓶颈之一是在 I/O 的处理效率上。由于硬件及网络的限制，I/O 的速度往往是固定的，如何在此前提下尽可能处理更多的客户请求，提高 CPU 使用效率，便成了开发人员面临的最大问题。得益于基于事件驱动的编程模型，Node.js 使用单一的 Event loop 线程处理客户请求，将 I/O 操作分派至各异步处理模块，既解决了单线程模式下 I/O 阻塞的问题，又避免了多线程模式下资源分配及抢占的问题。至于使用 JavaScript
 开发服务器端代码，这并不是什么新鲜事物，JavaScript 本来就是一种完备的编程语言，微软的 IIS 服务器很早就支持 JavaScript 在其中运行。本文将重点讲述 Node.js 基于事件的编程模型，并与传统的处理方式进行对比，帮助您更好的理解 Node.js。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;major1&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;网络应用的性能瓶颈&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;网络应用的性能瓶颈之一在于 I/O 处理上，下表来自 Node.js 的作者 Ryan Dahl 为 JSConf 大会所作的&amp;nbsp;&lt;a href=&quot;http://s3.amazonaws.com/four.livejournal/20091117/jsconf.pdf&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;讲演&lt;/a&gt;，对比了在不同介质上进行 I/O 操作所花费的 CPU 时间。您能够清楚的发现，访问磁盘及网络数据所花费的 CPU 时间是访问内存时的数十万倍，而现在的网络应用，却需要大量的访问磁盘及网络，比如数据库查询、访问互联网等。如何提高此时
 CPU 的利用效率，便成了提升网络应用性能的关键。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;major1&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;表 1. 不同介质下 I/O 操作花费对比&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table border=&quot;0&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;ibm-data-table &quot; summary=&quot;不同介质下 I/O 操作花费对比&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
&lt;strong&gt;I/O&lt;/strong&gt;&lt;/th&gt;
&lt;th style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
&lt;strong&gt;CPU Cycle&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
L1-cache&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
L2-cache&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
RAM&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
250&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
Disk&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
41000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
Network&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
240000000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;major2&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;传统的处理方式&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;minor2.1&quot;&gt;&lt;span class=&quot;smalltitle&quot; style=&quot;font-size:1.2em; font-weight:bold&quot;&gt;单线程&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing1&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 1. 单线程下的阻塞式 I/O&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 var result = 
 db.query(&amp;quot;select * from T&amp;quot;); 
 // 使用该查询结果
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;上述代码描述了一个常见的案例，客户端发起一个 I/O 请求，然后等待服务器端返回 I/O 结果，结果返回后再对其进行操作，但这种请求常常需要很长时间（对于服务器的 CPU 处理能力来说）。这一过程中，服务器无法接受新的请求，即阻塞式 I/O。这种处理方式虽然简单，却不实用，尤其是面对大量请求的时候，简直就不可用。这种情景类&amp;#20284;在火车站售票窗口排队买票，如果您在春节期间去北京火车站排队买过票，绝不会认为这是一种好的处理方式。庆幸的是，现在很少有服务器采取这种处理方式。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;minor2.2&quot;&gt;&lt;span class=&quot;smalltitle&quot; style=&quot;font-size:1.2em; font-weight:bold&quot;&gt;多线程&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing2&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 2. 多线程下的阻塞式 I/O&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 var result = 
 db.query(&amp;quot;select * from T&amp;quot;); 
 // 使用该查询结果
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;该方式下，服务器为每个请求分配一个线程，所有任务均在该线程内执行，就像火车站多开了几个卖票窗口，处理效率高了许多。但就如读者看到的那样，在春节期间各个售票窗口前还是人满为患，为什么火车站不再多开一些售票窗口呢？当然是因为成本。线程也一样，服务器每创建一个线程，每个线程大概会占用 2M 的系统内存，而且线程之间的切换也会降低服务器的处理效率，基于成本的考虑，这种处理方式也有一定的局限性。然而，这却不是最主要的，主要的是开发多线程程序非常困难，容易出错。程序员需考虑死锁，数据不一致等问题，多线程的程序极难调试和测试。基本上在程序运行出错的时候，程序员才知道自己的程序有错误。而这种错误的代价往往又是巨大的，那些访问量巨大的电子商务网站时常会曝出价&amp;#26684;错误等导致公司损失的新闻。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;major3&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;事件驱动&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing3&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 3. 基于事件驱动的编程模型&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 db.query(&amp;quot;select..&amp;quot;, function (result) { 
 // 使用该查询结果
 }); 
 // 继续干其他的事
 // ……
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;上述代码的好处是：使用一个线程执行，客户发起 I/O 请求的同时传入一个函数，该函数会在 I/O 结果返回后被自动调用，而且该请求不会阻塞后续操作。就像电话订票，设想你一大早来到办公室，给火车站打个电话，将自己的票务信息，地址告诉对方，然后放下电话，泡杯茶，浏览一下网页，回复一下今天的电子邮件，你完全不用管火车票的事了，如果订到票，火车站会派快递公司按你电话中提到的联系方式送票给你。无疑，这是一种极其理想的处理方式。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;下图说明了这种编程模型，所有请求以及同时传入的回调函数均发送至同一线程，该线程通常叫做 Event loop 线程，该线程负责在 I/O 执行完毕后，将结果返回给回调函数。这里要注意的是 I/O 操作本身并不在该线程内执行，所以不会阻塞后续请求。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;fig1&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;图 1. Event loop&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;img alt=&quot;图 1. Event loop&quot; height=&quot;226&quot; src=&quot;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/image002.png&quot; width=&quot;378&quot; style=&quot;&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;&quot;&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;major4&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;Node.js 简介&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;有了上面对于事件处理编程模型的介绍，Node.js 就很好理解了。Node.js 是采用事件处理编程模型的 JavaScript 平台，它允许程序员开发大规模高并发的网络应用。这个概念并不新鲜，在 Node.js 之前，很多语言都提供了类&amp;#20284;的平台：Python 的 Twisted，Perl 的 AnyEvent，Ruby 的 EventMachine。Node.js 优于其他平台的另一个好处是所有的 I/O 操作都以异步方式实现，让程序员将主要精力放在应用的业务逻辑上。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;major5&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;为什么选用 JavaScript&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;事实上，在实现 Node.js 之初，作者 Ryan Dahl 并没有选择 JavaScript，他尝试过 C、Lua，皆因其欠缺一些高级语言的特性，如闭包、函数式编程，致使程序复杂，难以维护。而 JavaScript 则是支持函数式编程范型的语言，很好地契合了 Node.js 基于事件驱动的编程模型。加之 Google 提供的 V8 引擎，使 JavaScript 语言的执行速度大大提高。最终呈现在我们面前的就成了 Node.js，而不是 Node.c，Node.lua 或其他语言的实现。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;major6&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;一个例子&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;本文将在这里使用 Node.js 实现一个小型的 Web 应用，它将随机为用户显示一条谚语或名人名言，并允许浏览者添加自己喜欢的谚语。用 Node.js 开发 Web 应用非常简单，下面这段一百多行的代码就实现了一个完整的应用。如果您尚未安装好 Node.js，请登录其&amp;nbsp;&lt;a href=&quot;http://nodejs.org/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;官方网站&lt;/a&gt;查看详细安装说明。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing4&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 4. 导入所需要的模块（proverbs.js）&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 // 导入所需模块
 var http = require(&amp;quot;http&amp;quot;); 
 var url = require(&amp;quot;url&amp;quot;); 
 var qs = require('querystring'); 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;首先需要导入该应用所需要的模块，其中 http 模块负责创建 Web 服务器及 HTTP 相关服务，url 模块负责解析 URL 地址，querystring 模块负责处理请求参数。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing5&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 5. 数据存储（proverbs.js）&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 // 这里为了方便使用了全局变量
 var proverbs = [ 
		&amp;quot;The turtle wins the race.&amp;quot;, 
		&amp;quot;God hides in the details.&amp;quot;, 
        &amp;quot;There are two ways to write error-free programs; only the third one works.&amp;quot;, 
        &amp;quot;Perfect practice makes perfect.&amp;quot;
 ]; 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;这里为了方便，使用全局变量&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;proverbs&lt;/code&gt;存储已有谚语，在正式的应用中，应该考虑使用文件或数据库存储。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing6&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 6. 创建 Web 服务器（proverbs.js）&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 // 创建一个 Web 服务器
 http.createServer(onRequest).listen(8888); 
 console.log(&amp;quot;server is running...&amp;quot;); 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;使用 Node.js 开发 Web 应用非常简单，甚至不用配置 Web 服务器，一行代码就创建成功一个 Web 服务器，同时传入一个回调函数，服务器创建成功后，代码并没有阻塞到那里，而是接着往下执行，这就是事件驱动模型的编程风&amp;#26684;，在 Node.js 里将会大量采用这种方式。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing7&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 7. 请求处理函数（proverbs.js）&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 // 请求处理函数
 function onRequest(request, response) { 
	 var pathname = url.parse(request.url).pathname; 
	 console.log(&amp;quot;Reqeust for &amp;quot; &amp;#43; pathname &amp;#43; &amp;quot; received.&amp;quot;); 

 if (pathname === &amp;quot;/&amp;quot; || pathname === &amp;quot;/index&amp;quot; || pathname === &amp;quot;/proverb&amp;quot;) { 
		 getProverb(response); 
	 } else if (pathname === &amp;quot;/add&amp;quot;) { 

		 if (request.method.toLowerCase() == 'post') { 
			 var body = ''; 
			 request.on('data', function(data) { 
				 body &amp;#43;= data; 
			 }); 

			 request.on('end', function() { 

				 var POST = qs.parse(body); 
				 add(POST.text, response); 

			 }); 
		 } else { 
			 addProverb(response); 
		 } 

	 } else { 
		 response.writeHead(404, { 
			&amp;quot;Content-Type&amp;quot; : &amp;quot;text/plain&amp;quot;
		 }); 
		 response.write(&amp;quot;404 Not found&amp;quot;); 
		 response.end(); 
	 } 

 } 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;该函数负责分发请求，将接收到的 URL 根据规则转发至对应的请求处理模块。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing8&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 8. GET 请求（proverbs.js）&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 function getProverb(response) { 
	 var body = '&amp;lt;html&amp;gt;'
			 &amp;#43; '&amp;lt;head&amp;gt;'
			 &amp;#43; '&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; '
			 &amp;#43; 'charset=UTF-8&amp;quot; /&amp;gt;'
			 &amp;#43; '&amp;lt;/head&amp;gt;'
             &amp;#43; '&amp;lt;body style=&amp;quot;font-size: 4em;line-height: 1.2; margin-top: 200;&amp;quot;&amp;gt;'
             &amp;#43; '&amp;lt;blockquote&amp;gt;'&amp;#43; proverbs[Math.floor(Math.random()* proverbs.length)]
                &amp;#43; '&amp;lt;/blockquote&amp;gt;' &amp;#43; '&amp;lt;/body&amp;gt;'
			 &amp;#43; '&amp;lt;/html&amp;gt;'; 

	 response.writeHead(200, { 
		&amp;quot;Content-Type&amp;quot; : &amp;quot;text/html&amp;quot;
	 }); 
	 response.write(body); 
	 response.end(); 

 } 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;该函数负责处理 GET 请求，随机向用户返回一条谚语。细心的读者可能会发现该函数将 HTML，CSS 以及数据混在一起，显然不符合 MVC 的编程模式。Node.js 有很多第三方开发的模块，其中&amp;nbsp;&lt;a href=&quot;http://expressjs.com/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;express&lt;/a&gt;就是一款优秀的 Web 开发框架，有兴趣的读者可以研究一下。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing9&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 9. 用户输入表单（proverbs.js）&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 function addProverb(response) { 
	 var body = '&amp;lt;html&amp;gt;'
			 &amp;#43; '&amp;lt;head&amp;gt;'
			 &amp;#43; '&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; '
			 &amp;#43; 'charset=UTF-8&amp;quot; /&amp;gt;'
			 &amp;#43; '&amp;lt;/head&amp;gt;'
             &amp;#43; '&amp;lt;body style=&amp;quot;font-size: 4em;line-height: 1.2; margin-top: 200;&amp;quot;&amp;gt;'
			 &amp;#43; '&amp;lt;form action=&amp;quot;/add&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;'
			 &amp;#43; '&amp;lt;textarea name=&amp;quot;text&amp;quot; rows=&amp;quot;10&amp;quot; cols=&amp;quot;60&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;p&amp;gt;'
			 &amp;#43; '&amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Submit&amp;quot; 
			    /&amp;gt;' &amp;#43; '&amp;lt;/form&amp;gt;' &amp;#43; '&amp;lt;/body&amp;gt;'
			 &amp;#43; '&amp;lt;/html&amp;gt;'; 

	 response.writeHead(200, { 
		&amp;quot;Content-Type&amp;quot; : &amp;quot;text/html&amp;quot;
	 }); 
	 response.write(body); 
	 response.end(); 

 } 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;该函数返回一个 HTML 表单，允许用户输入自己喜欢的谚语或&amp;#26684;言。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;listing10&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 10. POST 请求（proverbs.js）&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				 
 function add(proverb, response) { 
	 proverbs.push[proverb]; 

	 var body = '&amp;lt;html&amp;gt;'
			 &amp;#43; '&amp;lt;head&amp;gt;'
			 &amp;#43; '&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; '
			 &amp;#43; 'charset=UTF-8&amp;quot; /&amp;gt;'
			 &amp;#43; '&amp;lt;/head&amp;gt;'
             &amp;#43; '&amp;lt;body style=&amp;quot;font-size: 4em;line-height: 1.2; margin-top: 200;&amp;quot;&amp;gt;'
			 &amp;#43; '&amp;lt;blockquote&amp;gt;' &amp;#43; proverb &amp;#43; '&amp;lt;/blockquote&amp;gt;' &amp;#43; '&amp;lt;/body&amp;gt;'
			 &amp;#43; '&amp;lt;/html&amp;gt;'; 

	 response.writeHead(200, { 
		&amp;quot;Content-Type&amp;quot; : &amp;quot;text/html&amp;quot;
	 }); 
	 response.write(body); 
	 response.end(); 

 } 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;该函数负责用户的 POST 请求，将用户输入保存到服务器端，并返回给用户结果。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/1201_wangqf_nodejs/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;major7&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;结束语&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;本文给大家介绍了基于事件的编程模型，这种编程模型正是 Node.js 这项最近流行技术的核心，希望读者能利用 Node.js 的优势，为自己的开发工作带来便利。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;resources&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;参考资料&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;strong&gt;学习&lt;/strong&gt;&lt;/p&gt;
&lt;ul style=&quot;&quot;&gt;
&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
参考&amp;nbsp;&lt;a href=&quot;http://nodejs.org/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;nodejs&lt;/a&gt;官方主页，了解 Node.js。&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;http://nodebeginner.org/index.html&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;The Node Beginner Book&lt;/a&gt;：一个非常好的 Node.js 教程，同时介绍了 JavaScript 中的高级特性。&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;http://debuggable.com/posts/understanding-node-js:4bd98440-45e4-4a9a-8ef7-0f7ecbdd56cb&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;Understanding Node.js&lt;/a&gt;：一篇有助于理解 Node.js 的文章。&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;Understanding the node.js event loop&lt;/a&gt;深入介绍了基于事件驱动的编程模型，并与传统的处理方式进行对比。&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
“&lt;a href=&quot;http://www.ibm.com/developerworks/cn/opensource/os-nodejs/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;Node.js 究竟是什么？&lt;/a&gt;”（developerWorks，2011 年 6 月）：你们中的许多人可能听说过新近出现的 Node.js，也许现在还在猜测它究竟是何物？Michael Abernethy 在本文中简要介绍了 Node 的作用及其当前局限性。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
“&lt;a href=&quot;http://www.ibm.com/developerworks/cn/cloud/library/cl-nodejscloud/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;使用 Node.js 作为完整的云环境开发堆栈&lt;/a&gt;”（developerWorks，2011 年 8 月）：本文探讨 Node.js，这是一个用于 UNIX 类平台上 V8 JavaScript 引擎的事件驱动的 I/O 框架，设计这一框架的目的是为了编写可伸缩的网络程序，如 Web 服务器。本文通过一个完整的例子说明如何在
 Node.js 中构建聊天服务器，分析了这个框架以及围绕它的生态系统（包括云计算产品），并对这个框架进行了总结。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
“&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/1107_chengfu_nodejs/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;使用 node.js 进行服务器端 JavaScript 编程&lt;/a&gt;”（developerWorks，2011 年 7 月）：node.js 是一个可以使用 JavaScript 开发服务器端应用的平台。它依托于 Google V8 JavaScript 引擎，并采用事件 I/O 的架构，可以用来创建高性能服务器。本文详细介绍了
 node.js 的基本知识、模块化的结构、事件驱动的机制以及常用的模块。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
“&lt;a href=&quot;http://www.ibm.com/developerworks/cn/java/j-nodejs/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;面向 Java 开发人员的 Node.js&lt;/a&gt;”（developerWorks，2011 年 12 月）：Node.js 是一种激动人心的开发方式，可替代传统的 Java 并发性，只要有一个开放的心态和一点点 JavaScript 知识，就可以立即开始进行开发。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;developerWorks Web development 专区&lt;/a&gt;：通过专门关于 Web 技术的文章和教程，扩展您在网站开发方面的技能。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;http://www.ibm.com/developerworks/cn/ajax/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;developerWorks Ajax 资源中心&lt;/a&gt;：这是有关 Ajax 编程模型信息的一站式中心，包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web20/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;developerWorks Web 2.0 资源中心&lt;/a&gt;，这是有关 Web 2.0 相关信息的一站式中心，包括大量 Web 2.0 技术文章、教程、下载和相关技术资源。您还可以通过&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web20/newto/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;Web
 2.0 新手入门&lt;/a&gt;&amp;nbsp;栏目，迅速了解 Web 2.0 的相关概念。&lt;br&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;br&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-2-5 20:54:14 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7235362&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：820 评论：0 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7235362#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638053016/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7235362&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Sun, 05 Feb 2012 20:54:14 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7235362</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7235362</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/638053016/1166164</fs:itemid></item><item><title>[转][转] jQuery Mobile 简介</title><link>http://blog.csdn.net/heiyeshuwu/article/details/7235356</link><description>&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;作者：&lt;span style=&quot;font-family:arial,sans-serif&quot;&gt;&lt;a class=&quot;dwauthor&quot; rel=&quot;#authortip1&quot; href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#author1&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;C. Enrique Ortiz&lt;/a&gt;, 开发人员兼作家, About Mobility Weblog&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;来源：&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html&quot;&gt;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N1006C&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;简介&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;jQuery Mobile 是一个用户界面（UI）框架，允许您编写一个有效的移动 web 应用程序用户界面而不必编写任何 JavaScript 代码。在本文中，了解这个框架的特性，包括基本页面、导航工具栏、表单控件和过渡效果。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;要理解本文，您需要：&lt;/p&gt;
&lt;ul style=&quot;&quot;&gt;
&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
HTML 经验&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
理解 JavaScript 基本原理&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
jQuery 基础知识&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;&quot;&gt;您可以从下面的&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#download&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;下载表&lt;/a&gt;&amp;nbsp;下载本文使用的 jQuery 插件源代码。&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#resources&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;参考资料&lt;/a&gt;&amp;nbsp;部分包含
 jQuery、JavaScript、DOM 和 HTML5 等相关信息。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N1008E&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;jQuery Mobile&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;jQuery Mobile 是一个针对触摸体验的 web UI 开发框架，允许您开发跨智能电话和平板电脑工作的移动 web 应用程序。jQuery Mobile 框架构建于 jQuery 内核之上，提供几个功能，包括 HTML 和 XML 文档对象模型（DOM）的操控、处理事件、使用 Ajax 执行服务器通信、以及用于 web 页面的动画和图像效果。这个移动框架本身是独立于 jQuery 内核（缩小或压缩后大约 25KB）的一个额外下载（缩小或压缩后大约 12KB）。与 jQuery
 框架的其余部分一样，jQuery Mobile 是一个免费的、双许可（MIT 和 GPL）库。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;在本文撰写之时，jQuery Mobile 框架处于 Alpha 2 version (v1.0a2)。代码处于草案阶段，可能会更改。但是，现有的框架非常坚固。鉴于在 alpha 发布中就有一个令人印象深刻的组件集可用，jQuery Mobile 有望成为一个优秀的移动 web 应用程序开发框架和工具集。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;jQuery Mobile 的基本特性包括：&lt;/p&gt;
&lt;dl style=&quot;&quot;&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;一般简单性&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;此框架简单易用。页面开发主要使用标记，无需或仅需很少 JavaScript。&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;持续增强和优雅降级&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;尽管 jQuery Mobile 利用最新的 HTML5、CSS3 和 JavaScript，但并非所有移动设备都提供这样的支持。jQuery Mobile 的哲学是同时支持高端和低端设备，比如那些没有 JavaScript 支持的设备，尽量提供最好的体验。&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;jQuery Mobile 在设计时考虑了访问能力，它拥有 Accessible Rich Internet Applications (WAI-ARIA) 支持，以帮助使用辅助技术的残障人士访问 web 页面。&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;小规模&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;jQuery Mobile 框架的整体大小比较小，JavaScript 库 12KB，CSS 6KB，还包括一些图标。&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;主题设置&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;此框架还提供一个主题系统，允许您提供自己的应用程序样式。&lt;/dd&gt;&lt;/dl&gt;
&lt;p style=&quot;&quot;&gt;用于 PhoneGap（使用 web 技术构建独立应用程序，参见&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#resources&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;参考资料&lt;/a&gt;）这样的工具包时，jQuery Mobile 框架有助于简化您的应用程序开发。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N100C5&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;浏览器支持&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;我们在移动设备浏览器支持方面取得了长足的进步，但并非所有移动设备都支持 HTML5、CSS 3 和 JavaScript。这个领域是 jQuery Mobile 的持续增强和优雅降级支持发挥作用的地方。如前所述，jQuery Mobile 同时支持高端和低端设备，比如那些没有 JavaScript 支持的设备 。持续增强（Progressive Enhancement）包含以下核心原则（来源：Wikipedia）：&lt;/p&gt;
&lt;ul style=&quot;&quot;&gt;
&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
所有浏览器都应该能够访问全部基础内容。&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
所有浏览器都应该能够访问全部基础功能。&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
增强的布局由外部链接的 CSS 提供。&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
增强的行为由外部链接的 JavaScript 提供。&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
终端用户浏览器偏好应受到尊重。&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;&quot;&gt;所有基本内容应该（按照设计）在基础设备上进行渲染，而更高级的平台和浏览器将使用额外的、外部链接的 JavaScript 和 CSS 持续增强。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;jQuery Mobile 目前支持以下移动平台：&lt;/p&gt;
&lt;ul style=&quot;&quot;&gt;
&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
Apple® iOS：iPhone、iPod Touch、iPad（所有版本）&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
Android™：所有设备（所有版本）&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
Blackberry® Torch（版本 6）&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
Palm™ WebOS Pre、Pixi&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
Nokia® N900（进程中）&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;&quot;&gt;查看 jQuery Mobile 站点上的支持浏览器列表了解更多信息（参见&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#resources&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;参考资料&lt;/a&gt;）。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N10109&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;UI 组件小结&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;jQuery Mobile 向不同种类的 UI 元素提供健壮的支持。图 1 显示了目前支持的 UI 组件的一个小结。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;fig1&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;图 1. jQuery Mobile UI 元素（至 2010 年 8 月）&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;img alt=&quot;一个页面描绘 jQuery Mobile UI 元素（至 2010 年 8 月），包括按钮、工具栏、列表视图等。&quot; height=&quot;713&quot; src=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/fig01.jpg&quot; width=&quot;580&quot; style=&quot;&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;工具栏、按钮、列表视图、选项卡、弹出菜单、对话框、进度、编辑面板和表单元素均受到支持。您的移动 web 应用程序需要的大部分（如果不是全部的话）UI 元素都已提供。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N10123&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;code style=&quot;font-family:monospace; font-size:1.1em!important; font-weight:bold&quot;&gt;$.mobile&lt;/code&gt;&amp;nbsp;与受支持的方法和事件&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;JavaScript 对象&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;jQuery&lt;/code&gt;&amp;nbsp;还被引用为&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$&lt;/code&gt;。jQuery Mobile 框架使用一些移动插件（包括&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;mobile&lt;/code&gt;&amp;nbsp;或&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile&lt;/code&gt;）扩展
 jQuery 内核，这些插件定义几个事件和方法。表 1 列示了一些由&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile&lt;/code&gt;&amp;nbsp;公开的方法。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;N10143&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;表 1. 由&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile&lt;/code&gt;&amp;nbsp;公开的方法&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table border=&quot;1&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;ibm-data-table&quot; summary=&quot;&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
方法&lt;/th&gt;
&lt;th scope=&quot;col&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
用途&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.changePage&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
以编程方式从一个页面切换到另一个页面。
&lt;p style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em&quot;&gt;
例如，要使用一个幻灯片过渡切换到页面 weblog.php，使用&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.changePage(&amp;quot;weblog.php&amp;quot;, &amp;quot;slide&amp;quot;)&lt;/code&gt;。&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.pageLoading&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
显示或隐藏页面加载消息。
&lt;p style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em&quot;&gt;
例如，要隐藏消息，使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.pageLoading(true)&lt;/code&gt;。&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.silentScroll&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
滚动到一个特殊的 Y 位置，不生成滚动事件。
&lt;p style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em&quot;&gt;
例如，要滚动到 Y 位置 100，使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.silentScroll(100)&lt;/code&gt;。&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.addResolutionBreakpoints&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
jQuery Mobile 已经为&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;min/max&lt;/code&gt;&amp;nbsp;类定义了一些断点。调用这个方法来增加断点。
&lt;p style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em&quot;&gt;
例如，要为 800 像素宽度添加&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;min/max&lt;/code&gt;&amp;nbsp;类，使用&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.addResolutionBreakpoints(800)&lt;/code&gt;。&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.activePage&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
引用当前活动页面。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;您可以使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;bind()&lt;/code&gt;&amp;nbsp;或&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;live()&lt;/code&gt;&amp;nbsp;方法绑定几个事件，比如 jQuery Mobile 初始化、触摸事件、方向更改、滚动事件、页面显示/隐藏事件、页面初始化事件、以及动画事件。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;例如，触摸事件包括&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;tap&lt;/code&gt;、&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;taphold&lt;/code&gt;&amp;nbsp;和各种滑指（swipe）事件。滚动事件包括&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;scrollstart&lt;/code&gt;&amp;nbsp;和&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;scrollstop&lt;/code&gt;。页面事件允许接收通知：页面创建之前，页面创建时，页面显示或隐藏之前，以及页面显示或隐藏之时。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;清单 1 展示了 jQuery Mobile 开始执行时绑定一个特定事件的示例。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;list1&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 1. 绑定到&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;mobileinit&lt;/code&gt;&amp;nbsp;事件&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
$(document).bind(&amp;quot;mobileinit&amp;quot;, function(){
  //apply overrides here
});
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;上面的事件允许您在 jQuery Mobile 启动时覆盖默认&amp;#20540;。可以覆盖几个设置，比如：&lt;/p&gt;
&lt;ul style=&quot;&quot;&gt;
&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;LoadingMessage&lt;/code&gt;&amp;nbsp;— 设置页面加载时显示的默认文本。&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;defaultTransition&lt;/code&gt;&amp;nbsp;— 设置使用 Ajax 的页面更换的默认过渡。&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;&quot;&gt;可以根据需要覆盖更多配置参数。参阅 jQuery Mobile 文档（参见&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#resources&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;参考资料&lt;/a&gt;）或源代码（参见&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#download&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;下载&lt;/a&gt;）了解更多信息。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;您还可以绑定到其他事件，那些事件允许您基于&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;touch&lt;/code&gt;&amp;nbsp;和&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;page&lt;/code&gt;&amp;nbsp;事件创建动态应用程序。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N1020E&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;HTML5&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:1.1em!important; font-weight:bold&quot;&gt;data-*&lt;/code&gt;&amp;nbsp;属性&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;jQuery Mobile 依赖 HTML5&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;data-*&lt;/code&gt;&amp;nbsp;属性来支持各种 UI 元素、过渡和页面结构。不支持它们的浏览器将以静默方式弃用它们。表 2 显示如何使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;data-*&lt;/code&gt;&amp;nbsp;属性创建 UI 元素。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;table2&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;表 2. 用于 UI 元素的&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;data-*&lt;/code&gt;&amp;nbsp;属性&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table border=&quot;1&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;ibm-data-table&quot; summary=&quot;Example of data-* attributes for UI Components&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
元素&lt;/th&gt;
&lt;th scope=&quot;col&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
HTML5 data-* 属性&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
页眉、页脚工具栏&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&amp;lt;div data-role=&amp;quot;header&amp;quot;&amp;gt;&lt;br&gt;
&amp;lt;div data-role=&amp;quot;footer&amp;quot;&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
主体内容&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&amp;lt;div data-role=&amp;quot;content&amp;quot;&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
按钮&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot;&amp;nbsp;&lt;br&gt;
data-icon=&amp;quot;info&amp;quot;&amp;gt;Button&amp;lt;/a&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
已编组按钮&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&amp;lt;div data-role=&amp;quot;controlgroup&amp;quot;&amp;gt;&lt;br&gt;
&amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot;&amp;gt;Yes&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot;&amp;gt;No&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot;&amp;gt;Hell Yeah&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;/div&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
内联按钮&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&amp;lt;div data-inline=&amp;quot;true&amp;quot;&amp;gt;&lt;br&gt;
&amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot;&amp;gt;Foo&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot; data-theme=&amp;quot;b&amp;quot;&amp;gt;Bar&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;/div&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
表单元素（选择菜单）&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&amp;lt;div data-role=&amp;quot;fieldcontain&amp;quot;&amp;gt;&lt;br&gt;
&amp;lt;label for=&amp;quot;select-options&amp;quot; class=&amp;quot;select&amp;quot;&amp;gt;Choose an option:&amp;lt;/label&amp;gt;&lt;br&gt;
&amp;lt;select name=&amp;quot;select-options&amp;quot; id=&amp;quot;select-options&amp;quot;&amp;gt;&lt;br&gt;
&amp;lt;option value=&amp;quot;option1&amp;quot;&amp;gt;Option 1&amp;lt;/option&amp;gt;&lt;br&gt;
&amp;lt;option value=&amp;quot;option2&amp;quot;&amp;gt;Option 2&amp;lt;/option&amp;gt;&lt;br&gt;
&amp;lt;option value=&amp;quot;option2&amp;quot;&amp;gt;Option 3&amp;lt;/option&amp;gt;&lt;br&gt;
&amp;lt;/select&amp;gt;&lt;br&gt;
&amp;lt;/div&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
基本列表视图&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&amp;lt;ul data-role=&amp;quot;listview&amp;quot;&amp;gt;&lt;br&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;index.html&amp;quot;&amp;gt;One&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;index.html&amp;quot;&amp;gt;Two&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br&gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;index.html&amp;quot;&amp;gt;Three&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;br&gt;
&amp;lt;/ul&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
对话框&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&amp;lt;a href=&amp;quot;foo.html&amp;quot; data-rel=&amp;quot;dialog&amp;quot;&amp;gt;Open dialog&amp;lt;/a&amp;gt;&lt;br&gt;
&amp;lt;a href=&amp;quot;dialog.html&amp;quot; data-role=&amp;quot;button&amp;quot; data-inline=&amp;quot;true&amp;quot;&lt;br&gt;
data-rel=&amp;quot;dialog&amp;quot; data-transition=&amp;quot;pop&amp;quot;&amp;gt;Open dialog&amp;lt;/a&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
过渡&lt;/td&gt;
&lt;td style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&amp;lt;a href=&amp;quot;index.html&amp;quot; data-transition=&amp;quot;pop&amp;quot; data-back=&amp;quot;true&amp;quot;&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;jQuery Mobile 文档包含受支持的&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;data-*&lt;/code&gt;&amp;nbsp;语法的完整列表。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N102C5&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;jQuery Mobile 页面结构&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;本节讨论 jQuery Mobile 页面的一般结构。jQuery Mobile 拥有一些页面结构指南。通常，一个页面结构应该拥有以下部分：&lt;/p&gt;
&lt;dl style=&quot;&quot;&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;页面栏&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;通常包含页面标题和 Back 按钮&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;内容&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;您的应用程序的内容&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;页脚栏&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;通常包含导航元素、版权信息、以及需要添加到页脚的任何内容&lt;/dd&gt;&lt;/dl&gt;
&lt;p style=&quot;&quot;&gt;图 2 展示了这些不同的部分的示例。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;fig2&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;图 2. 一个 jQuery Mobile web 应用程序的一般结构&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;img alt=&quot;一个 jQuery Mobile web 应用程序的结构，显示页眉栏、内容部分和页脚栏&quot; height=&quot;488&quot; src=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/fig02.jpg&quot; width=&quot;325&quot; style=&quot;&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;页眉和页脚工具栏支持固定和全屏定位选项。固定位置使工具栏在滚动时保持静态。全屏定位与固定定位基本相同，只是工具栏仅在单击页面时才显示（以便提供一个不刺&amp;#30524;的全屏体验）。本节余下部分将探索一个通用页面结构的 HTML 代码。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;一个 HTML 文档类型本身的定义为&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;!DOCTYPE html&amp;gt;&lt;/code&gt;，这定义一个 HTML5 文档类型。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;HTML 页眉部分加载三个重要的 jQuery Mobile 组件：&lt;/p&gt;
&lt;ul style=&quot;&quot;&gt;
&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
jQuery Core 库 — 核心 jQuery 库&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
jQuery Mobile 库 — jQuery 框架特定于移动的部分&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
jQuery Mobile CSS — 定义核心 jQuery Mobile UI 元素的 CSS，它定义过渡和不同的 UI 小部件，比如滑块和按钮，大量使用 Webkit 变形和动画。&lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot;&quot;&gt;清单 2 显示了 HTML 页面部分。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;list2&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 2. HTML 页眉部分&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
&amp;lt;html&amp;gt; 
    &amp;lt;head&amp;gt; 
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; /&amp;gt; 
        &amp;lt;title&amp;gt;Intro to jQuery Mobile&amp;lt;/title&amp;gt; 
        &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;http://code.jquery.com/mobile
/1.0a2/jquery.mobile-1.0a2.min.css&amp;quot; /&amp;gt; 
        &amp;lt;script src=&amp;quot;http://code.jquery.com/jquery-1.4.4.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
        &amp;lt;script src=&amp;quot;http://code.jquery.com/mobile/1.0a2
/jquery.mobile-1.0a2.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt; 
    &amp;lt;/head&amp;gt; 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;HTML 代码的下一个部分定义页面本身；查看&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;data-role=&amp;quot;page&amp;quot;&lt;/code&gt;&amp;nbsp;属性的使用方法。清单 3 展示了一个示例。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;#list3&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 3. 定义一个页面块&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
    &amp;lt;body&amp;gt; 

        &amp;lt;div data-role=&amp;quot;page&amp;quot; id=&amp;quot;page1&amp;quot;&amp;gt; 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;清单 3 定义了一个页面。&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;id&lt;/code&gt;&amp;nbsp;属性仅当多个本地页面块位于同一个 HTML 文件文档上时才需要，这是定义惟一 ID 的一个最佳实践。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;下面两个代码清单将展示如何定义页面不同的页眉、内容、以及页脚部分。页眉栏通常包含页面标题和 Back 按钮，如清单 4 所示。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;list4&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 4. 页眉栏部分&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
                &amp;lt;div data-role=&amp;quot;header&amp;quot;&amp;gt; 
                &amp;lt;h1&amp;gt;Header Bar&amp;lt;/h1&amp;gt; 
            &amp;lt;/div&amp;gt;&amp;lt;!-- /header --&amp;gt; 
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;在本例中，页眉栏只包含一个 H1 页眉标题文本。页面内容位于页眉下方，如下所示。清单 5 中的示例只显示了一个简单段落，但这是您添加列表、按钮、表单等元素的地方。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;list5&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 5. 页面内容部分&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
            &amp;lt;div data-role=&amp;quot;content&amp;quot;&amp;gt;   
                &amp;lt;p&amp;gt;Content Section&amp;lt;/p&amp;gt;      
            &amp;lt;/div&amp;gt;&amp;lt;!-- /content --&amp;gt;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;页脚栏通常是您放置导航元素和版权信息的地方，如清单 6 所示。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;list6&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 6. 页脚栏部分&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
            &amp;lt;div data-role=&amp;quot;footer&amp;quot;&amp;gt; 
                &amp;lt;h4&amp;gt;Footer Bar&amp;lt;/h4&amp;gt; 
            &amp;lt;/div&amp;gt;&amp;lt;!-- /footer --&amp;gt; 
        &amp;lt;/div&amp;gt;&amp;lt;!-- /page --&amp;gt; 

    &amp;lt;/body&amp;gt; 
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;清单 6 中的页脚部分示例非常简单。向页脚栏添加一个导航栏不太复杂，如清单 7 所示。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;list7&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 7. 向页脚部分添加一个导航栏&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
&amp;lt;div data-role=&amp;quot;footer&amp;quot; class=&amp;quot;ui-bar&amp;quot;&amp;gt;
    &amp;lt;div data-role=&amp;quot;controlgroup&amp;quot; data-type=&amp;quot;horizontal&amp;quot;&amp;gt;
    &amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot;&amp;gt;Today&amp;lt;/a&amp;gt;
    &amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot;&amp;gt;Tomorrow&amp;lt;/a&amp;gt;
    &amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot;&amp;gt;Week&amp;lt;/a&amp;gt;
    &amp;lt;a href=&amp;quot;index.html&amp;quot; data-role=&amp;quot;button&amp;quot;&amp;gt;No date&amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&amp;lt;!-- /footer --&amp;gt;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;图 3 显示生成的页脚栏部分，其中包含新添加的导航栏。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;fig3&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;图 3. 包含导航栏的页脚&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;img alt=&quot;与图 2 类&amp;#20284;的图像，但现在页脚是一个导航栏，其中包含以下按钮：Today、Tomorrow、Week、No date。&quot; height=&quot;486&quot; src=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/fig03.jpg&quot; width=&quot;325&quot; style=&quot;&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;&quot;&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N10377&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;定义多个本地页面&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;前面的示例只涉及一个页面。jQuery Mobile 还支持在一个 HTML 文档中放置多个页面。这些页面是内部链接的本地页面，您可以将它们编为一组，实现预加载目的。多页页面的结构与前面的单页页面示例类&amp;#20284;，只是它将包含多个页面数据角色。清单 8 展示了一个示例。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;list8&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 8. 在单个 HTML 文件中定义多个页面&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
&amp;lt;div data-role=&amp;quot;page&amp;quot; id=page1&amp;quot;&amp;gt;
   &amp;lt;div data-role=&amp;quot;header&amp;quot;&amp;gt;
    :
   &amp;lt;/div&amp;gt;
   &amp;lt;div data-role=&amp;quot;content&amp;quot;&amp;gt;
    :
   &amp;lt;/div&amp;gt;
   &amp;lt;div data-role=&amp;quot;footer&amp;quot;&amp;gt;
    :
   &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
:
:
&amp;lt;div data-role=&amp;quot;page&amp;quot; id=page2&amp;quot;&amp;gt;
   &amp;lt;div data-role=&amp;quot;header&amp;quot;&amp;gt;
    :
   &amp;lt;/div&amp;gt;
   &amp;lt;div data-role=&amp;quot;content&amp;quot;&amp;gt;
    :
   &amp;lt;/div&amp;gt;
   &amp;lt;div data-role=&amp;quot;footer&amp;quot;&amp;gt;
    :
   &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;引用同一个 HTML 文档中的本地页面时，jQuery Mobile 将自动处理那些引用。引用一个外部页面时，jQuery Mobile 将显示一个加载转盘。如果遇到错误，此框架将自动显示并处理一个错误消息弹出窗口。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N1038C&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;页面过渡&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;jQuery Mobile 支持基于 CSS 的页面过渡（受到 jQtouch 的启发），页面过渡在导航到一个新页面和返回上一个页面时应用。这些过渡包括：&lt;/p&gt;
&lt;dl style=&quot;&quot;&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;幻灯片&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;提供一个水平过渡&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;向上滑动和向下滑动&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;提供上下屏幕的过渡&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;弹出&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;提供一个爆炸式过渡类型&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;淡出&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;提供一个淡出过渡&lt;/dd&gt;&lt;dt style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:0px&quot;&gt;
&lt;strong&gt;翻页&lt;/strong&gt;&lt;/dt&gt;&lt;dd style=&quot;font-family:arial,nsimsun,sans-serif&quot;&gt;提供一个翻页过渡&lt;/dd&gt;&lt;/dl&gt;
&lt;p style=&quot;&quot;&gt;可以以两种方式添加页面过渡：&lt;/p&gt;
&lt;ul style=&quot;&quot;&gt;
&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
向链接添加一个数据过渡属性，使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;&amp;lt;a href=&amp;quot;index.html&amp;quot; data-transition=&amp;quot;pop&amp;quot; data-back=&amp;quot;true&amp;quot;&amp;gt;&lt;/code&gt;
&lt;p style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0.3em; padding-right:5px; padding-bottom:0px; font-size:1em&quot;&gt;
在静态页面上使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;data-transition&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
通过编程方式，使用&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;$.mobile.changePage(&amp;quot;pendingtasks.html&amp;quot;, &amp;quot;slideup&amp;quot;);&lt;/code&gt;
&lt;p style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0.3em; padding-right:5px; padding-bottom:0px; font-size:1em&quot;&gt;
处理动态页面时使用编程方法。&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N103D1&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;列表视图&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;列表视图是一种基础 UI 元素类型，广泛应用于移动应用程序。jQuery Mobile 支持大量列表视图：基础、嵌套、编号和只读列表；分割按钮；列表分割器；计数泡泡；缩略图；图标；搜索过滤栏；插入式列表；以及主题列表。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;清单 9 展示了一个基本列表视图。列表视图通过&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;&amp;lt;ul data-role=&amp;quot;listview&amp;quot;&amp;gt;&lt;/code&gt;&amp;nbsp;数据属性创建。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;list9&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 9. 创建一个简单的列表视图&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; /&amp;gt;
        &amp;lt;title&amp;gt;Intro to jQuery Mobile&amp;lt;/title&amp;gt;
        &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;http://code.jquery.com/mobile
/1.0a2/jquery.mobile-1.0a2.min.css&amp;quot; /&amp;gt;
        &amp;lt;script src=&amp;quot;http://code.jquery.com/jquery-1.4.4.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
        &amp;lt;script src=&amp;quot;http://code.jquery.com/mobile/1.0a2
/jquery.mobile-1.0a2.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;

        &amp;lt;div data-role=&amp;quot;page&amp;quot;&amp;gt;

            &amp;lt;div data-role=&amp;quot;header&amp;quot;&amp;gt;
               &amp;lt;h1&amp;gt;Facebook Friends&amp;lt;/h1&amp;gt;
            &amp;lt;/div&amp;gt;&amp;lt;!-- /header --&amp;gt;

            &amp;lt;div data-role=&amp;quot;content&amp;quot;&amp;gt;
               &amp;lt;p&amp;gt;

               &amp;lt;ul data-role=&amp;quot;listview&amp;quot; data-inset=&amp;quot;true&amp;quot;&amp;gt;

                  &amp;lt;li&amp;gt;
                  &amp;lt;a href=&amp;quot;index.html&amp;quot;&amp;gt;Get Friends&amp;lt;/a&amp;gt;
                  &amp;lt;/li&amp;gt;

                  &amp;lt;li&amp;gt;
                  &amp;lt;a href=&amp;quot;index.html&amp;quot;&amp;gt;Post to Wall&amp;lt;/a&amp;gt;
                  &amp;lt;/li&amp;gt;

                  &amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;index.html&amp;quot;&amp;gt;Send Message&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
               &amp;lt;/ul&amp;gt;

               &amp;lt;/p&amp;gt;

            &amp;lt;/div&amp;gt;&amp;lt;!-- /content --&amp;gt;

            &amp;lt;div data-role=&amp;quot;footer&amp;quot;&amp;gt;
            &amp;lt;/div&amp;gt;&amp;lt;!-- /footer --&amp;gt;
        &amp;lt;/div&amp;gt;&amp;lt;!-- /page --&amp;gt;

    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;在&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;&amp;lt;ul data-role=&amp;quot;listview&amp;quot;/&amp;gt;&lt;/code&gt;&amp;nbsp;中，您定义了一些公共&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;&amp;lt;li&amp;gt;&lt;/code&gt;&amp;nbsp;列表项目。这个示例完美地展示了 jQuery Mobile 如何扩展基本 HTML 语法。清单 10 中的代码示例的结果如图
 4 所示。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;fig4&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;图 4. 一个简单的列表视图&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;img alt=&quot;一个简单的列表视图，显示 Facebook 朋友，有 Get friends、Post to wall 和 Send message 三个选项。&quot; height=&quot;489&quot; src=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/fig04.jpg&quot; width=&quot;325&quot; style=&quot;&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;&quot;&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N10403&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;表单&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;表单是另一个常用的 web 工件，用于向服务器提交信息。jQuery Mobile 支持许多表单 UI 组件：文本输入、搜索输入、滑块、翻转切换开关、单选按钮、复选框、选择菜单和主题表单。它们都可以被轻松创建。&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#list10&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;清单 10&lt;/a&gt;&amp;nbsp;显示了一个表单，该表单带有一个选择菜单和一个提交按钮。&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;选择菜单由原生&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;&amp;lt;select name=&amp;quot;select-options&amp;quot; id=&amp;quot;select-options&amp;quot;&amp;gt;&lt;/code&gt;&amp;nbsp;驱动，但 jQuery Mobile 改进了它的 “观感”。&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;&amp;lt;div data-role=&amp;quot;fieldcontain&amp;quot;&amp;gt;&lt;/code&gt;&amp;nbsp;语句组合不同的&amp;#20540;以实现可视化目的。表单本身通过原生&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;&amp;lt;form
 action=&amp;quot;...&amp;quot; method=&amp;quot;get&amp;quot;&amp;gt;&lt;/code&gt;&amp;nbsp;定义。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;list10&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;清单 10. 一个表单、选择菜单和提交按钮&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; summary=&quot;This table contains a code listing.&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;code-outline&quot; style=&quot;font-family:arial,nsimsun,sans-serif; background-color:rgb(247,247,247)!important; border-top-width:1px; border-right-width:1px; border-bottom-width:1px; border-left-width:1px; border-top-style:solid; border-right-style:solid; border-bottom-style:solid; border-left-style:solid; border-top-color:rgb(204,204,204); border-right-color:rgb(204,204,204); border-bottom-color:rgb(204,204,204); border-left-color:rgb(204,204,204); padding-top:2px; padding-right:2px; padding-bottom:5px; padding-left:2px&quot;&gt;
&lt;pre class=&quot;displaycode&quot; style=&quot;width:694px; margin-top:0px; margin-bottom:0px; font-family:'Andale Mono','Lucida Console',Monaco,Liberation,fixed,monospace; font-size:11px; overflow-x:auto; overflow-y:auto; background-color:rgb(247,247,247)!important; color:rgb(0,0,0)&quot;&gt;				
&amp;lt;form action=&amp;quot;forms-results.php&amp;quot; method=&amp;quot;get&amp;quot;&amp;gt; 
    &amp;lt;fieldset&amp;gt; 
        &amp;lt;div data-role=&amp;quot;fieldcontain&amp;quot;&amp;gt;
            &amp;lt;label for=&amp;quot;select-options&amp;quot; class=&amp;quot;select&amp;quot;&amp;gt;Choose 
an option:&amp;lt;/label&amp;gt;
            &amp;lt;select name=&amp;quot;select-options&amp;quot; id=&amp;quot;select-options&amp;quot;&amp;gt;
                &amp;lt;option value=&amp;quot;option1&amp;quot;&amp;gt;Option 1&amp;lt;/option&amp;gt;
                &amp;lt;option value=&amp;quot;option2&amp;quot;&amp;gt;Option 2&amp;lt;/option&amp;gt;
                &amp;lt;option value=&amp;quot;option2&amp;quot;&amp;gt;Option 3&amp;lt;/option&amp;gt;
            &amp;lt;/select&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Submit&amp;lt;/button&amp;gt; 
    &amp;lt;/fieldset&amp;gt; 
&amp;lt;/form&amp;gt;
&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;图 5 展示了表单及其内容。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;a name=&quot;fig5&quot; style=&quot;&quot;&gt;&lt;span style=&quot;padding-top:0.3em; padding-right:5px; padding-bottom:0.7em; padding-left:5px; font-size:0.76em; font-family:arial,sans-serif&quot;&gt;图 5. 带有选择菜单和提交按钮的简单表单&lt;/span&gt;&lt;/a&gt;&lt;br style=&quot;&quot;&gt;
&lt;img alt=&quot;一个简单表单，其中有一个选择菜单，带有选项 1、2 和 3，还有一个提交按钮&quot; height=&quot;333&quot; src=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/fig05.jpg&quot; width=&quot;450&quot; style=&quot;&quot;&gt;&lt;span style=&quot;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;选择选择菜单时，jQuery Mobile 在图像（图 5 中的右边）上显示一个带有所有选项&amp;#20540;的弹出菜单，这个弹出菜单将在选择完成后自动关闭。只要表单的&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;action&lt;/code&gt;&amp;nbsp;和&amp;nbsp;&lt;code style=&quot;font-family:monospace; font-size:small!important&quot;&gt;method&lt;/code&gt;&amp;nbsp;属性适当定义，jQuery
 Mobile 就能负责表单、Ajax 调用和结果页面之间的过渡，并在必要时显示一个转盘。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N10444&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;其他 UI 组件&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;jQuery Mobile 网站和文档中还有更多 UI 元素和元素变体（参见&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#resources&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;参考资料&lt;/a&gt;）&amp;#20540;得您探索。为补充本文的内容，建议您查看以下内容：可折叠内容、布局网&amp;#26684;、主题设置、以及列表视图和表单的剩余部分。&lt;/p&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;N10450&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;结束语&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;本文介绍了可扩展 jQuery Mobile JavaScript 框架。您了解了这个框架的基础知识，以及如何编写一个有效的移动 web 应用程序用户界面而不必编写任何 JavaScript 代码。如果您需要操作 HTML 文档，可以使用 jQuery 内核进行操作。您探索了基本页面和导航、工具栏、表单控件和过渡效果。jQuery Mobile 提供了大量可以以编程方式处理的方法、事件和属性，但愿这能激励您去探索本文没有涵盖的 UI 组件的更多信息。&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;div class=&quot;ibm-alternate-rule&quot; style=&quot;&quot;&gt;&lt;/div&gt;
&lt;p class=&quot;ibm-ind-link ibm-back-to-top&quot; style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jqmobile/index.html#ibm-pcon&quot; class=&quot;ibm-anchor-up-link&quot; style=&quot;color:rgb(153,102,153); display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none; background-color:initial; font-weight:bold&quot;&gt;回页首&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;&lt;a name=&quot;download&quot;&gt;下载&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table width=&quot;100%&quot; summary=&quot;This table contains downloads for this document.&quot; class=&quot;ibm-data-table &quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; style=&quot;&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
描述&lt;/th&gt;
&lt;th scope=&quot;col&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
名字&lt;/th&gt;
&lt;th scope=&quot;col&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
大小&lt;/th&gt;
&lt;th scope=&quot;col&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top; background-color:rgb(247,248,252); text-align:left&quot;&gt;
下载方法&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tb-row&quot; scope=&quot;row&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
本文源代码&lt;/td&gt;
&lt;td nowrap=&quot;nowrap&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
jquerymobileexamplecode.zip&lt;/td&gt;
&lt;td nowrap=&quot;nowrap&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
3KB&lt;/td&gt;
&lt;td nowrap=&quot;nowrap&quot; style=&quot;font-family:arial,nsimsun,sans-serif; border-top-color:rgb(204,204,204); border-top-style:solid; border-top-width:1px; padding-top:8px; padding-right:5px; padding-bottom:8px; padding-left:5px; vertical-align:top&quot;&gt;
&lt;a class=&quot;fbox&quot; href=&quot;http://www.ibm.com/developerworks/apps/download/index.jsp?contentid=791103&amp;amp;filename=jquerymobileexamplecode.zip&amp;amp;method=http&amp;amp;locale=zh_CN&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;HTTP&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;&quot;&gt;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/whichmethod.html&quot; class=&quot;ibm-forward-link&quot; style=&quot;color:rgb(153,102,153); background-color:initial; display:inline; margin-top:0px; margin-right:0px; margin-bottom:0px; margin-left:0px; padding-top:0px; padding-right:0px; padding-bottom:0px; padding-left:18px; text-decoration:none&quot;&gt;关于下载方法的信息&lt;/a&gt;&lt;/p&gt;
&lt;br style=&quot;&quot;&gt;
&lt;p style=&quot;&quot;&gt;&lt;a name=&quot;resources&quot;&gt;&lt;span class=&quot;atitle&quot; style=&quot;font-size:1.5em; font-weight:bold&quot;&gt;参考资料&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;&quot;&gt;&lt;strong&gt;学习&lt;/strong&gt;&lt;/p&gt;
&lt;ul style=&quot;&quot;&gt;
&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
全面了解&amp;nbsp;&lt;a href=&quot;http://jquerymobile.com/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;jQuery Mobile 框架&lt;/a&gt;。&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
探索 jQuery Mobile&amp;nbsp;&lt;a href=&quot;http://jquerymobile.com/demos/1.0a2/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;文档和演示&lt;/a&gt;：文章、APIs 和演示代码。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
访问所有 jQuery&amp;nbsp;&lt;a href=&quot;http://docs.jquery.com/Main_Page&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;文档&lt;/a&gt;。&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;http://jquerymobile.com/gbs/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;Mobile Graded Browser Support&lt;/a&gt;&amp;nbsp;提供一个 jQuery Mobile 支持的浏览器的矩阵。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
“&lt;a href=&quot;http://jqfundamentals.com/book/book.html&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;jQuery Fundamentals&lt;/a&gt;”（Rebecca Murphey，2010 年）提供了 jQuery JavaScript 库的一个综合概览。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;http://docs.jquery.com/Plugins/Authoring&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;jQuery: Plugins/Authoring&lt;/a&gt;&amp;nbsp;展示了如何编写您自己的 jQuery 插件。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;https://developer.mozilla.org/en/JavaScript/Guide&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;JavaScript Guide&lt;/a&gt;&amp;nbsp;介绍了使用 JavaScript 需要知道的知识。&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;https://developer.mozilla.org/en-US/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;Mozilla Developer Network&lt;/a&gt;&amp;nbsp;是面向 web 开发人员的一个不错资源。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
阅读来自 W3C 规范文档的&amp;nbsp;&lt;a href=&quot;http://www.w3.org/TR/DOM-Level-2-Core/introduction.html&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;What is the Document Object Model?&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
JavaScript 教程&amp;nbsp;&lt;a href=&quot;http://www.howtocreate.co.uk/tutorials/javascript/domstructure&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;DOM objects and methods&lt;/a&gt;&amp;nbsp;涵盖了 W3C DOM 的所有属性、集合和方法。&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
获取一个&amp;nbsp;&lt;a href=&quot;http://www.w3.org/WAI/intro/aria&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;WAI-ARIA&lt;/a&gt;（Accessible Rich Internet Applications Suite）概述，ARIA 定义了一种方法，使得残障人士能更轻松地访问 web 内容和 web 应用程序。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/Progressive_enhancement&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;持续增强&lt;/a&gt;&amp;nbsp;是一种 web 设计策略，强调访问能力、语义 HTML 标记、外部样式表和脚本技术。&amp;nbsp;&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
“&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/wa-jsdom/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;JavaScript 和文档对象模型（DOM）&lt;/a&gt;”（developerWorks，2002 年 7 月）检查了 DOM 的 JavaScript 方法，并逐步展示了如何构建一个用户可以添加注释并编辑注释内容的 web 页面。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
教程&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/education/xml/x-udom/index.html&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;理解 DOM&lt;/a&gt;（developerWorks，2007 年 3 月）讲述了一个 DOM 文档的结构。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
阅读 W3C 的&amp;nbsp;&lt;a href=&quot;http://dev.w3.org/html5/spec/Overview.html&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;HTML5 规范&lt;/a&gt;。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
developerWorks 的&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;developerWorks 中国网站 Web 开发专区&lt;/a&gt;&amp;nbsp;专门提供关于各种 Web 解决方案的文章。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
查看&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/web/lp/html5/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;HTML5 专题&lt;/a&gt;，了解更多和 HTML5 相关的知识和动向。&lt;br&gt;
&lt;br&gt;
&lt;/li&gt;&lt;li style=&quot;font-family:arial,nsimsun,sans-serif; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-right:5px; padding-bottom:3px&quot;&gt;
developerWorks&amp;nbsp;&lt;a href=&quot;http://www.ibm.com/developerworks/cn/offers/techbriefings/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;技术活动&lt;/a&gt;和&lt;a href=&quot;http://www.ibm.com/developerworks/cn/swi/&quot; style=&quot;color:rgb(153,102,153)&quot;&gt;网络广播&lt;/a&gt;：随时关注 developerWorks 技术活动和网络广播。&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;
&lt;br&gt;

            &lt;div&gt;
                作者：heiyeshuwu 发表于2012-2-5 20:53:11 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7235356&quot;&gt;原文链接&lt;/a&gt;
            &lt;/div&gt;
            &lt;div&gt;
            阅读：500 评论：0 &lt;a href=&quot;http://blog.csdn.net/heiyeshuwu/article/details/7235356#comments&quot; target=&quot;_blank&quot;&gt;查看评论&lt;/a&gt;
            &lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638053015/heiyeshuwu/csdn.net/s.gif?r=http://blog.csdn.net/heiyeshuwu/article/details/7235356&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</description><pubDate>Sun, 05 Feb 2012 20:53:11 +0800</pubDate><author>heiyeshuwu</author><guid isPermaLink="false">http://blog.csdn.net/heiyeshuwu/article/details/7235356</guid><dc:creator>heiyeshuwu</dc:creator><fs:srclink>http://blog.csdn.net/heiyeshuwu/article/details/7235356</fs:srclink><fs:srcfeed>http://blog.csdn.net/heiyeshuwu/feed.aspx</fs:srcfeed><fs:itemid>csdn.net/heiyeshuwu/~1166182/638053015/1166164</fs:itemid></item></channel></rss>
