淘宝技术这十年.pdf
http://www.100md.com
2020年4月14日
![]() |
| 第1页 |
![]() |
| 第5页 |
![]() |
| 第19页 |
![]() |
| 第27页 |
![]() |
| 第45页 |
![]() |
| 第77页 |
参见附件(4570KB,195页)。
淘宝技术这十年是子柳写的淘宝网站的发展史,主要讲述了淘宝技术的发展以及面临的各种技术和运营问题,作者在淘宝的八年经历,有行业内的八卦,励志和失败的故事等等。

淘宝技术这十年内容
《淘宝技术这十年》内容简介:任何网站的发展都不是一蹴而就的。它在发展过程中会遇到各种各样的问题和业务带来的压力。正是这些问题和压力推动着技术的进步和发展,而技术的发展反过来又会促进业务的更大提升。如今淘宝网的流量排名已是全球前15名、国内前3名,其系统服务器也从一台发展到万台以上。
《淘宝技术这十年》从工程师的角度讲述淘宝这个超大规模互联网系统的成长历程,及其所有主动和被动的技术变革的前因后果。书中有幕后故事、产品经验、架构演进、技术启蒙,也有大牛成长、业内八卦、失败案例、励志故事。《淘宝技术这十年》文风流畅,有技术人员特有的幽默感;内容积极正面,有现场感,全部是作者亲身经历。
作者简介
子柳:本名赵超,2004年加入淘宝网,取花名子柳。历任开发工程师、项目经理、产品经理、测试经 理,2009年随着淘宝系统的大规模重构和人才的迅速扩张,创办了“淘宝技术大学”,培养内外部工 程师众多,人称“校长”。2011年将培训中的内容写成文章发表,遂一发不可收拾,总结了淘宝十年 的技术之路,乃成本书
书籍章节目录
第一部分淘宝技术发展1
引言:光棍节的狂欢
个人网站
LAMP
Oracle/支付宝/肝旺
第二部分淘宝技术发展2
Java时代
脱胎换置
坚若磐石
创造技术
IES
Tair
第三部分淘宝技术发展3
分布式时代
服务化
中间件
HSE
NotifyHSE
TDDL
Session框架
开放平台
第四部分我在淘宝这八年
第一年(2004年一2005年)
第二年(2005年一2006年)
第三年(2006年一2007年)
第四年(2007年一2008年)
第五年(2008年一2009年)
第六年(2009年一2019年)
第七年(2019年一2011年)
第八年(2011年一2012年)
第五部分生P列传
正明——集团核心系统高级研究员
正祥——淘宝高级研究员,OceanBase项目负责人
毕玄——集团核心系统盗深技术专家
放翁——淘宝开放平台项目负责人
作为技术专家
作为孩子父亲
作为美女的老公
业余生活丰富多彩
吴翰清——阿里云集团信息安全中心高级安全专家
云锋—数据平台与产品部资深技术专家
淘宝传奇工程师多隆的程序世界
精彩书评
这是一本好玩的书,从前面两章看,主要是讲故事;从后面两章看,主要是讲人物;从中间几章看,主要是讲技术。我在写作的过程中,把部分章节贴到了博客上,有人看了说励志,有人看了说对技术有帮助,有人看了说对产品有帮助,有人看了说对创业有帮助,有人看了说里面的段子特别逗,现在我也不知道这是人文读物还是技术书了。
其实技术书很容易写成催眠的读物,这本书我一开始就没有当做技术书来写,最早这是我写给自己看的。在2011年底的时候,我突然意识到在淘宝度过了七年的时光,七年说长不长说短不短,回忆起来有些往事历历在目,有些却已开始模糊。为了给自己留点回忆,我就开始记录自己这几年的故事,七年之间发生了很多有趣的事情,越写越多,写着写着我就希望能够挖掘更多的内容了。在当时我担任着“淘宝技术大学”的校长,这给我的写作提供了得天独厚的优势,我可以听不同的人讲淘宝技术所有的事情。于是我就开始凭记忆去写淘宝在过去几年的技术进展,再去找当事人求证内容的细节。然后又由于有些当事人实在太有料了,我干脆把跟他交谈的内容也整理了出来,当做《牛P列传》来呈现给读者(淘宝的技术人员以P级来定义,牛P就是很高级别的专家了)。至此,本书包含了三种行文格式的内容:一个是笔者自己经历的美好时光,一个是淘宝技术这几年的发展历程,一个是那些牛人的牛事。希望能够通过这三个维度,让读者对淘宝的技术有个概括的了解,进而通过淘宝,对互联网的技术有个概览。
书名取《淘宝技术这十年》,口气有点大了,但我很难用一个更确切的名字来概括本书的内容,淘宝在这十年里的技术是很难用一本书来写完的,对于笔者不太熟悉的领域(例如运维、云计算、大数据)没敢着墨太多,书中主要围绕网站的业务和系统架构之间的关系展开论述。我希望能够抛砖引玉,未来有更多的人来写《淘宝运维这十年》、《淘宝数据这十年》……
书写完之后,再回过头来读,我意识到自己经历了一场伟大的变革,这个时代把电子商务推到了一个浪潮之巅,我是这个浪潮中的一滴水珠,我无意描述这场伟大的浪潮,只希望通过一滴水珠映射出浪潮底下的故事。这不是淘宝官方的史书,我不具备这样的高度和视野,这只是一个小人物的所见所想。
这本书不仅仅是给技术人员看的,只要你在互联网的圈子里,从前往后看,我会把互联网技术用大家都能懂的语言来解释,对于非技术人员来说,看过之后也算是做了一次技术启蒙。
淘宝技术这十年截图


淘宝技术这十年
第一部分淘宝技术发展1
引言:光棍节的狂欢
个人网站
LAMP
Oracle支付宝旺旺
第二部分淘宝技术发展2
Java时代
脱胎换骨
坚若磐石
创造技术
TFS
Tair
第三部分淘宝技术发展3
分布式时代
服务化
中间件
HSF
NotifyHSF
TDDL
Session框架
开放平台
第四部分我在淘宝这八年
第一年(2004年—2005年)
第二年(2005年—2006年)
第三年(2006年—2007年)第四年(2007年—2008年)
第五年(2008年—2009年)
第六年(2009年—2010年)
第七年(2010年—2011年)
第八年(2011年—2012年)
第五部分牛P列传
正明——集团核心系统高级研究员
正祥——淘宝高级研究员,OceanBase项目负责人
毕玄——集团核心系统资深技术专家
放翁——淘宝开放平台项目负责人
作为技术专家
作为孩子父亲
作为美女的老公
业余生活丰富多彩
吴翰清——阿里云集团信息安全中心高级安全专家
云铮——数据平台与产品部资深技术专家
淘宝传奇工程师多隆的程序世界第一部分淘宝技术发展1
“所有的进步都是不稳定的,一个问题解决了,我们不得不面对又一个新问
题。”——马丁?路德?金
引言:光棍节的狂欢
“时间到,开抢!”坐在电脑前早已等待多时的小美一看时间已到2011年11月
11日零时,便迫不及待地投身于淘宝商城一年一度的大型网购促销活动——“淘宝
双11购物狂欢节”。小美打开早已收藏好的宝贝——某品牌的雪地靴,飞快的点击
购买、付款,一回头发现3000双靴子已被抢购一空。
小美跳起来,大叫一声“欧耶!”
小美不知道,就在11日零点过后的这一分钟里,全国有342万人和她一起涌入淘
宝商城。当然,她更不知道,此时此刻,在淘宝杭州的一间办公室里,灯火通明,这里是“战时指挥部”,淘宝技术部的一群工程师正紧盯着网站的流量和交易数
据。白板上是他们刚刚下的赌注,赌谁能最准确地猜中流量峰值和全天的交易总
额。他们的手边放着充足的食物和各类提神的饮料。
一阵急促的电话铃声响起,是前线部门询问数据的,工程师大声报着:“第1分
钟,进入淘宝商城的会员有342万人”。过了一会儿,工程师主动拿起电话:“交易
额超过1亿元人民币了,现在是第8分钟。”接下来,“第21分钟,刚突破2亿
元”,“第32分钟,3亿元了”,“第1个小时,4.39亿元”。这些数据随后出现在
微博上,引起了一片惊呼。
“完蛋了!”突然有人大喝一声,所有的眼睛都紧张地盯着他,只见他挠挠
头,嘿嘿地笑道“我赌得少了,20亿元轻松就能过了,我再加5亿元。”他跑到白板
边上把自己的赌注擦去,写上25,接下来有人写上28,有人写上30,有人到微博上
开下盘口,同事们纷纷转载下注。接下来的这24个小时,战时指挥部的工程师们都
不能休息,他们盯着网站的各种监控指标,适时调整机器,增减功能。顶住第一波
高峰之后,这些人开始忙里偷闲地给自己买东西,大家互相交流着哪家买的移动硬
盘靠谱,哪家衣服适合自己的女朋友,不时有人哀嚎宝贝被人抢了、信用卡额度不够了。同时,旁边白板上的赌注越下越大。
11月11日,这个棍子最多的日子被网民自我调侃地变成了一个节日——“光棍
节”,而淘宝网又用疯狂的折扣促销给它赋予了另外一个意义——“购物狂欢
节”。2011年11月11日这一天,淘宝商城与淘宝网交易额之和突破52亿元人民币,这个数字是“购物天堂”香港一天零售总额8.5亿元的6倍。
网民感受到的是疯抢的喜悦,而网站的技术人员感受到的却是“压力山大”。
就如同你家办酒席,宴请左邻右舍,这个办起来容易,倘若宴请十里八乡所有的
人,吃饭的人固然开心,但却不是一般人家能够办得起来的。能办得起来如此盛宴
者,需要强大的财力和物力、组织能力、技术实力(例如做这么多菜,你的炒锅一
定要是“分布式的”、“可复制的”、“可扩展的”,洗菜和切菜要有“工作流引
擎”,跑堂的要计算一下最优路径,甚至连厨房的下水道都要重新设计)。
淘宝能够举办如此盛宴,网站的技术实力可见一斑。至2011年年底,淘宝网拥
有全国最大的Hadoop分布式计算集群之一(2000多个节点,CPU:24000core,Memory:48000GB,Disk:24000块),日新增数据50TB,有40PB海量数据存储,分布在全国各地80多个节点的CDN网络,支撑的流量超过800Gbps。淘宝的搜索引擎
能够对数十亿的商品数据进行实时搜索,另外,还拥有自主研发的文件存储系统和
缓存系统,以及Java中间件和消息中间件系统,这一切组成了一个庞大的电子商务
操作系统。从商业数据上看,Amazon的财报显示2011年完成了大约480亿美元的交
易额,eBay的2011年财报显示全年完成了大约600亿美元的交易额(不包括其独立
的汽车交易平台)。无论从交易额、商品数量还是从同比增速等指标上看,淘宝网
均远超于此,是目前全球最大的电子商务平台。(由于淘宝是非上市公司,未公布
2011年的业绩,以上内容来自淘宝网技术副总裁@_行癫的微博)。
以上这些技术数据可能已经让一些人产生了不适的感觉,为了让更多的人读懂
这本书,我们用下面这段文字描述一下小美访问淘宝网的时候,从技术的角度来
看,网站上发生了什么样的事情。
参考资料来自《你刚才在淘宝上买了一件东西》(来自阿里员工卡特)
你发现快要过年了,于是想给你的女朋友买一件毛衣,你打开了
www.taobao.com,这时你的浏览器首先查询DNS服务器,将www.taobao.com转换
成IP地址。不过你首先会发现,在不同的地区或者不同的网络(电信、联通、移
动)下,转换后的IP地址很可能是不一样的,这首先涉及到负载均衡的第一步,通
过DNS解析域名时,将你的访问分配到不同的入口,同时尽可能保证你所访问的入口
是所有入口中可能较快的一个(这和后文的CDN不一样)。
你通过这个入口成功地访问了www.taobao.com实际的入口IP地址,这时产生了
一个PV(PageView,页面访问量。每日每个网站的总PV量是形容一个网站规模的重
要指标。淘宝网全网在平日(非促销期间)的PV大概是16~25亿个之间)。同时作
为一个独立的用户,你这次访问淘宝网的所有页面均算作一个
UV(UniqueVisitor,用户访问)。最近臭名昭著的12306.cn的日PV量最高峰在10亿个左右,而UV量却远小于淘宝网十余倍,这其中的原因相信大家都知道。
因为同一时刻访问www.taobao.com的人数过于巨大,所以,即便是生成淘宝首
页页面的服务器,也不可能仅有一台,仅用于生成www.taobao.com首页的服务器就
可能有成百上千台,那么你的一次访问时生成页面给你看的任务便会被分配给其中
一台服务器完成。这个过程要保证公正、公平、平均(即这成百上千台服务器每台
负担的用户数要差不多),这一很复杂的过程由几个系统配合完成,其中最关键的
便是LVS(LinuxVirtualServer,世界上最流行的负载均衡系统之一,是由目前在
淘宝网供职的章文嵩博士开发的)。
经过一系列复杂的逻辑运算和数据处理,这次用于给你看的淘宝网首页的HTML
内容便成功生成了。对Web前端稍微有点常识的人都应该知道,浏览器下一步会加载
页面中用到的CSS、JS(JavaScript)、图片等样式、脚本和资源文件。但是可能
相对较少的人才会知道,你的浏览器在同一个域名下并发加载的资源数量是有限
的,例如IE6和IE7是两个,IE8是6个,chrome各版本不大一样,一般是4~6个。
我刚刚看了一下,我访问淘宝网首页需要加载126个资源,那么如此小的并发连接数
自然会加载很久。所以前端开发人员往往会将上述这些资源文件分布在多个域名
下,变相地绕过浏览器的这个限制,同时也为下文的CDN工作做准备。
据不可靠消息称,在2011年“双十一”当天高峰,淘宝的访问流量最巅峰达到
871GBs,这个数字意味着需要178万个4MBs的家庭宽带才能负担得起,也完全有
能力拖垮一个中小城市的全部互联网带宽。显然,这些访问流量不可能集中在一
起,并且大家都知道,不同地区、不同网络(电信、联通等)之间互访会非常缓
慢,但是你却很少发现淘宝网访问缓慢,这便是CDN(ContentDeliveryNetwork,即内容分发网络的作用)。淘宝在全国各地建立了数十个甚至上百个CDN节点,利用
一些手段保证你访问的(这里主要指JS、CSS、图片等)站点是离你最近的CDN节
点,这样便保证了大流量的分散已及在各地访问的加速。
这便出现了一个问题,那就是假若一个卖家发布了一个新的宝贝,上传了几张
新的宝贝图片,那么淘宝网如何保证全国各地的CDN节点中都会同步存在这几张图片
供用户使用呢?这就涉及大量的内容分发与同步的相关技术。另外,淘宝上拥有海
量的宝贝图片等静态文件,这些文件的总容量也达到了数
PB(1PB=1024TB=1048576GB),为了快速存取这些文件,淘宝开发了分布式文件
系统TFS(TaoBaoFileSystem)来处理这类问题。
好了,这时你终于加载完成淘宝首页,然后习惯性地在首页搜索框中输入“毛
衣”二字并按回车键,这时你又产生了一个PV,然后,淘宝网的主搜索系统便开始
为你服务,它首先对你输入的内容基于一个分词库进行分词操作。众所周知,英文
是以词为单位的,词和词之间靠空格隔开,而中文是以字为单位,句子中所有的字
连起来才能描述一个意思。例如,英文句子“Iamastudent”用中文表示,则
为“我是一个学生”。计算机可以很简单地通过空格知道student是一个单词,但
是不太容易明白“学”、“生”两个字合起来才表示一个词。把中文的汉字序列切
分成有意义的词,就是中文分词,有些人也称为切词。“我是一个学生”分词的结
果是“我 是 一个 学生”。
是进行分词操作之后,还需要根据你输入的搜索词进行购物意图分析。用户进
行搜索时常常有如下几类意图。
-浏览型:没有明确的购物对象和意图,边看边买,用户比较随意和感性。
Query注1例如:“2010年10大香水排行”、“2010年流行毛衣”、“zippo有多
少种类?”;
-查询型:有一定的购物意图,体现在对属性的要求上。Query例如:“适合老
人用的手机”、“500元手表”;
-对比型:已经缩小了购物意图,具体到某几个产品。Query例如:“诺基亚
E71E63”、“akgk450px200”;注1Query即查询。为了在数据库或搜索引擎中寻
找某一特定文件、网站、记录或一系列记录,由搜索引擎或数据库送出的信息。
——作者注89第一部分:淘宝技术发展
-确定型:已经做了基本决定,重点考察某个对象。Query例如:“诺基亚N97”、“IBMT60”。通过对你的购物意图的分析,主搜索会呈现出完全不同的结
果。
之后的数个步骤后,主搜索系统便根据上述以及更多复杂的条件列出了搜索结
果,这一切是由一千多台搜索服务器完成的。然后你开始逐一点击浏览搜索出的宝
贝,查看宝贝详情页面。经常网购的亲们会发现,当你买过一个宝贝之后,即便是
商家多次修改了宝贝详情页,你仍然能够通过“已买到的宝贝”查看当时的快照。
这是为了防止商家对在商品详情中承诺过的东西赖账不认。显然,对于每年数十亿
甚至上百亿笔交易的商品详情快照进行保存和快速调用不是一件简单的事情。这其
中又涉及数套系统的共同协作,其中较为重要的是Tair(淘宝自行研发的分布式KV
存储方案)。
接下来,无论你是否真的进行了交易,你的这些访问行为都会如实地被系统记
录下来,用于后续的业务逻辑和数据分析。这些记录中的访问日志记录便是最重要
的记录之一,但是从前面我们得知,这些访问是分布在各个地区多个不同的服务器
上的,并且由于用户众多,这些日志记录都非常庞大,达到TB级别也非常正常。那
么,为了快速、及时、同步地传输这些日志数据,淘宝研发了TimeTunnel,用于进
行实时的数据传输,然后交给后端系统进行计算报表等操作。
你的浏览数据、交易数据以及其他很多数据记录均会被保留下来,使得淘宝存
储的历史数据轻而易举地便达到了数十甚至更多个PB。如此巨大的数据量存储在阿
里巴巴集团的数据仓库中,并且其中有些数据使用了压缩比高达1:120的极限存储技
术。之后这些数据会通过一个叫做云梯的基于Hadoop的由3000多台服务器组成的超
大规模数据系统,以及一个基于阿里巴巴集团自主研发的ODPS系统的数据系统,不
断地进行分析和挖掘。
淘宝从这些数据中能够知道小到你是谁,你喜欢什么,你的孩子几岁了,你是
否在谈恋爱,喜欢玩魔兽世界的人喜欢什么样的饮料等,大到各行各业的零售情况、各类商品的兴衰消亡等海量的信息。
说了这么多,其实也只是叙述了淘宝上正在运行的成千上万个系统中的寥寥几
个。即便是你仅仅访问一次淘宝的首页,所涉及的技术和系统规模都是你完全无法
想象的,是淘宝2000多名顶级的工程师们的心血结晶,其中甚至包括长江学者、国
家科学技术最高奖得主等众多牛人。同样,百度、腾讯等的业务系统也绝不比淘宝
简单。你需要知道的是,你每天使用的互联网产品看似简单易用,背后却凝聚着难
以想象的智慧与劳动。
(本文所涉及的技术与数据均来源于互联网)
为了有一个更直观的对比,我们说一个同行,他在2011年光棍节之前做促销,数据流量达到了12Gbps(他们有这么大的流量,老板很高兴,在微博上公布了这个
数据),这时的流量达到了极限,网站几乎挂掉,用户无法下订单。而淘宝网光棍
节当天网络的流量最高达到800Gbps,带给各家银行和快递公司的流量也让他们如
临大敌(后来,他们以能够撑住淘宝带来的流量为荣而到处宣传)。另外,如果你
在网上购买过火车票,更能体会到网站能支持多大的流量有多重要。但这不是一朝
一夕就能做出来的,也不是有钱就能办到的。
以上对比的这些网站,也许读者很容易就能猜到是哪一家,这里绝对没有嘲笑
他们的意思,采用通常的网站技术方案能做到这种程度已经不错了。任何网站的发
展都不是一蹴而就的,通常是在什么阶段采用什么技术。在发展的过程中,网站会
遇到各种各样的问题,正是这些原因才推动着技术的进步和发展,而技术的发展反
过来又会促进业务的更大提升。二者互为因果,相互促进。如今淘宝网的流量已经
是全球排名第12、国内排名第3(至2011年年底,eBay全球排名第20,国内前两名
是百度和腾讯)。淘宝网的系统也从使用一台服务器,到采用万台以上的服务器。
本书就为大家描述淘宝网在整个发展过程中,所有主动和被动的技术变革的前因后
果,这由很多有趣的故事组成。
正如同很多人或组织成功了以后,就会为自己的出身编造一个美丽的传说。关
于淘宝网的出身,网上也有非常多的传说,下面我们就从它的出生开始讲起。
个人网站
LAMP
2003年4月7日,马云在杭州成立了一个神秘的组织。他叫来十位员工,要他们
签了一份协议,这份协议要求他们立刻离开阿里巴巴集团,去做一个神秘的项目。
这个项目要求绝对保密,老马戏称“连说梦话被老婆听到都不行,谁要是透漏出
去,我将追杀到天涯海角”。这份协议是英文版的,匆忙之间,大多数人根本来不
及看懂,但出于对老马的信任,都卷起铺盖离开了阿里巴巴。
他们去了一个神秘的据点——湖畔花园小区的一套未装修的房子里,房子的主
人是马云。这伙人刚进去的时候,马云给他们布置了一个任务,就是在最短的时间
内做出一个个人对个人(C2C)的商品交易的网站。这里出一个问题考考大家,看你
适不适合做淘宝的创业团队:亲,要是让你来做,你怎么做?
在说出这个答案之前,我们先介绍一下这个创业团队的成员:三个开发工程师
(虚竹、三丰、多隆)、一个UED工程师(二当家)、三个运营工程师(小宝、阿
珂、破天)、一个经理(财神),以及马云和他的秘书。当时对整个项目组来说,压力最大的就是时间,为什么时间这么重要呢?火云邪神先生说过“天下武功无坚
不破,唯快不破”,还有一个原因就是当时eBay和易趣在资本方面正打得不可开
交,我们是趁虚而入的,等他们反应过来就危险了。那怎么在最短的时间内把一个
网站从零开始建立起来呢?了解淘宝历史的人都知道淘宝是在2003年5月10日上线
的,2003年4月7日到5月10日,这之间只有一个月时间。要是你在这个团队里,你
怎么做?不是“抄一个来”,我们的答案是——“买一个来”。
买一个网站显然比做一个网站要省事,但是他们的梦想可不是做一个小网站而
已,要做大,就不是随便买一个就行的,要有比较低的维护成本,要能够方便地扩展和二次开发。那么接下来就是第二个问题:买一个什么样的网站?答案是:轻量
一点的,简单一点的。于是买了这样一个架构的网站:
LAMP(Linux+Apache+MySQL+PHP),这个直到现在还是一个很常用的网站架构模
型,其优点是:无须编译,发布快速,PHP语言功能强大,能做从页面渲染到数据访
问所有的事情,而且用到的技术都是开源、免费的。
当时我们是从一个美国人那里买来的一个网站系统,这个系统的名字叫做
PHPAuction(其官方网站http:www.phpauction.netAuction,即是拍卖的意
思,这个名字很直白,一眼就可看出这个系统是用什么语言做的、用途是什么),PHPAuction有好几个版本,我们买的是最高版的,功能比较多,而且最重要的是对
方提供了源代码。最高版比较贵,花了我们差不多2000美元(貌似现在降价了,只
要946美元,在他们的网站上有明码标价的信息)。买来之后不是直接就能用的,需
要很多本地化的修改,例如,修改一些数据类型,增加后台管理的功能,页面模板
改得漂亮一点,页眉和页脚加上自己的站点简介等。其中最有技术含量的是对数据
库进行了一个修改,原来是从一个数据库进行所有的读写操作,现在把它拆分成一
个主库、两个从库,并且读写分离。这么做的好处有几点:存储容量增加了,有了
备份,使得安全性增加了,读写分离使得读写效率得以提升(写要比读更加消耗资
源,分开后互不干扰)。这样整个系统的架构就如下图所示。
其中,pearDB是一个PHP模块,负责数据访问层。另外,他们也用开源的论坛
系统PHPBB(http:www.phpbbchina.com)搭建了一个小的论坛社区,在当时,论坛几乎是所有网站的标配。虚竹负责机器采购、配置、架设等,三丰和多隆负责
编码,他们把交易系统和论坛系统的用户信息打通,给运营人员开发出后台管理的
功能(Admin系统),把交易类型从只有拍卖这一种增加为拍卖、一口价、求购商
品、海报商品(意思是还没推出的商品,先挂个海报出来,这是快速增加商品数的
一个好方法)四种。(PHPAuction系统里只有拍卖的交易,Auction即拍卖的意
思。@_行癫在微博中提到:今天,eBay所有的交易中,拍卖交易仍然占40%,而在
中国,此种模式在淘宝几乎从一开始就未能占据优势,如今在主流的交易中几乎可
以忽略不计。背后的原因一直令人费解,我大致可以给出其中一种解释,eBay基本
上只在发达国家展开业务,制造业外包后,电子商务的基本群体大多只能表现为零
散的个体间交易。)
在开发过程中,这个项目的代号是BMW(没错!就是宝马的意思)。这个是二当
家提出的建议,二当家特别喜欢宝马,他希望我们的网站也如同宝马一样漂亮、快
速、安全,充满乐趣。二当家现在的座驾就是一辆宝马X5,算是得偿所愿了。在上
线的时候需要给这个网站取个名字,为了不引起eBay的注意,这个名字要撇开与阿
里巴巴的关系,所以“阿里爷爷”、“阿里舅舅”之类的域名是不能用的。这时
候,美女阿珂提供了一个很好听的名字“淘宝”。因为她家里有人热爱收藏古董,经常去市场上淘宝贝,而她本人也非常热爱逛街,享受“淘”的乐趣,她觉得“淘
宝”两个字特别符合网站的定位(阿珂说想到这个名字的时候,脑子里一道闪电劈
过,真的是“灵光一闪”。后来“支付宝”的名字也是阿珂取的)。于是这个大名
就定了下来,淘宝网横空出世了。
在接下来的大半年时间里,这个网站迅速显示出了它的生机。这里有必要提一
下当时的市场环境,非典(SARS)的肆虐使得大家都不敢出门,尤其是去类似商场
等人多的地方。另外,在神州大地上最早出现的C2C网站易趣也正忙得不亦乐乎,2002年3月,eBay以3000万美元收购了易趣公司33%的股份,2003年6月以1.5亿美元收购了易趣公司剩余67%的股份。当时,淘宝网允许买卖双方留下联系方式,允许
同城交易,整个操作过程简单轻松。而eBay是收费的,为了收取交易佣金,eBay禁
止买卖双方这么做,这必然增加了交易过程的难度。而且eBay为了全球统一,把易
趣原来的系统替换成了美国eBay的系统,用户体验一下全变了,操作起来非常麻
烦,很多易趣的卖家在那边都混不下去了,这等于是把积累的用户拱手送给了淘
宝。为了不引起eBay的注意,淘宝网在2003年里一直声称自己是一个“个人网
站”。由于这个创业团队强大的市场开拓和运营能力,淘宝网的发展非常迅猛,2003年年底就吸引了注册用户23万个,每日31万个PV,从2003年5月到同年年底成
交额达3371万元。这没有引起eBay的注意,却引起了阿里巴巴内部很多员工的注
意,他们觉得这个网站以后会成为阿里巴巴强劲的对手,甚至有人在内网发帖,忠
告管理层要警惕这个刚刚起步的网站,但管理层似乎无动于衷。(这个团队的保密
工作做得真好!)
在市场和运营的后方,淘宝网的技术团队也在快速地做着系统的改进和创新。
这里还有一个有趣的故事,eBay和易趣早期都有员工在论坛上响应用户的需求,eBay的论坛用粉红色背景来区分员工的发言,易趣的员工在论坛上的昵称都选各种
豆豆,例如“黄豆豆”、“蚕豆豆”、“黑眼豆豆”等。淘宝在讨论运营策略的时
候提到这个问题,老马也要求所有的员工都去论坛上回答用户的问题。最早回答问
题的任务落在小宝头上,我们用什么名字好呢?“淘淘”、“宝宝”、“淘宝
宝”、“宝宝淘”?小宝都不满意,认为太女性化了,辱没了他堂堂一个七尺汉
子。讨论了很久之后,小宝灵光乍现,干脆取个名字叫“小宝”吧,小宝带七个老
婆来开店,迎接各位客官,很有故事性和现场感。于是接下来很多武侠小说中的人
物开始在淘宝论坛中行侠仗义,这些昵称下面标志着“淘宝店小二”,他们回答着
各种各样的问题,快速响应着用户的各种需求。如果是技术上能解决的,几个人商
量一下,马上就开发、测试、发布上线。公司给这几个人租了房子,他们合住在湖
畔花园旁边的小区里(男女分开),每天睁开眼就去公司,半夜两三点收工睡觉,响应用户的需求非常快。反过来对比一下,易趣被eBay收购之后,系统更换成了全
球通用的版本,响应用户的一个需求需要层层审批,据说,买个办公桌都要走两个
月流程,反应速度自然慢了下来。
当时淘宝第一个版本的系统中已经包含了商品发布、管理、搜索、商品详情、出价购买、评价投诉、我的淘宝等功能(现在主流程中也是这些模块。在2003年10
月增加了一个功能节点:“安全交易”,这是支付宝的雏形)。随着用户需求和流
量的不断增长,系统做了很多日常改进,服务器由最初的一台变成了三台,一台负
责发送Email、一台负责运行数据库、一台负责运行WebApp。一段时间之后,商品
搜索的功能占用数据库资源太大了(用like搜索的,很慢),2003年7月,多隆又
把阿里巴巴中文站的搜索引擎iSearch搬了过来。
如此快节奏的工作,其实大家都累得不轻,有人就提议大家随时随地锻炼身
体,可是当时SARS横行,在一个一百多平方米的房子里,怎么锻炼呢?高挑美女阿
珂提议大家练习提臀操,这样有助于保持身材,这个建议遭到男士的一致反对,后
来虚竹就教大家练习倒立,这个大家都能接受。于是这个倒立的传统一直延续至
今,与花名文化、武侠文化一并传承了下来。
随着访问量和数据量的飞速上涨,问题很快就出来了,第一个问题出现在数据
库上。MySQL当时是第4版的,我们用的是默认的存储引擎MyISAM,这种存储引擎在
写数据的时候会把表锁住。当Master同步数据到Slave的时候,会引起Slave写,这
样在Slave的读操作都要等待。还有一点是会发生Slave上的主键冲突,经常会导致
同步停止,这样,你发布的一些东西明明已经成功了,但就是查询不到。另外,当
年的MySQL不比如今的MySQL,在数据的容量和安全性方面也有很多先天的不足(和
Oracle相比)。
Oracle支付宝旺旺
讲到这里,顺便先辟个谣,网上有很多这样骗转发的励志段子:“1998年,马
化腾等一伙人凑了50万元创办了腾讯,没买房;1998年,史玉柱借了50万元搞脑白
金,没买房;1999年,丁磊用50万元创办了163.com,没买房;1999年,陈天桥炒
股赚了50万元,创办盛大,没买房;1999年,马云等18人凑了50万元注册了阿里巴
巴,没买房。如果当年他们用这50万元买了房,现在估计还在还着银行的贷款
吧。”事实上,阿里巴巴和淘宝网都是在马云自己的房子里创办的,阿里巴巴是
1999年初发布上线的。所以,关于马云买房子的事情,真相是这样的。
淘宝网作为个人网站发展的时间其实并不长,由于它太引人注目了,马云在
2003年7月就宣布这个是阿里巴巴旗下的网站,随后在市场上展开了很成功的推广运
作。最著名的就是利用中小网站来做广告,突围eBay在门户网站上对淘宝的广告封
锁。这时候,eBay终于看到淘宝网这个后起之秀了,他对竞争者的态度就是“封杀
他”。eBay买断了新浪、搜狐、网易的电子商务类型的广告,签署了排他性协议,切断了淘宝在这上面做广告的路子。大路不通,我们就独辟蹊径,上网比较早的人
应该还记得那些在右下角的弹窗和网站腰封上一闪一闪的广告,“淘宝网”几个字
总是如影随形地出现在任何中小型网站上。市场部那位到处花钱买广告的家伙太能
花钱了,一出手就是几百万元,他被我们称为“大少爷”。
“大少爷”们做的广告,带来的就是迅速上涨的流量和交易量。在2003年年
底,MySQL已经撑不住了,技术的替代方案非常简单,就是换成Oracle。换为
Oracle的原因除了它容量大、稳定、安全、性能高之外,还有人才方面的原因。在
2003年的时候,阿里巴巴已经有一支很强大的DBA团队了,有鲁国良、冯春培、汪
海(七公)这样的人物,后来还有冯大辉(@fenng)、陈吉平(拖雷)。这样的人
物牛到什么程度呢?Oracle给全球的技术专家颁发一些头衔,其中最高级别的叫
ACE(就是扑克牌的“尖儿”,够大的吧),被授予这个头衔的人目前全球也只有
300多名(公布名单的网址为:http:apex.oracle.complsotnf?
p=19297:3),当年全球只有十几名,而阿里巴巴就有4名。有如此强大的技术后
盾,把MySQL换成Oracle是顺理成章的事情。
但更换数据库不是只换个库就可以的,其访问方式和SQL语法都要跟着变,最重
要的一点是,Oracle的性能和并发访问能力之所以如此强大,有一个关键性的设计
——连接池,连接池中放的是长连接,是进程级别的,在创建进程的时候,它就要
独占一部分内存空间。也就是说,这些连接数在固定内存的OracleServer上是有限
的,任何一个请求只需要从连接池中取得一个连接即可,用完后释放,这不需要频
繁地创建和断开连接,而连接的创建和断开的开销是非常大的。但对于PHP语言来
说,它对数据库的访问都是很直接的,每一个请求都要一个连接。如果是长连接,应用服务器增多时,连接数就多了,就会把数据库拖挂,如果是短连接,频繁地连接后再断开,性能会非常差(而Java语言有很多现成的连接池)。那如何是好呢?
我们打探到eBay用了一个连接池的工具,是BEA卖给他们的。我们知道,BEA的东西
都很贵,我们买不起,就放弃了找BEA的念头,于是多隆在网上寻寻觅觅,找到一个
开源的连接池代理服务SQLRelay(http:sqlrelay.sourceforge.net),这个
东西能够提供连接池的功能,多隆对它进行了一些功能改进之后,系统的架构就变
成了如下形式。
数据一开始是放在本地的,七公带领的DBA们对Oracle做调优的工作,也对SQL
进行调优。后来数据量变大后,本地存储无法满足了,买了
NAS(NetworkAttached储),Storage,网络附属存
NetApp(NetworkAppliance,美国网域存储技术有限公司)的NAS作为数据库的存
储设备,加上OracleRAC(RealApplicationClusters,实时应用集群)来实现负
载均衡。七公说这实际上是走了一段弯路,NAS的NFS(NetworkFileSystem)协议传输的延迟很严重,但那时侯不懂。后来采购了Dell和EMC合作的SAN低端存储,性
能一下提升了十几倍,这才比较稳定了。再后来,数据量更大了,存储的节点一拆
二、二拆四,RAC又出问题了,这才踏上了购买小型机的道路。在那段不稳定的时间
里,七公曾经在机房住了5天5夜,差点被辐射成蜘蛛侠。
替换完数据库后,时间到了2004年春天,俗话说“春宵一刻值千金”,但这些
人的春宵却不太好过,他们在把数据的连接放在SQLRelay之后就噩梦不断,这个代
理服务经常会死锁,如同之前的MySQL死锁一样。虽然多隆做了很多修改,但当时那
个版本内部处理的逻辑不对,问题很多,最快的解决办法就是“重启”它的服务。
这在白天还好,只要连接上机房的服务器,把进程杀掉,然后开启就可以了。但是
最痛苦的是它在晚上也要死掉,于是工程师们不得不24小时开着手机,一旦收
到“SQLRelay进程挂起”的短信,就从春梦中醒来,打开电脑,连上机房的网络,重启服务,后来干脆每天睡觉之前先重启一下。做这事最多的据说是三丰,他现在
是淘宝网的总裁。现在我们知道,任何牛B的人物,都有一段苦B的经历。
微博上有人说“好的架构是进化来的,不是设计来的”。的确如此,其实还可
以再加上一句“好的功能也是进化来的,不是设计来的”。在架构的进化过程中,业务的进化也非常迅猛。最早的时候,买家打钱给卖家都是通过银行转账汇款,有
些骗子收了钱却不发货,干脆逃之夭夭。这是一个很严重的问题,一个人这么干了
之后,很快就有更多的人学会了(这就是传说中的“病毒传播”)。然而魔高一
尺,道高一丈,淘宝网这伙人开始研究防骗子的解决方案,他们看了PayPal的支付
方式,发现不能解决问题。研究了类似QQ币的东西,想弄个“淘宝币”出来,发现
也不行。后来这几个聪明的脑袋把这些想法糅合起来,突然想到了“担保交易”这
种第三方托管资金的办法。于是在2003年10月,淘宝网上线了一个功能,叫做“安
全交易”,卖家如果选择支持这种功能,买家就会把钱交给淘宝网,等他收到货之
后,淘宝网再把钱给卖家,这就是现在的“支付宝”。这个功能最早是让卖家可选
的,因为这会延迟他收款的周期。但一旦卖家用了这个之后,就发现交易量猛增,一年之后,几乎所有的卖家都选择担保交易,到后来干脆所有的交易都必须走担保
交易。在2012年支付宝的年会上,支付宝公布2011年的交易笔数已经是PayPal的两
倍。这个划时代的创新,其实就是在不断思索过程中的一个灵光乍现。
当时开发“安全交易”功能的是茅十八和他的徒弟苗人凤(茅十八开发到一半
去上海读MBA了,苗人凤现在是支付宝的首席业务架构师),开发与银行网关对接功
能的是多隆。当时多数银行的网站已经支持在线支付了,但多隆告诉我,他们的网
关五花八门,用什么技术的都有,我们必须一家一家地去接。而且银行的网关不保
证用户付钱后就一定能扣款成功,不保证扣款成功后就一定通知淘宝,也不保证通
知淘宝后就一定能通知到,以及不保证通知到了就不重复通知。这害苦了苗人凤,他必须每天手工核对账单,少一分钱都睡不着觉,因为对不齐账就一定是有人的钱
找不到地方了,这可是天大的问题。另外,他为了测试这些功能,去杭州所有的银
行都办理了一张银行卡。一大堆银行卡摆在桌子上,不知道的人还以为他一定很有
钱(高富帅啊),其实里面都只是十元八元的。现在我们再一次知道,任何牛B的人
物,都必须有一段苦B的经历。
有人说淘宝打败易趣(eBay中国)是靠免费,其实这只是原因之一。如果说和
易趣过招的第一招是免费,这让用户无须成本就能进来,那么第二招就是“安全支
付”,这让用户放心付款,不必担心被骗。在武侠小说中,真正的高手飞花摘叶即
可伤人,他们不会局限于一两招,一旦出手,则连绵不绝。而淘宝的第三招就
是“旺旺”。其实淘宝旺旺也不是自己生出来的,是从阿里巴巴的“贸易通”复制
过来的。从2004年3月开始,“叮咚!叮咚!”这个经典的声音就回荡在所有淘宝买
家和卖家的耳边,“亲,包邮不?”“亲,便宜5毛行不?”这亲切的砍价声造就了
后来的“淘宝体”。有人说中国人就是爱砍价,虽然笔者体会不到砍价成功后有多
少成就感,但每次我去菜市场,看到大妈们砍价砍得天昏地暗,那满足的劲头堪比
捡到了钱,我就深刻地理解了淘宝旺旺在交易过程中的价值。我猜eBay也体会不到
砍价的乐趣,他们一直不允许买卖双方在线聊天,收购了Skype之后也没有用到电子
商务中去。
旺旺在推出没多久,就惹了一个法律方面的麻烦。有个做雪饼的厂家找上门
来,说我们侵权了,他们家的雪饼很好吃,牛奶也做得不错,我们都很喜欢。然后
我们就在旺旺的前面加了两个字,叫做“淘宝旺旺”。最早做旺旺开发的人只有一
个——无崖子,我们叫他“旺旺之父”,为了支持他的工作,我们工作用的IM工具仅限于旺旺,旺旺在线数上新高之后,他请我们吃鸭脖子。有时候为了吃到鸭脖
子,我们盯着在线数看,快到整数量的时候,自己赶紧去挂几个小号上去。还有一
个很卡哇伊的设计师MM——奇灵,开发出了一套旺旺表情,这套表情比所有的聊天
软件的表情都大,也更加生动,一直沿用到现在,我们叫奇灵为“旺旺之母”。
在那个野蛮生长的阶段,其实很多产品都是想到什么就做什么,例如,我们还
搭建过一个聊天室,但似乎淘宝网不是一个闲聊的地方,这个聊天室门可罗雀,一
段时间后就关闭掉了。
SQLRelay的问题搞得三丰等人很难睡个囫囵觉,那一年开半年会的时候,公司
特地给三丰颁了一个奖项,对他表示深切的安慰。但不能总这样通过不断地重启来
保证系统的稳定性。于是,2004年上半年开始,整个网站就开始了一个脱胎换骨的
手术。
第二部分淘宝技术发展2
所有的进步都是不稳定的,一个问题解决了,我们不得不面对又一个新问
题。”——马丁?路德?金Java时代
脱胎换骨
我的师父黄裳曾经说过“好的架构图充满美感”。一个架构好不好,从审美的
角度就能看出来。后来我看了很多系统的架构,发现这个言论基本成立。反观淘宝
以前两个版本的架构,如下图所示,你看哪个比较美?
显然,第一个比较好看,第二个显得头重脚轻,这也注定了它不是一个稳定的
版本,只存活了不到半年的时间。2004年初,SQLRelay的问题解决不了,数据库必
须要用Oracle,那么从哪里动刀呢?只有换开发语言了。换什么语言好?用Java。
Java是当时最成熟的网站开发语言,它有比较良好的企业开发框架,被世界上主流
的大规模网站普遍采用。另外,有Java开发经验的人才也比较多,后续维护成本会
比较低。
到2004年上半年,淘宝网已经运行了一年的时间,这一年积累了大量的用户,也快速开发了很多功能,当时这个网站已经很庞大了,而且新的需求还在源源不断
地增加。把一个庞大的网站的开发语言换掉,无异于脱胎换骨,在换的过程中还不
能拖慢业务的发展,这无异于边换边跑,对时间和技术能力的要求都非常高。做这
样的手术,需要请第一流的专家来主刀。现在再考一下大家:亲,如果你在这个创
业团队中,请什么样的人来做这
件事?我们的答案是请Sun公司的人。没错,就是创造Java语言的那家公司,世界上没有比他们更懂Java的了。除此之外,还有一个不为人知的原因,我刚才说
到Java被世界上主流的大规模网站普遍采用,其中有一个网站就是eBay,那时侯
eBay的系统刚刚从C++改到Java,而且就是请Sun的工程师给改造成Java架构的,这下你懂了吧?他们不仅更懂Java,而且更懂eBay。
Sun公司的这帮工程师的确很强大,在笔者2004年年底来淘宝的时候,他们还
在,我有幸与他们共事了几个月。现在摆在他们面前的问题是用什么办法把一个庞
大的网站从PHP语言迁移到Java?而且要求在迁移的过程中,不停止服务,原来系
统的bugfix和功能改进不受影响。亲,你要是架构师,你怎么做?有人的答案是写
一个翻译器,如同把中文翻译成英文一样,自动翻译。我只能说你这个想法太超前
了,“tooyoung,toosimple,sometimesnaive”。当时没有,现在也没有人能做到。他们的大致方案是给业务分模块,一个模块一个模块地渐进式替换。如用户模
块,老的member.taobao.com继续维护,不添加新功能,新功能在新的模块上开
发,跟老的模块共用一个数据库,开发完毕之后放到不同的应用集群上,另开一个
域名member1.taobao.com,同时再替换老的功能,替换一个,就把老的模块上的
功能关闭一个,逐渐把用户引导到member1.taobao.com,等所有的功能都替换完
之后,关闭member.taobao.com上。从设计上来看,这个member1的二级域名应该
是一个过渡状态,但我们把member域名的代码下线以后,发现很难把member1切换
回member,因为有些地方把链接写死了,于是后来很长时间里我们都是在用
member1.taobao.com这样奇怪的域名。一年后,有另外一家互联网公司开始做电
子商务了,我们发现他们的域名也叫member1.xx.com、auction1.xx.com,复制
得毫无保留,我们只能会心一笑。
说了开发模式,再说说用到的JavaMVC框架,当时的struts1.x是用得比较多的
框架,但是用过webwork和struts2的人可能知道,struts1.x在多人协作方面有很
多致命的弱点,由于没有一个轻量框架作为基础,因此,很难扩展,这样架构师对
于基础功能和全局功能的控制就很难做到。而阿里巴巴的18个创始人之中,有个架
构师周悦虹,他在JakartaTurbine的基础上做了很多扩展,打造了一个阿里巴巴自
己用的MVC框架
WebX(http:www.openwebx.orgdocsWebx3_Guide_Book.html),这个框架
易于扩展,方便组件化开发,它的页面模板支持JSP和Velocity等,持久层支持
ibatis和hibernate等,控制层可以用EJB和Spring(Spring是后来才有的)。项
目组选择了这个强大的框架。另外,当时Sun在全世界大力推广他们的EJB,虽然淘
宝的架构师认为这个东西用不到,但他们还是极力坚持。在经历了很多次的技术讨
论、争论甚至争吵之后,这个系统的架构就变成了下图的形式。
MVC框架是阿里的WebX,控制层用了EJB,持久层是ibatis。另外,为了缓解数
据库的压力,商品查询和店铺查询放在搜索引擎中。这个架构图是不是好看了一点
了?
Sun的这帮工程师开发完淘宝的网站之后,用同样的架构又做了一个很牛的网
站,叫“支付宝”。(上一篇说过支付宝最初是淘宝上的“安全交易”功能,这个
功能后来独立出来,成立了一个网站,也成立了一个公司,就是现在的支付宝。把
支付宝从淘宝分出去的人,就是Sun公司的这几个人。)下图是支付宝的第一次员工
大会。
上面的架构中,引入了搜索引擎iSearch(前文说过,iSearch其实是在LAMP
系统运行一段时间之后被多隆引进的,换为Oracle之后只是替换一下数据源)。其
实这个搜索引擎的原理很简单,就是把数据库里的数据dump(倾倒)成结构化的文
本文件后,放在硬盘上,提供Web应用以约定的参数和语法来查询这些数据。这看起
来不难,难的是数以亿计的信息,怎么做到快速更新呢?这好比你做了一个网站,在百度上很快就能搜到,你一定很满意了。但如果你发布一件商品,在淘宝上过1个
小时还搜不到,你肯定要郁闷了。另一个难点是如何保证非常高的容量和并发量?
再往后面就要考虑断句和语义分析的问题,以及推荐算法等更加智能的问题。这些
内容先不详细介绍,因为搜索引擎的技术已经足以写好几本书了。
其实在任何时候,开发语言本身都不是系统的瓶颈,业务带来的压力更多的存
在于数据和存储方面。前面也说到,MySQL撑不住之后换为Oracle,Oracle的存储
一开始在本机上,后来在NAS上,NAS撑不住了用EMC的SAN存储,再后来,Oracle
的RAC撑不住了,数据的存储方面就不得不考虑使用小型机。在2004年夏天,DBA七
公、测试工程师郭芙和架构师行癫,踏上了去北京测试小型机的道路。他们带着小型机回来的时候,我们像欢迎领袖一样欢迎他们,因为那是我们最值钱的设备,价
格表上的数字吓死人。小型机买回来之后,我们争相合影,然后Oracle就运行在了
小型机上,存储方面,从EMC低端CX存储到Sunoemhds高端存储,再到EMCdmx高端
存储,一级一级地往上跳。
到2004年底,淘宝网已经有4百多万种商品了,日均4千多万个PV,注册会员达
400万个,全网成交额达10亿元。
到现在为止,我们已经用上了IBM的小型机、Oracle的数据库、EMC的存储,这
些东西都是很贵的,那些年可以说是花钱如流水。有人说过“钱能解决的问题,就
不是问题”,但随着淘宝网的发展,在不久以后,钱已经解决不了我们的问题了。
花钱买豪华的配置,也许能支持1亿个PV的网站,但淘宝网的发展实在是太快了,到
了10亿个PV怎么办?到了百亿怎么办?在几年以后,我们不得不创造技术,解决这
些只有世界顶尖的网站才会遇到的问题。后来我们在开源软件的基础上进行自主研
发,一步一步地把IOE(IBM小型机、Oracle、EMC存储)这几个“神器”都去掉
了。这些神器就如同《西游记》中那些神仙的兵器,他们身边的妖怪们拿到这些兵
器能把猴子打得落荒而逃。但最牛的神仙是不依赖这些神器的,他们挥一挥衣袖、翻一下手掌就威力无比了。
坚若磐石
已经有读者在迫不及待地问怎么去掉了IOE?别急,在去掉IOE之前还有很长的
路要走(在后面讲到TDDL的时候,会提到去IOE的一些事情)。行癫等人买回小型机之后,我们用上了Oracle。然后七公带着一帮DBA做优化SQL和存储方面的工作,行癫带着几个架构师研究数据库的扩展性。Oracle本身是一个封闭的系统,用
Oracle怎么做扩展呢?用现在一个时髦的说法就是做“分库分表”。
我们知道,一台Oracle的处理能力是有上限的,它的连接池有数量限制,查询
速度与容量成反比。简单地说,在数据量上亿、查询量上亿的时候,就到它的极限
了。要突破这种极限,最简单的方式就是多用几个Oracle数据库。但一个封闭的系
统做扩展,不像分布式系统那样直接加机器就可以了。我们的做法是把用户的信息
按照ID来存放到两个数据库中(DB1和DB2),把商品的信息和卖家信息放在两个对
应的数据库中,把商品类目等通用信息放在第三个库中(DBcommon)。这么做的目
的是除了增加了数据库的容量之外,还有一个就是做容灾,即万一一个数据库挂
了,整个网站上还有一半的商品可以买。
数据库这么分后,应用程序就会出现麻烦,如果我是卖家,查看我的商品没有
问题,我们都在一个库里。但如果我是一个买家,买的商品有DB1的,也有DB2的,要查看“我已买到的宝贝”的时候,应用程序怎么办?必须到两个数据库中分别查
询对应的商品。要按时间排序怎么办?两个库中“我已买到的宝贝”全部查出来在
应用程序中做合并。另外,分页怎么处理?关键字查询怎么处理?专业点的说法就
是数据的Join没法做了。这些工作交给程序员来做也许会更麻烦,于是行癫出手
了,他写了一个数据库路由的框架DBRoute,统一处理了数据的合并、排序、分页
等操作,让程序员像使用一个数据库一样操作多个数据库里的数据,这个框架在淘
宝的Oracle时代一直在使用。但是后来随着业务的发展,这种分库的第二个目的
——“容灾”的效果没有达到。像评价、投诉、举报、收藏、我的淘宝等很多地
方,都必须同时连接DB1和DB2,哪个库挂了都会导致整个网站挂掉。
上一篇说过,采用EJB其实是和Sun的工程师妥协的结果,在他们离开之后,EJB也逐渐被冷落了下来。在2005年和2006年的时候,Spring大放异彩,于是在控
制层用Spring替换掉了EJB,给整个系统精简了很多代码。
上一篇还说过,为了减少数据库的压力,提高搜索的效率,我们引入了搜索引
擎。随着数据量的继续增长,到了2005年,商品数有1663万个,PV有8931万个,注
册会员有1390万个,这给数据存储带来的压力依然很大,数据量大,速度就慢。
亲,除了搜索引擎、分库分表,还有什么办法能提升系统的性能?一定还有招数可以用,这就是缓存和CDN(内容分发网络)。
你可以想象,9000万次的访问量,有多少是在商品详情页面?访问这个页面的
时候,数据全都是只读的(全部从数据库中读出来,不写入数据库),在那个时
候,我们的架构师多隆大神做了一个基于BerkeleyDB的缓存系统,把很多不太变动
的只读信息放了进去。其实最初这个缓存系统还比较弱,我们并不敢把所有能缓存
的信息都往里面放,一开始先把卖家的信息放里面,然后把商品属性放里面,再把
店铺信息放里面,但是像商品详情这类字段太大的放进去受不了。说到商品详情,这个字段比较恐怖,有人统计过,淘宝商品详情打印出来平均有5米长,在系统里其
实放在哪里都不招人待见。笔者清楚地记得,我来淘宝之后担任项目经理做的第一
个项目就是把商品详情从商品表中移出来。它最早与商品的价格、运费等信息放在
一个表中,拖慢了整张表的查询速度,而很多时候查询商品信息是不需要查看详情
的。于是在2005年的时候,我把商品详情放在数据库的另外一张表中,再往后,这
个大字段被从数据库中请了出来,先是放入了缓存系统,到现在是放进了文件系统
TFS中。
到现在为止,整个商品详情的页面都在缓存里面了,眼尖的读者可能会发现现
在的商品详情不全是“只读”的信息了,这个页面上有个信息叫“浏览量”(这个
信息是2006年加上去的),这个数字每刷新一次,页面就要“写入”存储一次,这
种高频度实时更新的数据能用缓存吗?通常来说,这种是必须放进数据库的,但是
悲剧的是,我们在2006年开发这个功能的时候,把浏览量写入数据库,发布上线1个
小时后,数据库就挂掉了,每天几亿次的写入,数据库承受不了。那怎么办?亲,……先不回答你,后面讲到缓存Tair的时候再说。(下图不是广告,请把注意力从
左边移到右边中间,看看浏览量这个数据在哪里。)
CDN这个工作相对比较独立,跟别的系统一样,一开始我们采用的也是商用系
统。后来随着流量的增加,商用的系统已经撑不住了,LVS的创始人章文嵩博士带人
搭建了淘宝自己的CDN网络。在本文的引言中,我说过淘宝的CDN系统支撑了
800Gbps以上的流量,作为对比,我们可以看一下国内专业做CDN的上市公司
ChinaCache的介绍——“ChinaCache是中国第一的专业CDN服务提供商,向客户提
供全方位网络内容快速分布解决方案。作为首家获信产部许可的CDN服务提供商,目
前ChinaCache在全国50多个大中城市拥有近300个节点,全网处理能力超过
500Gbps,其CDN网络覆盖中国电信、中国网通、中国移动、中国联通、中国铁通和
中国教育科研网等各大运营商。”——淘宝一家的流量比他们的加起来还要多,这
样你可以看出淘宝在CDN上的实力,这在全世界都是数一数二的(其实我们一开始用
的商用CDN就是ChinaCache,它们支撑了很长时间)。另外,因为CDN需要大量的服
务器,要消耗很多能源(消耗多少?在前两年我们算过一笔账,淘宝上产生一个交
易,消耗的电量足以煮熟4个鸡蛋)。这两年,章文嵩的团队又在研究低功耗的服务
器,在绿色计算领域也做了很多开创性的工作,我们定制的基于英特尔凌动处理器
的低功耗服务器已经部署到了CDN机房,降低了很大的能耗。这方面的内容可以看后
面笔者对章文嵩博士的专访。
回想起刚用缓存那段时间,笔者还是个菜鸟,有一个经典的错误常常犯,就是
更新数据库的内容时,忘记通知缓存系统,结果在测试的时候就发现我改过的数据
在页面上没有变化。后来做了一些页面上的代码,修改CSS和JS的时候,用户本地缓存的信息没有更新,页面上也会乱掉,在论坛上被人说的时候,我告诉他用
Ctrl+F5组合键(清除本地缓存刷新页面),然后赶紧修改脚本文件的名称,重新
发布页面。
我们对数据分库、放弃EJB、引入Spring、加入缓存、加入CDN等工作,看起来
没有章法可循,其实都是围绕着提高容量、提高性能、节约成本来做的,由于这些
是不算大的版本变迁,我们姑且叫它2.1版,这个版本从构图上看有三只脚,是不是
稳定了很多?
在这个稳定的版本下,淘宝网的业务有了突飞猛进的发展,2005年5月,微软的
MSN门户大张旗鼓地进入中国,淘宝网成为它的购物频道。2005年中,盛大进军机
顶盒业务,其电视购物的功能也是淘宝网开发的。虽然因为水土不服或者政策的原
因,这两个业务现在都看不到了,但他们曾经是中国互联网行业的大事件。那位和
微软谈合作的人是@胖胡斐,他花起钱来也是大手笔的,我们就管他叫“二少爷”,他现在是蘑菇街的COO。
另外,老马也从来都不缺少娱乐精神,他看到湖南卫视的超女如此成功,也想
借鉴一下这种模式。就在2005年底,淘宝网和湖南卫视合作推出了一档节目,叫
做“超级Buyer秀”。这是一个定位于“超级会网购的人”的一个选秀节目,以百万
年薪为诱饵,让大家分享自己的网购经历,网友投票选出最终胜者。这个从海选到
表演,历时一年多,广告做得铺天盖地。虽然节目最终没有超女那样火爆,这也
让“淘宝网就是网购”的形象通过湖南卫视更加深入人心。
到2006年,淘宝网已经有了1.5亿个的日均PV,商品数达5千多万个,注册用户
3千多万个,全网成交额达169亿元。
创造技术
TFS
回顾一下上面几个版本,1.0版的PHP系统运行了将近一年的时间(2003年5月
—2004年1月),服务器由一台发展到多台;后来数据库撑不住了,将MySQL换成了
Oracle,引入了搜索引擎(2004年1月—2004年5月,叫1.1版本);然后不到半年
的时间又把开发语言换成了Java(2004年2月—2005年3月,叫2.0版本),数据服
务逐步采用了IOE;随着数据量和访问量的增长,我们进行数据分库、加入缓存、使
用CDN(2004年10月—2007年1月,叫2.1版本)。这几个版本中间有些时间上的重
合,因为很多架构的演化并没有明显的时间点,它是逐步进化而来的。
在描述2.1版本的时候,我写的标题是《坚若磐石》,这个“坚若磐石”是因为
这个版本终于稳定下来了,在这个版本的系统上,淘宝网运行了两年多的时间。这
期间有很多优秀的人才加入,也开发了很多优秀的产品,例如,商品的类目属性、支付宝认证系统、招财进宝项目、淘宝旅行、淘宝彩票、淘宝论坛等,甚至在团购
网站风起云涌之前,淘宝网在2006年就推出了“团购”的功能。
在这些产品和功能的最底层,其实还是商品管理和交易管理这两大功能。这两
大功能在2.1版本中都有很大的变化。商品管理起初是要求卖家选择7天到期还是14
天到期,到期之后自动下架,必须重新发布才能上架,上架之后就变成了新的商品
信息(ID变过了)。另外,如果商品在这个期间成交了,之后再有新货,必须发布
一个新的商品信息。这么做有几个原因,一是参照拍卖商品的时间设置,要在某日
期前结束挂牌;二是搜索引擎不知道同样的商品哪个排在前面,那就把挂牌时间长
的排前面(这样就必须在某个时间把老的商品下架,否则它会一直排在前面);第
三是成交信息和商品ID关联,这个商品如果多次编辑还是同一个ID的话,成交记录
中的商品信息会不断改变;还有一个不为人知的原因是我们的存储有限,不能让所
有的商品老存放在主库中。这种处理方式简单粗暴,但还算是公平。不过这样会导
致很多需求都无法满足,例如,卖出一件商品之后就无法更改价格,否则前面已经
成交的那个价格都变了,而且同样的商品,上一次销售后的很多好评都无法在下一个商品上体现出来;再如,我买过的商品结束后只看到交易的信息,不知道卖家是
否还会卖。基于这些需求,我们在2006年下半年把商品和交易拆开,一个商家的一
种商品有一个唯一的ID,上下架都是同一个商品。那么如果卖家修改价格和库存等
信息,已成交的信息怎么处理?那就在买家每交易一次的时候,都记录下商品的快
照信息,有多少次交易就有多少个快照。这样买卖双方比较爽了,但这给系统带来
了什么?存储的成本大幅度上升了!
存储的成本高到什么程度呢?数据库方面用了IOE,一套下来就是千万级别的,那几套下来就是——好多钱啊。另外,淘宝网还有很多文件需要存储,最主要的就
是图片、商品描述、交易快照,一个商品要包含几张图片和一长串的描述信息,而
每一张图片都要生成几张规格不同的缩略图。在2010年,淘宝网的后端系统上保存
着286亿个图片文件。图片在交易系统中非常重要,大家常说“一张好图胜千
言”、“无图无真相”,淘宝网的商品照片,尤其是热门商品图片的访问流量是非
常大的。在淘宝网整体流量中,图片的访问流量要占到90%以上,而且这些图片平均
大小为17.45KB,小于8KB的图片占整体图片数量的61%,占整体系统容量的11%。这
么多的图片数据、这么大的访问流量,给淘宝网的系统带来了巨大的挑战。对于大
多数系统来说,最头疼的就是大规模的小文件存储与读取,因为磁头需要频繁寻道
和换道,因此,在读取上容易带来较长的延时。在大量高并发访问量的情况下,简
直就是系统的噩梦。我们该怎么办?
同样的套路,在某个规模以下采用现有的商业解决方案,达到某种规模之后,商业的解决方案无法满足,只有自己创造解决方案了。对于淘宝的图片存储来说,转折点在2007年。这之前,一直采用商用存储系统,应用NetApp公司的文件存储系
统。随着淘宝网的图片文件数量以每年3倍的速度增长,淘宝网后端NetApp公司的
存储系统也从低端到高端不断迁移,直至2006年,即使是NetApp公司最高端的产品
也不能满足淘宝网存储的要求。从2006年开始,我们决定自己开发一套针对海量小
文件存储的文件系统,用于解决自身图片存储的难题。这标志着淘宝网从使用技术
到了创造技术的阶段。
2007年之前的图片存储架构如下图所示。
在一次架构师大会上,章文嵩博士总结了几点商用存储系统的局限和不足。
第一,商用存储系统没有对小文件存储和读取的环境进行有针对性的优化;第
二,文件数量大,网络存储设备无法支撑;第三,整个系统所连接的服务器越来越
多,网络连接数已经达到网络存储设备的极限;第四,商用存储系统扩容成本高,10TB的存储容量需要几百万元,而且存在单点故障,容灾和安全性无法得到很好的
保证。
谈到在商用系统和自主研发之间的经济效益方面的对比,章文嵩博士列举了以
下几点经验。
第一,商用软件很难满足大规模系统的应用需求,无论是存储、CDN还是负载均
衡,在厂商实验室端,都很难实现如此大的数据规模测试。
第二,在研发过程中,将开源和自主开发相结合,会有更好的可控性,若系统
出了问题,完全可以从底层解决问题,系统扩展性也更高。
第三,在一定规模效应的基础上,研发的投入都是值得的。下图演示的是一个
自主研发和购买商用系统的投入产出比,实际上,图中交叉点的左边,购买商用系
统都是更加实际和经济性更好的选择,只有在规模超过交叉点的情况下,自主研发
才能收到较好的经济效果。实际上,规模化达到如此程度的公司并不多,不过淘宝
网已经远远超过了交叉点。
第四,自主研发的系统可在软件和硬件的多个层次之间不断优化。
历史总是惊人的巧合,在我们准备研发文件存储系统的时候,Google走在了前面,2007年,他们公布了GFS(GoogleFileSystem)的设计论文,这给我们带来了
很多借鉴的思路。随后我们开发出了适合淘宝使用的图片存储系统
(TaoBaoFileSystem,TFS)。3年之后,我们发现历史的巧合比我们想象的还要
神奇,几乎跟我们同时,中国的另外一家互联网公司也开发了他们的文件存储系
统,甚至取的名字都一样——TFS,太神奇了!(猜猜是哪家)
2007年6月,TFS正式上线运营。在生产环境中应用的集群规模达到了200台
PCServer(146GB×6SAS15KBRaid5),文件数量达到上亿级别;系统部署存储容
量为140TB;实际使用存储容量为50TB;单台支持随机IOPS200+,流量为3MBs。
说到TFS的系统架构,首先要描述清楚业务需求,淘宝对图片存储的需求大概可
以描述如下:
文件比较小;并发量高;读操作远大于写操作;访问随机;没有文件修改的操
作;要求存储成本低;能容灾,能备份。显然,应对这种需求时要用分布式存储系
统;由于文件大小比较统一,可以采用专有文件系统;由于并发量高,读写随机性
强,需要更少的IO操作;考虑到成本和备份,需要用廉价的存储设备;考虑到容
灾,需要能平滑扩容。
参照GFS并做了大量的优化之后,TFS1.0版的架构图如下。
从上面的架构图可看出:集群由Server和多台Data一对NameServer构成,NameServer的两台服务器互为双机,这就是集群文件系统中管理节点的概念。
在这个系统中:
-每个DataServer运行在一台普通的Linux主机上;
-以Block文件的形式存放数据文件(一个Block的大小一般为64MB);
-Block存储多份是为了保证数据安全;
-利用ext3文件系统存放数据文件;
-磁盘raid5做数据冗余;
-文件名内置元数据信息,用户自己保存TFS文件名与实际文件的对照关系,这
使得元数据量特别小。
淘宝TFS文件系统在核心设计上最大的取巧在于,传统的集群系统中元数据只有
1份,通常由管理节点来管理,因而很容易成为瓶颈。而对于淘宝网的用户来说,图
片文件究竟用什么名字来保存他们并不关心,因此,TFS在设计规划上考虑在图片的
保存文件名上暗藏了一些元数据信息,例如,图片的大小、时间、访问频次等信
息,包括所在的逻辑块号。而在实际的元数据上,保存的信息很少,因此,元数据
结构非常简单。仅仅只需要一个FileID就能够准确定位文件在什么地方。由于大量
的文件信息都隐藏在文件名中,整个系统完全抛弃了传统的目录树结构,因为目录
树开销最大。拿掉后,整个集群的高可扩展性可极大地提高。实际上,这一设计理
念和目前业界的“对象存储”较类似。
在TFS上线之前,淘宝网每个商品只允许上传一张图片,大小限定在120KB之
内,在商品详情中的图片必须使用外站的服务。那时侯发布一件商品确实非常麻
烦,笔者曾经想卖一台二手电脑,我先把照片上传到Google相册,在发布到淘宝网
之后发现Google相册被墙(即被屏撇,无法访问),我的图片别人看不到,当时很
郁闷。在TFS上线后,商品展示图片开放到5张,商品描述里面的图片也可以使用淘
宝的图片服务,到现在为止,淘宝网给每个用户提供了1GB的图片空间。技术和业务
就是这么互相借力推动着的,业务满足不了的时候,技术必须创新,技术创新之
后,业务有了更大的发展空间。
TFS发布之后,又经历了多个版本的修改,到1.3版的时候已经比较成熟了。
2009年6月,TFS1.3版本上线,集群规模大大扩展,部署到淘宝的图片生产系统
上,整个系统已经从原有200台PC服务器扩增至440台PC服务器
(300B×12SAS15KBRPM)+30台PC服务器(600B×12SAS15KBRPM)。支持文件数量
也扩容至百亿级别;系统部署存储容量为1800TB;当前实际存储容量为995TB;单
台DataServer支持随机IOPS900+,流量为15MB+;目前NameServer运行的物理内
存是217MB(服务器使用千兆网卡)。
TFS1.3版本逻辑结构图如下图所示。
在TFS1.3版本中,工程师们重点改善了心跳和同步的性能,最新版本的心跳和
同步在几秒钟之内就可完成切换,同时进行了一些新的优化,包括元数据存储在内
存中、清理磁盘空间等。
性能上也做了优化,包括如下内容。
-采用ext4文件系统,并且预分配文件,减少ext3等文件系统数据碎片带来的
性能损耗;
-单进程管理单块磁盘的方式,摒除RAID5机制;
-带有HA机制的中央控制节点,在安全稳定和性能复杂度之间取得平衡;
-缩减元数据大小,将更多的元数据加载入内存,提升访问速度;y跨机架和IDC的负载均衡及冗余安全策略;
-完全平滑扩容。
对于整个图片服务来说,仅有TFS还是不够的,整个图片服务机器的拓扑结构如
下图所示。
整个图片存储系统就像一个庞大的服务器,有处理单元、缓存单元和存储单
元。前面已经介绍过后台的TFS集群文件存储系统,在TFS前端,还部署着200多台
图片文件服务器,用Apache实现,用于生成缩略图的运算。
值得一提的是,根据淘宝网的缩略图生成规则,缩略图都是实时生成的。这样
做的好处有两点:一是为了避免后端图片服务器上存储的图片数量过多,大大节约
后台存储空间的需求,我们计算过,采用实时生成缩略图的模式比提前全部生成好缩略图的模式节约90%的存储空间。也就是说,存储空间只需要后一种模式的10%。
二是,缩略图可根据需要实时生成,这样更加灵活。
图片文件服务器的前端则是一级缓存和二级缓存,前面还有全局负载均衡的设
置,用于解决图片的访问热点问题。图片的访问热点一定存在,重要的是,让图片
尽量在缓存中命中。目前淘宝网在各个运营商的中心点设有二级缓存,整体系统中
心店设有一级缓存,加上全局负载均衡,传递到后端TFS的流量就已经非常均衡和分
散了,对前端的响应性能也大大提高。根据淘宝的缓存策略,大部分图片都尽量在
缓存中命中,如果缓存中无法命中,则会在本地服务器上查找是否存有原图,并根
据原图生成缩略图,如果都没有命中,则会考虑去后台TFS集群文件存储系统上调
取。因此,最终反馈到TFS集群文件存储系统上的流量已经被大大优化了。
淘宝网将图片处理与缓存编写成基于Nginx的模块,我们认为,Nginx是目前性
能最高的HTTP服务器(用户空间),代码清晰,模块化非常好。淘宝网使用
GraphicsMagick进行图片处理,采用了面向小对象的缓存文件系统,前端有
LVS+Haproxy将原图和其所有的缩略图请求都调度到同一台Image Server(图片服
务器)。
在文件定位上,内存用Hash算法做索引,最多一次读盘。另外会有很多相同的
图片重复上传上来,去除重复文件也是采用Hash算法来做的。写盘方式则采用
Append方式写,并采用了淘汰策略FIFO,主要考虑降低硬盘的写操作,没有必要进
一步提高Cache命中率,因为ImageServer和TFS位于同一个数据中心,读盘效率还
是非常高的。
目前淘宝网的TFS已经开源(见code.taobao.org),业界的同仁可以一起使
用和完善这个系统。
Tair
TFS的开发让淘宝的图片功能得到了充分的发挥。同TFS一样,很多技术都是在
产品的推动下得到发展的。在介绍下面的技术之前,有必要说说前些年我们做过的
几个产品。
先说一个比较悲剧的——“团购”,这个团购可不是现在满大街挂的那种
Groupon类型的模式,在Groupon产生之前,在2006年,淘宝的产品经理一灯就提
出了“团购”这种产品。一灯最初的设想是让买家在社区发起团购,“团长”找到
足够的人之后,去跟卖家砍价,这类似于现在蘑菇街的“自由团”。但由于种种原
因,在开发的时候,对产品的功能做了裁剪,与最初的设想比起来偏离了一点,变
成了让卖家设置团购价,在买家达到指定的数量之后,以团购价成交。这个功能看
起来是结合了淘宝“一口价”和“荷兰拍”的另一种交易模式,但最终没有支撑下
去,这种交易方式最大的弱点就是让买家看到了卖家的底牌,即便达不到团购的数
量,他们也往团购的价格上砍。当时为了提高流量,淘宝网开辟了团购专区,实诚
的卖家在达不到团购数量的时候,被砍价砍亏了,狡猾的卖家干脆提高原价,利用
这个专区做促销。在接下来的两年里,这个产品沦落成了促销工具(话说现在满大
街的团购,其实也就是促销)。这个产品让研发人员对“产品”这个概念有了深刻
的认识。
再说一个更加悲剧的——“我的淘宝”。“我的淘宝”是给会员管理自己的商
品、交易、收货地址、评价、投诉的地方,这个地方必须在登录之后才能看到,所
以风格与外观完全不一样,很长时间都没有优化过,样子丑,用户操作也不方便,如果一个人有很多商品,上下架需要一个一个地操作,非常麻烦(想想那些卖书
的)。这时候一个重要人物承志(现在的蘑菇街CEO)登场了,他给我们演示了最牛
的前端交互技术,就是Gmail上那种AJAX的交互方式,可以拖动,可以用鼠标右
键,也可以用组合键,操作完毕还不刷新页面,管理商品如有神助,帅呆了。我是
这个项目的项目经理,一灯是产品经理,我们再拉上万剑和一伙工程师就开始行动
了。我们热火朝天地干了三个月,快要完成的时候,老马突然出现在我身后,看我操作了一遍新版“我的淘宝”之后,问我这是不是客户端软件,我说是网页,他抓
狂了,说这跟客户端软件一样,链接下面的下画线都没有,上下架用文件夹表示,他都不知道怎么操作,卖家肯定也不会玩。
页面如下图所示:看看这神乎其技的翻页条、精致的文件夹结构、人性化的多
选框,还有一个类似Excel的冻结窗口的功能,这有多么性感啊!
老马果然是神一样的人物,他说的应验了,淘宝历史上第一个群体性事件爆发
了,试用完新版本的“我的淘宝”之后,很多卖家愤怒了,说不会玩儿。一灯就和
承志一起商量怎么把页面改得像网页一点,改了半个月,愤怒依然没有平息。我很
无奈地看着这两个人在那里坚持,然后跟老板们商量怎么办。后来我们到论坛上让
大家投票要不要使用新版“我的淘宝”,投票结果是一半以上的人反对。于是这十
来个人做了3个月的系统被杀掉了。这让我非常沮丧,但最痛苦的还不是这个,我们
下线之后,另外一拨卖家不满了,说这么好的功能怎么没有了?这个产品带给我们
的是新技术(AJAX、prototype框架)的尝试,以及新技术对用户操作习惯的改
变,一定要慎之又慎。另外,还有一点没有总结好的教训,就是应对群体事件的时
候,我们手足无措,在后来“招财进宝”和淘宝商城出现群体性事件的时候,我发
现悲剧在重演。
说到“招财进宝”,这个是最悲剧的产品。在2006年“五一”的时候,一个划
时代的项目启动了。财神说要用最好的项目阵容,我被选中了,这一下让我觉得我
能划分到最好的员工之类,在“我的淘宝”这个产品中严重受伤的心又痊愈了。这
是一个商品P4P的系统,就是按成交付费。我们认为已经有很多卖家有钱了,但淘宝
上这么多的商品,他们很难被找到,卖家愿意花钱让商品排在前面。我们允许卖家购买广告位,把他的商品按一定算法给出排名(类似于百度的竞价排名,但不仅仅
看他出了多少钱,还要看信用、成交量、被收藏数量等,这个算法弄得巨复杂)。
这是一个多么牛的盈利模式啊!
这个系统进行得很顺利,但发布的时候,更大的群体性事件出来了,买家们质
疑:你们不是承诺三年不收费吗?收广告费不是收费吗?后来我们的竞争对手又推
波助澜,公关公司和圈子里各路大侠上蹿下跳,甚至同行推出了“一键搬家”的功
能来收纳我们的会员。一时间,舆论哗然,各种矛头都指了过来。为了收场,我们
又一次在论坛中让用户投票决定产品是否下线,同“我的淘宝”一样,以悲剧收
场。也如同“我的淘宝”一样,下线后,一拨尝到甜头的卖家说,这么好的功能怎
么没有了?(直到Yahoo中国合并之后,开发了淘宝直通车,才以类似的产品形态满
足了这部分需求。)
虽然“招财进宝”失败了,但这个项目中对技术的探索更加深入,其中用到了
用户行为追踪、AJAX等,而且有一个技术的细节非常经典,淘宝商品详情页面每天
的流量有几个亿,里面的内容都是放在缓存里的,做“招财进宝”的时候,我们要
给卖家显示他的商品被浏览的次数(见下图),这个数字必须实时更新,而用缓存
一般都是异步更新的,所以,一开始根本没考虑把这个数据放入缓存里。我们的商
品表里增加了这样一个字段,每增加一个PV,该字段就要更新一次。发布一个小时
后,数据库就挂掉了。数据库撑不住怎么办?一般的缓存策略是不支持实时更新
的,这时候多隆大神想了个办法,在Pache上面写了一个模块,这个数字根本不经过
下层的WebApp容器(只经过Apache)就写入一个集中式的缓存区了,这个缓存区的
数据再异步更新到数据库。这就是我前面提到的,整个商品详情的页面都在缓存中
了,把缓存用到了极致。
接下来,我们就说说缓存的技术吧。
淘宝在很早就开始使用缓存技术了,在2004年的时候,我们使用一个叫做
ESI(EdgeSideIncludes)的缓存(Cache)。在决定采用ESI之前,多隆试用了
Java的很多Cache,但都比较重,后来用了OracleWebCache,也经常挂掉,OracleWebCache也支持ESI,多隆由此发现了ESI这个好东东。ESI是一种数据缓
冲缓存服务器,它提供将Web网页的部分(这里指页面的片段)进行缓冲缓存的技
术及服务。以往的数据缓冲服务器和信息传送服务以“页”为单位制作,复制到数
据缓冲服务器中,这用于处理静态页面很有效,但在面对动态内容的时候,就很难
得到高效率。在ESI中是部分的缓冲网页,使用基于XML的标记语言,指定想要缓冲
的页面部分。由此,页面内分为动态地变更部分和静态的不变更部分,只将静态的
部分有效地发送到服务器中。淘宝网的数据虽然大部分都是动态产生的,但页面中
的静态片段也有很多,例如,页面的头、尾,商品详情页面的卖家信息等(如下图
右侧),这些最早都是从ESI缓存中读取的。
ESI解决了页面端静态片段的缓存,聪明的读者可能马上就想到了,在后端的那
些数据能不能使用缓存?显然也是可以的,而且是必需的。例如,一个大卖家的商
品和店铺,一天的浏览量可能是几百万个,一个小卖家的可能只有几个,那么这个
大卖家的用户信息要是每次都从数据库中读取,显然不划算,要是把这个信息放在
内存中,每次都从内存里取,性能要好很多。这种应用场景就是memcached这种
Key-Value缓存的用武之地。只可惜,在淘宝急需要memcached的时候,它还没有
崭露头角(它于2003年6月出现,但近几年才火爆起来,当时没发现它)。我们的架
构师多隆大神再一次出手写了一个缓存系统,叫TBstore,这是一个分布式的基于
BerkeleyDB的缓存系统,推出之后,在阿里巴巴集团内部使用非常广泛,特别是对
于淘宝,TBstore上应用了ESI(就是上面说过的那个ESI)、Checkcode(验证
码)、Description(前文说过的商品详情)、Story(心情故事,商品信息里面的
一个大字段,长度仅次于商品详情)、用户信息等内容。
TBstore的分布式算法实现:根据保存的Key(关键字),对key进行Hash算
法,取得Hash值,再对Hash值与总Cache服务器数据取模。然后根据取模后的值,找到服务器列表中下标为此值的Cache服务器。由JavaClientAPI封装实现,应用
无须关心。
TBstore有一个优点,这也是它的弱点,它的存储是基于BerkeleyDB的,而
BerkeleyDB在数据量超过内存的时候,就要往磁盘上写数据了,所以,它是可以做
持久化存储的。但是一旦往磁盘写入数据,作为缓存的性能就大幅下降。
这时又有一个项目,推动了淘宝在缓存方面的技术提升。在2007年,我们把淘
宝的用户信息独立出来,形成一个中心系统UIC(UserInformationCenter),因
为淘宝所有的功能都要依赖于用户信息,所以这个模块必须单独拿出来,否则以后
的系统无法扩展。把UIC拿出来以后,应用系统访问UIC,UIC访问数据库取得用户
信息,粗算一下,每天要取几十亿条的用户信息,若直接查询数据库,数据库肯定
会崩溃,这里必须要用缓存。于是多隆专门为UIC写了一个缓存系统,取名叫做
TDBM。TDBM抛弃了BerkeleyDB的持久功能,数据全部存放在内存中。到2009年,多隆又参考了memcached的内存结构,改进了TDBM的集群分布方式,在内存利用率
和吞吐量方面又做了大幅提升,推出了TDBM2.0系统。
下图是一个关键应用的实时监控信息,第一行是UIC的缓存命中率,可以看到有
99.2%之高。换句话说,也就是给数据库减少了99.2%的压力。
由于TDBM、TBstore的数据接口和用途都很相似,开发团队把二者合并,推出
了淘宝自创的Key-Value缓存系统——Tair(TaoBaoPair的意思,Pair即Key-
Value数据对)。Tair包括缓存和持久化两种存储功能。Tair作为一个分布式系
统,由一个中心控制节点和一系列的服务节点组成,我们称中心控制节点为
ConfigServer,服务节点是DataServer。ConfigServer负责管理所有的
DataServer,维护DataServer的状态信息。DataServer对外提供各种数据服务,并以心跳的形式将自身的状况汇报给ConfigServer。ConfigServer是控制点,而
且是单点,目前采用一主一备的形式来保证其可靠性。所有的DataServer地位都是
等价的。Tair的架构图如下图所示。
系统部署结构如下图所示。
目前,Tair支撑了淘宝几乎所有系统的缓存信息。Tair已开源,地址为
code.taobao.org。
在创造了TFS和Tair之后,整个系统的架构如下图所示。
在这个时候,研发部对搜索引擎iSearch也进行了一次升级,之前的搜索引擎
是把数据分到多台机器上,但是每份数据只有一份,现在是每份数据变成多份,整
个系统从一个单行的部署变成了矩阵,能够支撑更大的访问量,并且做到很高的可
用性。
到2007年,淘宝网日均PV达到2.5亿个,商品数超过1亿个,注册会员数达5千
多万个,全网成交额达433亿元。 第三部分淘宝技术发展3
“所有的进步都是不稳定的,一个问题解决了,我们不得不面对又一个新问
题。”——马丁?路德?金
分布式时代
服务化
在系统发展的过程中,架构师的眼光至关重要,作为程序员,只要把功能实现
即可,但作为架构师,要考虑系统的扩展性、重用性,对于这种敏锐的感觉,有人
说是一种“代码洁癖”。淘宝早期有几个架构师具备了这种感觉,周悦虹开发的
Webx是一个扩展性很强的框架,行癫在这个框架上插入了数据分库路由的模块、Session框架等。在做淘宝后台系统的时候,同样需要这几个模块,行癫指导我把
这些模块单独打成JAR包。另外,在做淘宝机票、彩票系统的时候,页面端也有很多
东西需要复用,最直观的是页眉和页脚,一开始,我们的每个系统中都复制了一
份,但奇妙的是,那段时间页脚要经常修改,例如,把“雅虎中国”改成“中国雅
虎”,过一段时间又加了一个“口碑网”,再过一段时间变成了“雅虎口碑”,最
后又变成了“中国雅虎”。后来我就把这部分Velocity模板独立出来做成了公用的
模块。
上面说的都是比较小的复用模块,到2006年,我们做了一个商品类目属性的改
造,在类目中引入了属性的概念。项目的代号叫做“泰山”,如同它的名字一样,这是一个举足轻重的项目,这个改变是一个划时代的创新。在这之前的三年时间
内,商品的分类都是按照树状一级一级的节点来分的,随着商品数量的增长,类目
也变得越来越深,且越来越复杂,这样,买家如果要查找一件商品,就要逐级打开
类目,找商品之前要弄清商品的分类。而淘宝运营部门管理类目的小二也发现了一
个很严重的问题,例如,男装里有T恤、T恤下面有耐克、耐克有纯棉的,女装里也
有T恤、T恤下面还是有耐克、耐克下面依然有纯棉的,那是先分男女装,再分款式、品牌和材质呢,还是先分品牌,再分款式、材质和男女装呢?弄得很乱。这时
候,一位大侠出来了——一灯,他说品牌、款式、材质等都可以叫做“属性”,属
性是类似Tag(标签)的一个概念,与类目相比更加离散、灵活,这样也缩减了类目
的深度。这个思想的提出一举解决了分类的难题!从系统的角度来看,我们建立
了“属性”这样一个数据结构,由于除了类目的子节点有属性外,父节点也可能有
属性,于是类目属性合起来也是一个结构化的数据对象。这个做出来之后,我们把
它独立出来作为一个服务,叫做Catserver(CategoryServer)。跟类目属性密切
关联的商品搜索功能独立出来,叫做Hesper(金星)。Catserver和Hesper供淘宝
的前后台系统调用。
现在淘宝的商品类目属性已经是全球最大的,几乎没有什么类目的商品在淘宝
上找不到(除了违禁的),但最初的类目属性改造完之后,我们很缺乏属性数据,尤其是数码类。从哪里弄这些数据呢?我们跟“中关村在线”合作,拿到了很多数
据,那个时候,很多商品属性信息的后边标注着:“来自中关村在线”。有了类目
属性,给运营工作带来了很大的便利,我们知道淘宝的运营主要就是类目的运营,什么季节推什么商品,都要在类目属性上做调整,让买家更容易找到。例如,夏天
让用户在女装一级类目下标出材质是不是蕾丝的、是不是纯棉的,冬天却要把羽绒
衣调到女装一级类目下,什么流行,就要把什么商品往更高级的类目调整。这样类
目和属性要经常调整,随之而来的问题就出现了——调整到哪个类目,所属商品的
卖家就要编辑一次自己的商品,随着商品量的增长,卖家的工作量越来越大,他们
肯定受不了。到了2008年,我们研究了超市里前后台商品的分类,发现超市前台商
品可以随季节和关联来调整摆放场景(例如著名的啤酒和尿布的关联),后台仓库
里要按照自然类目来存储,二者密切关联,却又相互分开这样卖家发布商品选择的
是自然类目和属性,淘宝前台展示的是根据运营需要摆放商品的类目和属性。改造
后的类目属性服务取名为Forest(森林,与类目属性有点神似。Catserver还用于
提供卖家授权、品牌服务、关键词等相关的服务)。类目属性的服务化是淘宝在系
统服务化方面做的第一个探索。
虽然个别架构师具备了“代码洁癖”,但淘宝前台系统的业务量和代码量还是
呈爆炸式的增长。业务方总在后面催,开发人员不够就继续招人,招来的人根本看不懂原来的业务,只好摸索着在“合适的地方”加一些“合适的代码”,看看运行
起来像那么回事后,就发布上线。在这样的恶性循环中,系统越来越臃肿,业务的
耦合性越来越高,开发的效率越来越低。借用当时比较流行的一句话“你写一段代
码,编译一下能通过,半个小时就过去了;编译一下没通过,半天就过去了。”在
这种情况下,系统出错的概率也逐步增长,常常是你改了商品相关的某些代码,发
现交易出问题了,甚至你改了论坛上的某些代码,旺旺出问题了。这让开发人员苦
不堪言,而业务方还认为开发人员办事不力。
大概是在2007年年底的时候,研发部空降了一位从硅谷来的高管——空闻大
师。空闻是一位温厚的长者,他告诉我们一切要以稳定为中心,所有影响系统稳定
的因素都要解决掉。例如,每做一个日常修改,都必须对整个系统回归测试一遍;
多个日常修改如果放在一个版本中,要是一个功能没有测试通过,整个系统都不能
发布。我们把这个叫做“火车模型”,即任何一个乘客没有上车,都不许发车。这
样做最直接的后果就是火车一直晚点,新功能上线更慢了,我们能明显感觉到业务
方的不满,空闻的压力肯定非常大。
现在回过头来看看,其实我们并没有理解背后的思路。正是在这种要求下,我
们不得不开始改变一些东西,例如,把回归测试日常化,每天晚上都跑一遍整个系
统的回归。另外,在这种要求下,我们不得不对这个超级复杂的系统做肢解和重
构,其中复用性最高的一个模块——用户信息模块开始拆分出来,我们叫它
UIC(UserInformationCenter)。在UIC中,它只处理最基础的用户信息操作,例如,getUserById、getUserByName等。
在另一方面,还有两个新兴的业务对系统基础功能的拆分也提出了要求。在那
个时候,我们做了淘宝旅行(trip.taobao.com)和淘宝彩票
(caipiao.taobao.com)两个新业务,这两个新业务在商品的展示和交易的流程
上都跟主站的业务不一样,机票是按照航班的信息展示的,彩票是按照双色球、数
字和足球的赛程来展示的。但用到的会员功能和交易功能是与主站差不多的,当时
做起来就很纠结,因为如果在主站中做,会有一大半跟主站无关的东西,如果重新做一个,会有很多重复建设。最终我们决定不再给主站添乱了,就另起炉灶做了两
个新的业务系统,从查询商品、购买商品、评价反馈、查看订单这一整个流程都重
新写了一套。现在在“我的淘宝”中查看交易记录的时候,还能发现“已买到的宝
贝”中把机票和彩票另外列出来了,他们没有加入到普通的订单中。在当时,如果
已经把会员、交易、商品、评价这些模块拆分出来,就不用什么都重做一遍了。
到2008年初,整个主站系统(有了机票、彩票系统之后,把原来的系统叫做主
站)的容量已经到了瓶颈,商品数在1亿个以上,PV在2.5亿个以上,会员数超过了
5000万个。这时Oracle的连接池数量都不够用了,数据库的容量到了极限,即使上
层系统加机器也无法继续扩容,我们只有把底层的基础服务继续拆分,从底层开始
扩容,上层才能扩展,这才能容纳以后三五年的增长。
于是我们专门启动了一个更大的项目,即把交易这个核心业务模块拆分出来。
原来的淘宝交易除了跟商品管理耦合在一起,还在支付宝和淘宝之间转换,跟支付
宝耦合在一起,这会导致系统很复杂,用户体验也很不好。我们把交易的底层业务拆分出来,叫交易中心(TradeCenter,TC),所谓底层业务,就如创建订单、减
库存、修改订单状态等原子型的操作;交易的上层业务叫交易管理
(TradeManager,TM),例如,拍下一件普通商品要对订单、库存、物流进行操
作,拍下虚拟商品不需要对物流进行操作,这些在TM中完成。这个项目取了一个很
没有创意的名字——“千岛湖”,开发人员取这个名字的目的是想在开发完毕之
后,去千岛湖玩一圈,后来他们如愿以偿了。这个时候还有一个淘宝商城的项目在
做,之前拆分出来的那些基础服务给商城的快速构建提供了良好的基础。
类目属性、用户中心、交易中心,随着这些模块的逐步拆分和服务化改造,我
们在系统架构方面也积累了不少经验。到2008年年底就做了一个更大的项目,把淘
宝所有的业务都模块化,这是继2004年从LAMP架构到Java架构之后的第二次脱胎换
骨。我们对这个项目取了一个很霸气的名字——“五彩石”(女娲炼石补天用的石
头)。这个系统重构的工作非常惊险,有人称为“给一架高速飞行的飞机换发动
机”。“五彩石”项目发布之后,相关工程师去海南三亚玩了几天。
他们把淘宝的系统拆分成了如下架构。
其中,UIC和Forest在上文已说过,TC、IC、SC分别是交易中心
(TradeCenter)、商品中心(ItemCenter)、店铺中心(ShopCenter),这些
中心级别的服务只提供原子级的业务逻辑,如根据ID查找商品、创建交易、减少库
存等操作。再往上一层是业务系统TM(TradeManager,交易业务)、IM(ItemManager,商品业务)、SM(ShopManager,后来改名叫SS,即
ShopSystem,店铺业务)、Detail(商品详情)。
拆分之后,系统之间的交互关系变得非常复杂,示意图如下所示。
系统这么拆分的好处显而易见,拆分之后的每个系统可以单独部署,业务简
单,方便扩容;有大量可重用的模块便于开发新的业务;能够做到专人专事,让技
术人员更加专注于某一个领域。这样要解决的问题也很明显,分拆之后,系统之间
还是必须要打交道的,越往底层的系统,调用它的客户越多,这就要求底层的系统
必须具有超大规模的容量和非常高的可用性。另外,拆分之后的系统如何通信?这里需要两种中间件系统,一种是实时调用的中间件(淘宝的HSF,高性能服务框
架),一种是异步消息通知的中间件(淘宝的Notify)。另外,一个需要解决的问
题是用户在A系统登录后,到B系统的时候,用户的登录信息怎么保存?这又涉及一
个Session框架。再者,还有一个软件工程方面的问题,这么多层的一套系统,怎
么去测试它?
中间件
HSF
互联网系统的发展看似非常专业,其实在生活中也存在类似的“系统”,正如
一位哲学家说“太阳底下无新事”。我们可以从生活中的一个小例子来看网站系统
的发展,这个例子是HSF的作者毕玄写的。
一家小超市,一个收银员,同时还兼着干点其他的事情,例如,打扫卫生、摆
货。
来买东西的人多起来了,排队很长,顾客受不了,于是增加了一个收银台,雇
了一个收银员。
忙的时候收银员根本没时间去打扫卫生,超市内有点脏,于是雇了一个专门打
扫卫生的。
随着顾客不断增加,超市也经过好几次装修,由以前的一层变成了两层,这个
时候所做的事情就是不断增加收银台、收银员和打扫卫生的人。
在超市运转的过程中,老板发现一个现象,有些收银台排很长的队,有些收银
台排的人不多,了解后知道是因为收银台太多了,顾客根本看不到现在各个收银台
的状况。对于这个现象,一种简单的方法就是继续加收银台。但一方面,超市没地
方可加收银台了,另一方面,作为老板,当然不需要雇太多的人,于是开始研究怎样让顾客了解到收银台的状况,简单地加了一个摄像头和一个大屏幕,在大屏幕上
显示目前收银台的状况,这样基本解决了这个问题。
排队长度差不多后,又出现了一个现象,就是有些收银台速度明显比其他的
慢,原因是排在这些收银台的顾客买的东西特别多,于是又想了一招,就是设立专
门的10件以下的通道,这样买东西比较少的顾客就不用排太长的队了,这一招施展
后,顾客的满意度明显提升,销售额也好了不少,后来就继续用这招应对团购状
况、VIP状况。
在解决了上面的一些烦心事后,老板关注到了一个存在已久的现象,就是白天
收银台很闲,晚上则很忙,于是从节省成本上考虑,决定实行部分员工只在晚上上
班的机制,白天则关闭一些收银台,顾客仍然可以通过大屏幕看到哪些收银台是关
闭的,避免走到没人的收银台去,实行这招后,成本大大降低了。
这个生活中的例子及其解决的方法,其实和互联网网站发展过程中的一些技术
是非常类似的,只是在技术层面用其他名词来表达了而已,例如,有集群、分工、负载均衡、根据QoS分配资源等。
-集群:所有的收银员提供的都是收银功能,无论顾客到哪一个收银员面前,都
可完成付款,可以认为所有的收银员就构成了一个集群,都希望能做到顾客增加的
时候只需增加收银员就行。在现实生活中有场地的限制,而在互联网应用中,能否
集群化还受限于应用在水平伸缩上的支撑程度,而集群的规模通常会受限于调度、数据库、机房等。
-分工:收银员和打扫卫生的人分开,这种分工容易解决,而这种分工在互联网
中是一项重要而复杂的技术,没有现实生活中这么简单,涉及的主要有按功能和数
据库的不同拆分系统等,如何拆分以及拆分后如何交互是需要面临的两个挑战。因此,会有高性能通信框架、SOA平台、消息中间件、分布式数据层等基础产品的诞
生。
-负载均衡:让每个收银台排队差不多长,设立小件通道、团购通道、VIP通道
等,这些可以认为都是集群带来的负载均衡的问题,从技术层面上说,实现起来自
然比生活中复杂很多。
-根据QoS分配资源:部分员工仅在晚上上班的机制要在现实生活中做到不难,而对互联网应用而言,就是一件复杂而且极具挑战的事。
参照生活中的例子来说,在面对用户增长的情况下,想出这些招应该不难,不
过要掌握以上四点涉及的技术就相当复杂了,而且互联网中涉及的其他很多技术还
没在这个例子中展现出来,例如缓存、CDN等优化手段;运转状况监测、功能降级、资源劣化、流控等可用性手段,自建机房、硬件组装等成本控制手段。因此,构建
一个互联网网站确实是不容易的,技术含量十足,当然,经营一家超市也不简单。
从超市的运维可以抽象出系统设计的一些思路,服务拆分之后,如何取得我需
要的服务?在“电视机”上,把每个集群能提供的服务显示出来。你不需要关心哪
个人为你服务,当你有需要的时候,请先看头顶的电视机,它告诉你哪个服务在哪
个区域。当你直接去这个区域的时候,系统会给你找到一个最快速的服务通道。
这就是HSF的设计思想,服务的提供者启动时通过HSF框架向
ConfigServer(类似超市的电视机)注册服务信息(接口、版本、超时时间、序列
化方式等),这样ConfigServer上面就定义了所有可供调用的服务(同一个服务也
可能有不同的版本);服务调用者启动的时候向ConfigServer注册对哪些服务感兴
趣(接口、版本),当服务提供者的信息变化时,ConfigServer向相应的感兴趣的
服务调用者推送新的服务信息列表;调用者在调用时则根据服务信息的列表直接访
问相应的服务提供者,而无须经过ConfigServer。我们注意到ConfigServer并不
会把服务提供者的IP地址推送给服务的调用者,HSF框架会根据负载状况来选择具体
的服务器,返回结果给调用者,这不仅统一了服务调用的方式,也实现了“软负载
均衡”。平时ConfigServer通过和服务提供者的心跳来感应服务提供者的存活状
态。
在HSF的支持下,服务集群对调用者来说是“统一”的,服务之间是“隔
离”的,这保证了服务的扩展性和应用的统一性。再加上HSF本身能提供的“软负载
均衡”,服务层对应用层来说就是一片“私有云”了。
HSF框架以SAR包的方式部署到Jboss、Jetty或Tomcat下,在应用启动的时
候,HSF(High-SpeedServiceFramework,在开发团队内部有一些人称HSF为“好
舒服”)服务随之启动。HSF旨在为淘宝的应用提供一个分布式的服务框架,HSF从
分布式应用层面以及统一的发布调用方式层面为大家提供支持,从而可以很容易地
开发分布式的应用以及提供或使用公用功能模块,而不用考虑分布式领域中的各种
细节技术,例如,远程通讯、性能损耗、调用的透明化、同步异步调用方式的实现
等问题。
从上图HSF的标志来看,它的速度是很快的。HSF是一个分布式的标准Service
方式的RPC(RemoteProcedureCallProtocol,远程过程调用协议)框架,Service的定义基于OSGI的方式,通讯层采用TCPIP协议。关于分布式的服务框架
的理论基础,HSF的作者毕玄写了一篇博文
(http:www.blogjava.netBlueDavarchive20080124177533.html),有关基于OSGI的分布式服务框架,也有一系列的博文
(http:www.blogjava.netBlueDavarchive20080114175054.html)。
从下面这个HSF监控系统的截图中可以更直观地看到一些信息,在两个集群中有
两个服务器(其实有更多的,没有全部截图下来)都提供
com.taobao.item.service.SpuGroupS这一服务,版本号都是1.0.0,这个服务
在ConfigServer上的注册信息中包含超时时间、序列化方式。在后面那条信息中可
看到,在展开的这个集群中服务有835台机器已订阅,这些订阅者有淘宝的服务器
(cart是购物车功能的服务器),也有hitao(淘花网)的服务器。
HSF系统目前每天承担了300亿次以上的服务调用。
一些读者可能会有一个疑问:既然淘宝的服务化是渐进式的,那么在HSF出现之
前,系统之间的调用采用什么方式呢?
这个有点“五花八门”,例如,对于类目的调用方式是:Forest打包成一个
JAR包,在应用启动的时候装载到内存中,仅这一个JAR包所占用的内存就有800MB
之多(因为淘宝的类目数据太庞大了),对于当时一般只有2GB内存的开发机来说,加载完类目信息后,机器运行速度就非常慢。对于用户信息(UIC)来说,一开始的
调用方式是用Hessian接口。还有一些系统是通过WebService、Socket甚至是
HTTP请求来相互调用的。每种调用方式都涉及各种超时、信息的加解密、参数的定
义等问题,由此可见,在没有HSF之前,系统之间的调用是错综复杂的。而随着系统
拆分得越来越多,必须由一个统一的中间层来处理这种问题,HSF正是在这种背景下
诞生的。
NotifyHSF
解决了服务调用的问题,我们再提出一个很早就说过的问题:用户在银行的网关付钱后,银行需要通知到支付宝,但银行的系统不一定能发出通知;如果通知发
出了,不一定能通知到;如果通知到了,不一定不重复通知一遍。这个状况在支付
宝持续了很长时间,非常痛苦。支付宝从淘宝剥离出来的时候,淘宝和支付宝之间
的通信也面临同样的问题,那是2005年的事情,支付宝的架构师鲁肃提出用
MQ(MessageQueue)的方式来解决这个问题,我负责淘宝这边读取消息的模块。但
我们发现消息数量上来之后,常常造成拥堵,消息的顺序也会出错,在系统挂掉的
时候,消息也会丢掉,这样非常不保险。然后鲁肃提出做一个系统框架上的解决方
案,把要发出的通知存放到数据库中,如果实时发送失败,再用一个时间程序来周
期性地发送这些通知,系统记录下消息的中间状态和时间戳,这样保证消息一定能
发出,也一定能通知到,且通知带有时间顺序,这些通知甚至可以实现事务性的操
作。
在“千岛湖”项目和“五彩石”项目之后,淘宝自家的系统也拆成了很多个,他们之间也需要类似的通知。例如,拍下一件商品,在交易管理系统中完成时,它
需要通知商品管理系统减少库存,通知旺旺服务系统发送旺旺提醒,通知物流系统
上门取货,通知SNS系统分享订单,通知公安局的系统这是骗子……用户的一次请
求,在底层系统可能产生10次的消息通知。这一大堆的通知信息是异步调用的(如
果同步,系统耦合在一起就达不到拆分的目的),这些消息通知需要一个强大的系
统提供支持,从消息的数量级上看,比支付宝和淘宝之间的消息量又上了一个层
次,于是按照类似的思路,一个更加强大的消息中间件系统就诞生了,它的名字叫
做Notify。Notify是一个分布式的消息中间件系统,支持消息的订阅、发送和消
费,其架构图如下所示。
NotifyServer在ConfigServer上面注册消息服务,消息的客户端通过
ConfigServer订阅消息服务。某个客户端调用NotifyServer发送一条消息,NotifyServer负责把消息发送到所有订阅这个消息的客户端(这个过程参照HSF一
节,原理是一样的)。为了保证消息一定能发出,且对方也一定能收到,消息数据
本身就需要记录下来,这些信息存放在数据库中(可以是各种数据库)。由于消息
具有中间状态(已发送、未发送等),应用系统通过Notify可以实现分布式事物
——BASE(基本可用(BasicallyAvailable)、软状态(SoftState)、最终一
致(EventuallyConsistent))。NotifyServer可以水平扩展,NotifyClient
也可以水平扩展,数据库也可以水平扩展,从理论上讲,这个消息系统的吞吐量是
没有上限的,现在Notify系统每天承载了淘宝10亿次以上的消息通知。
下图展示了创建一笔交易之后,TC(交易中心)向Notify发送一条消息,后续
Notify所完成的一系列消息通知。
TDDL
有了HSF和Notify的支持,在应用级别中,整个淘宝网的系统可以拆分了,还
有一个制约系统规模的更重要的因素,就是数据库,也必须拆分。
在第二部分中讲过,淘宝很早就对数据进行过分库的处理,上层系统连接多个
数据库,中间有一个叫做DBRoute的路由来对数据进行统一访问。DBRoute对数据进
行多库的操作、数据的整合,让上层系统像操作一个数据库一样操作多个库。但是
随着数据量的增长,对于库表的分法有了更高的要求,例如,你的商品数据到了百
亿级别的时候,任何一个库都无法存放了,于是分成2个、4个、8个、16个、32
个……直到1024个、2048个。好,分成这么多,数据能够存放了,那怎么查询它?这时候,数据查询的中间件就要能够承担这个重任了,它对上层来说,必须像查询
一个数据库一样来查询数据,还要像查询一个数据库一样快(每条查询在几毫秒内
完成),TDDL就承担了这样一个工作。
另外,加上数据的备份、复制、主备切换等功能,这一套系统都在TDDL中完
成。在外面有些系统也用DAL(数据访问层)这个概念来命名这个中间件。
TDDL实现了下面三个主要的特性:
-数据访问路由——将针对数据的读写请求发送到最合适的地方;
-数据的多向非对称复制——一次写入,多点读取;
-数据存储的自由扩展——不再受限于单台机器的容量瓶颈与速度瓶颈,平滑迁
移。
下图展示了TDDL所处的位置。
下图展示了一个简单的分库分表数据查询策略。
下面是TDDL的主要开发者之一沈询讲述的“TDDL的前世今生”——数据层的发
展历程。
CommonDAO的时代
数据切分并不算是一个很新的概念,当商品库切分为两个时,就已经出现了名
字叫做xingdian(笑,那时候行癫已经不写代码了,但从代码的版本信息可以看到
作者)的人写的CommonDAO。
CommonDAO的思路非常简单实用,因为淘宝主要在使用ibatis作为访问数据库
的DAO层,所以,CommonDAO的作用就是对ibatis层做了一个很浅的封装,允许你
通过商品字串ID的第一个字符来访问两台数据库中的一台。
比如,如果字符串ID的第一个字符是0~7,那么走到数据库1去,如果是8~f,则走到数据库2去。同时,也允许用户直接给定数据库的名字来访问数据库。
这应该是最早的数据层原型。
TDDL1.0时代
后来,大家逐渐发现,如果按照业务的发展规模和速度,那么使用高端存储和小型机的Oracle存储的成本将难以控制,于是降低成本就成了必然。
如何能够在不影响业务正常发展的前提下,从一定程度上解决成本的问题呢?
“对一部分数据库使用MySQL”,DBA们的决策是这样,于是,分布式数据层的
重担就落到了华黎的头上。
别看现在数据水平切分似乎已经成了基础知识。在2007年、2008年,如何设计
它还真是让我们伤透了脑筋。
当时的我们,只知道eBay有一个数据层,却不知道如何设计和实现?
于是邀请了当时所有的业务负责人来畅想数据层的样子……
得到了以下需求:
-对外统一一切数据访问;y支持缓存、文件存储系统;
-能够在Oracle和MySQL之间自由切换;
-支持搜索引擎。
然后,我们自己的问题与现在大家所问的问题也是完全一样的。
如何实现分布式Join(连接)?——在跨节点以后,简单的Join会变成M×N台
机器的合并,这个代价比原来的基于数据库的单机Join大太多了。
如何实现高速多维度查询?——就像SNS中的消息系统,A发给B一个消息,那
么A要看到的是我发给所有人的消息,而B要看到的是所有人发给我的消息。这种多
维度查询,如何能够做到高效快捷呢?
如何实现分布式事务?——原始单机数据库中存在着大量的事务操作,在分布
式以后,分布式事务的代价远远大于单机事务,那么这个矛盾也变得非常明显。
华黎带着我和念冰,坐在那里讨论了一个半月,还是没想出来……于是决定先动
起手来。名字是我起的——TaobaoDistributedDatalayer(TDDL,后来有人对它
取了个外号:“头都大了”⊙﹏⊙b)
学习开源的AmoebaProxy。
找到的目标应用是“收藏夹”,首先要做的两个关键的特性是:分库分表和异
构数据库的数据复制。
开始本来希望和B2B的团队合作,因为我们觉得独立的Proxy没有太大必要。而
SQL解析器因为有淘宝特殊的需求,所以也需要重写。
可惜,最后因为B2B的人搬到滨江去了,交流十分不畅,所以最后只是做了拿来
主义,没有对开源的Amoeba和当时的Cobar有所贡献。
回到淘宝,因为有东西可以借鉴,我们在一个多月的时间内就完成了TDDL1.0
版本的工作。上线过程中虽然出了点小问题,不过总体来说是比较成功的。
TDDL2.0时代
随着使用TDDL的业务越来越多,对业务方来说,DBA对于使用MySQL以及数据切
分也积累了比较多的经验,于是决定开始动核心应用了。
“评价”是第一个重要的应用,评价最重要的问题还是在于双向查询、评价、被评价。于是我们的异构数据源增量复制就派上了用场。
然后是“商品”,我们在商品上投入了近半年的时间,失败很多,也成长得最
快。
-容量规划做得不到位,机器到位后因压力过大,直接死掉,于是产生了数据库
容量线上压力模拟测试。
-历史遗留问题,商品几乎是所有的业务都会使用的资源,所以接口设计比较复
杂。很多接口的调用在新架构上很难以低成本的方式实现。而推动业务改动,则需
要大量的时间和成本。
-数据层代码被业务代码侵染,看起来似乎应该是数据层的代码,但实际上又只
有商品在使用。这种问题让数据层的依赖变得更加庞大,边缘代码变得更多,冲突
更明显。
TDDL3.0~TDDL4.0时代
在商品之后,似乎所有的应用都可以使用类似的方式来解决业务增长上量的问
题。但正当我们志得意满的时候,却被“交易”撞了一个满怀。
我一直很感谢交易线的所有同仁,他们是淘宝草根精神的典型代表——功能可
以做得不那么“漂亮”,但必须减少中间环节,真正做到了实用、干净、简洁。我
们在向他们介绍产品的时候,他们对我们的实现细节提出了非常多的质疑,他们认
为整个流程中只有规则、主备切换对他们是有意义的,而解析、合并则是他们所不
需要的功能。
“不需要的功能为什么要放到流程里?增加的复杂度会导致更多的问题”。在
当时,我感到很痛苦,因为我无法回答他们这些质疑之声。
不过,也正是因为这些质疑,让我有了一个契机,重新审视自己所创造出来的
产品。
我问自己:它能够给业务带来什么益处?
对此,我的回答是:
-规则引擎切分规则可以用配置的方式帮助业务隔离具体的数据库地址与用户
的业务逻辑;
-单机主备切换;
-数据源简化和管理。于是,我们就产生了TDDL3.0版本。其主要的作用就是将
代码做了逻辑切分,将单机主备切换和数据源管理独立了出来。这样,可以针对不
同的业务需求,给予不同的逻辑分层。让每一个业务都有适合自己的使用数据库的
方式。
同时,我们开始做工具,RtoolsJADE作为数据库运维平台的组件被提了出
来。在它的帮助下,我们发现能够极大地提升用户在使用单机数据源和多机数据源
时的效率。用户只需要在客户端给定两个属性,就可以立刻开始使用。结果是用户
反馈比以前好了很多。
这也坚定了我们开发工具的决心。
工具平台时代
在尝到工具平台的甜头以后,我们在工具组件上走得更远了。
首先被提出的是“愚公”数据迁移平台。该平台能够在多种异构的数据库中进
行数据的平滑移动,对业务影响很小,并且也允许业务插入自己的业务逻辑。
这个东西主要能够帮助业务进行数据库自动扩容,自动缩容,单机、多机数据
迁移,在Oracle到MySQL数据迁移等场景中都发挥了重要的作用。
然后,又以内部开源的方式提出了“精卫”数据增量复制平台。这个平台基于
数据库的通用数据分发组件,基于开源的Tungsten进行了大量BugFix和结构调优。
在数据的一对多分发以及异步通知给DW和搜索等场景中都发挥了重要的作用。
TDDL的现在
粗略统计下来,TDDL已经走过了4年的时间,满足了近700个业务应用的使用需
求。其中有交易商品评价用户等核心数据,也有不那么有名的中小型应用。量变产
生质变,如何能够更好地帮助这些业务以更低的成本更快地完成业务需求,将成为
数据层未来最重要的挑战。
Session框架
介绍Session框架之前,有必要先了解一下Session。Session在网络应用中称
为“会话”,借助它可提供客户端与服务系统之间必要的交互。因为HTTP协议本身
是无状态的,所以经常需要通过Session来解决服务端和浏览器的保持状态的解决
方案。用户向服务器发送第一个请求时,服务器为其建立一个Session,并为此
Session创建一个标识,用户随后的所有请求都应包括这个标识号。服务器会校对
这个标识号以判断请求属于哪个Session。会话保持有效,默认状况下,直到浏览
器关闭,会话才结束。
Session中存储的内容包括用户信息:昵称、用户ID、登录状态等。
当网站服务器只有一台的时候,用Session来解决用户识别是很简单的,但是
当网站是一个集群的时候,同一用户的两次请求可能被分配到两台不同的服务器上
处理。怎样保证两次请求中存取的Session值一致呢?还有一个问题:网站规模扩
大时,对于一个具有上亿个访问用户的系统来说,当大部分用户的Session信息都
存储在服务端时,要在服务端检索出用户的信息效率就非常低了,Session管理器
不管用什么数据结构和算法都要耗费大量内存和CPU时间。如何解决服务端Session
信息的管理?
解决集群Session共享的问题,通常有以下两种办法。
-硬件负载,将用户请求分发到特定的服务器。
-ySession复制,就是将用户的Session复制到集群内所有的服务器。
这两种方法的弊端也很明显:
-成本较高。
-性能差。当访问量增大的时候,带宽增大,而且随着机器数量的增加,网络负
担成指数级上升,不具备高度可扩展性,性能随着服务器数量的增加急剧下降,而
且容易引起广播风暴。
这种情况下,Tbsession框架闪亮登场了。Tbsession框架致力于解决以下几
个问题。
-Session的客户端存储,将Session信息存储到客户端浏览器Cookie中。
-实现服务端存储,减少Cookie使用,增强用户信息的安全性,避免浏览器对
Cookie数量和大小的限制。
-Session配置统一管理起来,集中管理服务端Session和客户端Cookie的使用
情况,对Cookie的使用做有效的监管。
-支持动态更新,Session的配置动态更新。
简单地说,就是要么用客户端Cookie来解决问题,要不用服务端的集中缓存区
(Tair)的Session来解决登录问题。Tair已在前文介绍过,Session对它的使用
就不再描述了。
为什么这里还要提到用Cookie这种比较“落伍”的方式呢?其实是因为在淘宝
3.0版本以前,我们一直都用Cookie来识别用户,Cookie是放在客户端的,每一次
HTTP请求都要提交到服务端,在访问量比较小的时候,采用Cookie避免了Session
复制、硬件负载等高成本的情况。但随着用户访问规模的提高,我们可以折算一
下,一个Cookie大概是2KB的数据,也就是说,一次请求要提交到服务器的数据是
网页请求数据,再加上2KB的Cookie,当有上亿个请求的时候,Cookie所带来的流
量已经非常可观了,而且网络流量的成本也越来越高。于是在3.0版本中,我们采用
了集中式的缓存区的Session方式。
到此为止,应用服务切分了(TM、IM)、核心服务切分了(TC、IC)、基础服
务切分了(UIC、Forest)、数据存储切分了(DB、TFS、Tair),通过高性能服
务框架(HSF)、分布式数据层(TDDL)、消息中间件(Notify)和Session框架
支持了这些切分。一个美好的时代到来了,高度稳定、可扩展、低成本、快速迭
代、产品化管理,淘宝的3.0系统走上了历史的舞台。
在这个分布式系统的支持下,更多的业务迅速开发出来了,因为任何一个业务
都基于淘宝的商品、交易、会员、评价等基础体系,而这些基础体系就像“云”一
样存在,现在可以随处调用了。Hitao、淘花网、良无限、天猫、一淘、聚划算、各种SNS、各种移动客户端等如雨后春笋般地成长起来了。目前,淘宝已经变成了一个
生态体系,包含C2C、B2C、导购、团购、社区等各种电子商务相关的业务。
既然说是一种“生态体系”,那就不能把所有的业务把控在自己的手中,在开
发3.0版本的过程中,我们就有一个团队把淘宝“开放”出去了,我们把自己的数
据、自己的应用通过接口的方式让更多的开发者调用,他们可以开发出形形色色的
产品,例如,你可以开发出心形的淘宝店铺、菱形的店铺,再放到淘宝上供商家购
买。淘宝再多的员工,其创造力也是有限的,而开放出去之后,让无限的人都可以
参与到这个生态体系的建设中来,这个生态体系才是完整的。下面就是开放平台的
架构师放翁所记述的“开放平台这几年”注11。
开放平台
2006年年底:阿里巴巴提出了Workatalibaba的战略,二十多个人就被拉到湖
畔花园马云的公寓里开始一个叫阿里软件的公司创业。当时对于Workatalibaba有
一个朦朦胧胧的感觉,就是要为中小企业提供一个工作平台,但是工作平台又需要
是一个开放的平台,因为卖家的需求是长尾的,当时火热的Salesforce给了阿里人
(注1作者放翁在文中涉及的所有技术点都可以在
http:blog.csdn.netcenwenchu79中找到详细的内容,同时本文主要介绍开放
平台技术发展历程,产品和业务内容不涵盖在此,因此,受众群体主要是技术人
员。——作者注)一些启示,那就是做一个支持二次开发的工作平台,半开放式地
满足各种卖家的长尾管理需求。此时,软件市场上就开始培养起最早的一批TP(淘
宝开放合作伙伴)。迄今为止,很多非常成功的TP就是从那个时候开始进入淘宝卖
家市场的。
但经过一年的平台建设,发现开发者非常难利用平台做二次开发,只有阿里软
件公司内部的团队构建了三个不同的CRM软件。这时候淘宝来了一个业界的技术牛人
王文彬(花名:菲青),这位淘宝新晋的首席架构师找到阿里软件的平台架构团
队,谈到了当时业界还非常新颖的一种技术平台——开放平台。由于阿里软件已经
在做类似的开放工作,希望能够以合作的方式来试水开放平台。当时双方都是一种
尝试的态度,因此,最后敲定投入一个人花两周时间,看是否能够做出原型,如果
可以,就继续做,如果出不了原型,就此结束。两周时间里,负责阿里软件的架构
师放翁参看着美国雅虎的开放模式就搞出了开放平台的第一个雏形,没想到就这样
开启了5年的开放之路。后面会根据时间轴来说一下开放平台的产品和技术的变革,每一年会发生很多事情,但是调出的一点一滴是当年最有感触的。
2007年:萌芽。SOA盛行的年代,内部架构服务化成为开放的第一步,内部服
务不做好隔离,开放就意味着风险不可控。支付宝今天的服务框架SOFA(类
ESB)、淘宝的HSF(OSGI)、阿里软件的ASF(SCA)都是那个年代的产物,但服务化带来的痛却是一样的,不论是OSGI还是SCA之类的服务框架,本身的服务化规约
设计都类似,但难题也都摆在每个架构师和开发者面前:服务单元Bundle的粒度控
制,服务之间依赖管理,性能与规范的冲突,调试与隔离的平衡。这些都使得一线
开发者和平台框架实现者出现非常多的矛盾,而这个过程能活下来的框架最后都是
摒弃了很多企业级的设计思路,因为SOA架构从企业级产品演变而来,而服务化后的
内部平台要面对的开放平台天生就是互联网的产物。
2008年:雏形。2008年年底,平台开放淘宝服务30个,每天调用量2000次,这
一年开放平台的开发者面向的客户主要是阿里巴巴上的中小企业和淘宝C店卖家。开
放平台建设初期要解决的就是三个问题:
-服务路由。(外部可以获取内部信息)
-服务接口标准化。(统一方式的获得各种标准化信息)
-授权。(外部合法的获取内部信息)
服务路由其实就是写一个高效的HttpAgent,服务接口标准化就是对象文本化
(JSON,XML)。今天在各大开放平台广为使用的OAuth协议,当前处于0.6版本,没有任何实际的互联网开放平台使用,直到Google于2008年年底慢慢地对外推广开
放的时候,OAuth被封装到Google的OpenSDK中,才使得很多中小型互联网公司使
用这种看似复杂的两阶段授权交互模式。淘宝初期采用的是自有协议,因为OAuth2
以前的逻辑较复杂且使用不方便,直到2011年才开始支持OAuth2,同时做了部分的
安全增强。授权解决了开放最大的一个问题:用户安全的对应用访问其数据受信。
用户从此不用赤裸裸地将用户名和密码交给一个应用软件,应用也可以在允许的范
围内(操作、数据、授权时长)充分利用用户授权来玩转创意。
用户名密码UserAPP用户名密码网站UserAPP应用受信令牌用户名密码授权网站
有了上面的三板斧(路由、数据规范和授权),开放平台正式开门迎客了,没有对
外做任何的推广,日均调用数据就猛增到了1000次,此时两个互联网的新兴技术
Memcached和Hadoop开始在开放平台中尝试。今天看来,这两个技术已经被大规模
地使用,Memcached无疑是最好的选择,但当时号称分布式缓存的Memcached其实
是集中式缓存的一种,真正的分布式缓存还都在纠结于一致性和效率的问题(第2、3阶段提交)。此时需要有一种方式能够保证效率(可扩展)和稳定性,于是我们封
装了Memcached客户端,提升当时BIO的Java客户端的性能,同时引入了客户端负载
均衡和容灾的设计,这种设计已经被应用在现在很多大型分布式系统中。另一方
面,每天上千万的访问也让技术和产品对访问的行为有很强的分析需求,此时,Hadoop在雅虎的充分利用引起了我们的重视(当时的雅虎技术创新一直都是业界的
领头人),通过仅有的两台机器和一堆技术文档,我们摸索着搭建了公司内部的第
一个Hadoop集群,而所写的Hadoop入门实践也成为当时Hadoop入门的基础文档,对于每天2000次调用量的日志分析需求来说,Hadoop用得游刃有余,但随着业务的
不断发展,Hadoop离线分析所带来的问题也凸显出来,MR程序面对灵活多变的分析
需求,显得不易维护且效率低下(数据反复读取分析),于是我们也开始思考怎样
改进这个新玩意儿。
2009年:产品化。到2009年年底,平台开放淘宝服务100多个,每天调用量为
4000次,这一年开放平台的开发者面对的主要是淘宝C店卖家,卖家工具成为服务市
场的主流。这一年也是变化的一年,阿里软件年中的分拆使得开放平台的归属有些
微妙,一种情况是留在阿里云,作为集团的基础设施,另一种情况就是跟着主要的
业务需求方淘宝走,最后我们还是说服了博士,结束了阿里软件的老平台,淘宝正
式开始自己的开放之路。来到淘宝后,业务开放迅猛增长,从30个API猛增到了100
个API,没有对外做任何业务推广,平台调用量到了年底翻番。此时技术上的挑战又
聚焦到了性能上,一次APICall的业务消耗平均在30~40ms,开放平台当时的平台
处理消耗平均在10ms左右。我们做了数据打点和分析,发现最大的消耗在于互联网
数据的接收,同时大量的图片数据上行,更是加大了平台处理时间。另外,从访问
日志分析中可以看到很多无效的请求也占用了非常多的处理时间,这也意味着无效
请求和有效请求一样在消耗着有限的容器线程资源。于是我们开始尝试自己封装字
节流解析模块,按需解析上行数据,一来可以提升数据分析的性能(并行业务和数
据增量分析操作),二来可以用最小代价处理异常请求(当发现不满足业务规范
时,则立刻丢弃后续所有的数据),这块实现被叫做LazyParser,主要的实现重点
就是最小化数据缓存来进行并行业务和数据解析操作,上线后效果不错,整个系统
平均处理时间从10ms降低到了4ms。(包含了异常处理的优化和解析性能的提升)
另一方面,Hadoop的MR问题也日益突出,一大堆MR的Class(类)维护成本
高、性能问题也随之出现。此时我们开始尝试抽象分析业务场景,想到的是是否能
够通过配置就可以完成各种统计分析需求。要用配置替代代码,其实就看是否可以
穷举代码所实现的各种统计需求。当回顾SQL的理念时,发现其实所有的统计在切割成为KV作为输入输出时,所涵盖的需求无非是Max、Min、Average、Sum、Count、Distinct(这个是2012年实现的,用了bloomfilter和AtomicLong),再
复杂一些无非就是上述几个操作结果的数学表达式运算。因此,KV输入和KV输出的
离散统计配置需求已经抽象出来了,接着就是把统计完的一组组KV根据K来做
Groupby(分组),就生成了传统意义上的报表(K,v1,v2…)。从此以后,每天
的统计需求都通过配置来改变,再也没有一大堆MR代码,同时一次数据输入就可以
完成所有分析的处理,性能上得到了极大的提高。
虽然Hadoop每日分析抽象出模型配置解决了性能和易用性的问题,但是对于即
时分析却不太适合,当时出于监控的需求,希望能够一个小时就可以对数据做一次
增量的分析,用于监控服务整体的调用情况,保证对异常问题的即时排查。由于一
天4000次的调用量还不算很大,因此,当时就直接考虑采用MySQL分库分表的方
式,然后定时做SQL的查询,结果发现效果不错。当然,这个过程又产生了一个小组
件,要直到4000次的日志数据写磁盘和DB双份必然会带来不少的IO消耗,同时这
个系统并不是账务系统,丢掉一点日志也没关系。因此,就采取了异步批量数据外
写的设计(多线程守护各自的一块Buffer页,定时外刷或者满页外刷),这样在双
写的情况下,单机的Load也没有超过0.7。
但快到年底的时候,发生了一件事情让我们头痛不已,同时也成了开放平台的
一个“隐形炸弹”。一天晚上,突然发生平台大规模拒绝服务的告警,观察整个集
群发现,业务处理时间从平均的30~40ms,上升到了1s,仔细观察发现,某一个业
务的响应时间大幅攀升,从原来20ms的响应时间飙升到了1s以上,此时由于HTTP请
求的同步性,导致前端服务路由网关的集群线程都释放得非常慢,阻塞处理这个业
务的请求,而其他正常的业务(淘宝开放平台背后的服务由不同的团队维护,处理
时间从1ms到200ms都有)也无法被访问,因此,才有了开始的全线告警的产生。后
来发现是这个业务团队的一次发布中忽略了数据库索引建立导致服务耗时增加,但
这个问题开始时不时地拜访开放平台,开放平台稳定性受制于任何一个业务方,这
是不可接受的。对于这个问题,起先考虑集群拆分,即将重要业务和不重要业务拆
分,但考虑到实施成本(不同服务的利用率差异很大)和业务隔离是否彻底(重点
业务也会相互影响),最终放弃了这个想法。当时又想到了软负载切割Haproxy和LVS,一个是七层的网络软负载切割,一个是四层的负载切割,由于涉及业务,于是
考虑用七层的软负载切割,尝试一台Haproxy挂7台虚拟机,然后运行期可动态调
整,配置在出现问题的时候可人工干预切割流量。就这样,我们有了告警以后可以
手动切割的半人工方式干预措施。但我们依然晚上睡不踏实……(期间考虑过Web请
求异步化和Servlet3的模式来规避同步HTTP带来的平台阻塞,但当时唯一支持
Servlet3的Jetty和Tomcat做压力测试,效果都很不稳定)
2010年:平台化。到2010年年底,平台开放淘宝服务300多个,每天调用量为8
亿次,这一年淘宝正式开始对外宣传开放,淘宝开放年赢在淘宝,目前很多年收入
上千万的TP在这个时候成了先锋(2010年以前的可以叫做先烈),产品层面上,这
一年除了卖家工具的继续发展,SNS热潮的兴起带动了淘江湖的买家应用,游戏应用
的淘金者蜂蛹而入,开放的服务也继续保持300%的增速,覆盖面从卖家类延伸到了
买家类,从简单的API提供,到了淘宝网站支持深度集成应用到店铺和社区。
在8亿次访问量的情况下,再用MySQL做流式分析已经不可能了,分析时间要求
也从一个小时提升到了20分钟,此时经过快一年半的Hadoop使用和学习,再加上对
分布式系统的了解,正式开始写第一版的流式分析系统,MR的抽象依旧保留,而底
层的数据计算分析改用其他方式,这个“其他方式”和Hadoop的差异在于:
-分析任务数据来源于远端服务器日志(主要通过Pull,而非Push)。
-任务分配和调度采用被动分配(有点类似于VolunteerComputing的模式),Mater轻量的管理任务,Slave加入即可要求执行任务,对任务执行的情况不监控,只简单通过超时来重置任务状态。
-任务统一由Master来做最后的Reduce,Slave可以支持做Shuffle来减少数据
传输量和Master的合并压力,Master负责统一输出结果到本地。
总的来说,就是数据来源变了,数据不通过磁盘文件来做节点计算交互(只在
内存使用一次就丢掉了),简化任务调度,简化数据归并。这样第一版本的流式分
析出来了,当然,后面这些设计遇到的挑战让这个项目不断在演进,演进的各种优
化几年后发现都在Hadoop或者Hive之类的设计中有类似的做法。(参看Blog,地址
为http:blog.csdn.netcenwenchu79,根据时间轴可以看到各种结构优化和性
能优化的过程)这个系统三台虚拟机撑住了8亿次的日志即时分析,MySQL日志分析
就此结束。
这一年另一个重大改变就是更多的人对开放的价值有所认同,淘宝从一个部门
的开放走到了淘宝公司的开放,什么叫做部门开放?就是在10年以前大部分的API开
放都是开放平台这个团队来做封装维护,30个API还可以支撑,100个API已经让一
个专业的小团队应接不暇(当然不得不承认,迄今为止,淘宝最有全局业务知识的
还属这个团队的成员),300多个API这种势头基本上就无法由一个团队来做了,业
务变更带来的接口不稳定经常被投诉。因此,我们启动了服务轻量化的“长征项
目”,逐渐通过工具和平台将服务接入变成自动化的方式,将原来开放一个服务需
要点对点,手把手花一周时间实施完成的过程,通过自动化服务发布平台,一个人
一天时间就可以发布一个服务,并且服务的文档中,多语言版本SDK都自动生成。这
样就具备了服务轻量化的基础,然后将各个新开放的业务采用这种模式接入,而老
业务逐渐归还给各个业务方去维护。这样,服务的“稳定性”(业务方面)得到了
非常大的提升,用户对于服务的满意度也得到了极大的提高。
但这个担子放下了,那个担子又挑上了,在上面谈到后台应用不稳定导致平台
整体不稳定的问题在轻量化以后出现的频率和次数更多了,因为发布和维护都落到
了后台部门,此时对于各个系统的把控就更弱了,KPI中的稳定性指标基本就没法定
了。唯一能够彻底解决问题的办法就是HTTP服务异步化+事件驱动+虚拟隔离线程
池。2010年年中对Jetty7做了一次压测,发现Continuations的效果已经可以上正
式的环境了,于是开始在Jetty7的基础上做HTTP服务异步化+事件驱动的封装,同
时也实现了一个虚拟隔离线程池做配合。具体设计细节这里就不再多说,参看
Blog,简单描述原理如下:
-将前端容器线程和业务处理隔离。(类似NIO和BIO的设计差异)
-业务处理如果依赖于外部系统,则采用事件驱动的方式来减少线程等待,同时
提高线程占用资源的利用率。(从这点上说,理想和现实还是有很多细节差异的,在实现的时候必须根据依赖系统消耗时间占总时间的比例看是否需要事件驱动,事
件驱动带来的切换消耗是比较大的)
-通过一个大的线程池虚拟设置不同的业务可消耗的最大资源数,来充分共享资
源在异常情况下限制业务占用过多的资源(任务处理开始排队,而非无度地占用资
源)。
这个组件上线以后,没过几天就发生了一个典型的案例,一个业务在下午2点开
始响应时间从10ms上升到了40ms,然后继续上升到200ms,当时给这个业务模拟设
置最大的线程资源数是20个,就发现那时候由于RT时间提升,线程资源释放得慢,20个慢慢地被消耗完了,此时这个业务的队列开始从0到100,再到200……(当然,防止内存过多地被占用,会丢弃超过队列长度的业务处理),而其他业务还是正常
地使用着资源,平台平稳,到了下午4点多,业务方收到告警修复以后,RT时间下降
到了10ms,队列中的请求数量开始减少,最后队列清空,线程资源占用下降到正常
水平。
从此以后,震子开心地和我说:开放平台稳定性的KPI可以随便大胆地写几个9
了。
2011年:市场化。到2011年年底,平台开放淘宝服务758个,每天调用量19亿
次,这一年SNS热潮消退,游戏逐渐淡出,卖家市场依旧生意火爆,营销工具崭露头
角,成为开发者新宠,淘宝客成为开放新宠(这一年返利网和团购一样火,只是前者收钱,后者烧钱)。
就在开放平台前景一片大好的时候,出现了一个让开放转变和收缩的导火索,一家做营销工具的公司“团购宝”每天凌晨都会通过接口同步客户设置的一些优惠
商品信息到淘宝网,结果那天凌晨,微博上突然有很多人说某些店都是一块钱的便
宜货,要知道这种事情在微博盛行的时代,传播速度之快,影响之大,当即很多卖
家商品都被1块钱拍下。最后发现是线下的商品价格不知道怎么全被修改成1块钱,然后凌晨一同步,就导致出现了上面的一幕。从那时候开始,开放平台的KPI中增加
了一个重中之重的功能:安全,包括后面的很多技术产品都围绕安全展开。此时第
一个被波及提升能力的系统就是流式分析集群,20分钟一轮的数据分析要求压缩到3
分钟,同时数据量已经从每天8亿条增长到了每天19亿条,花了两个月时间断断续续
地优化集群结构设计和单机处理能力,对于其中经历的内容,有一天我翻Hadoop的
优化过程时看到了相似的场景,具体就不在这里赘述,详细内容可参考Blog。简单
地说,包括四个方面:充分利用多核能力用计算换内存;磁盘换内存,用并行设计
来保证整体业务时间消耗不变甚至减少;SlaveShuffle来减少Mater的合并压力;
数据压缩减少数据传输消耗和内存占用。
另一方面,由于2010年对于Jetty7的充分理解和封装,此时看到了又一个新技
术的契机,2010年去美国参加Javaone,当时看到有老外用Jetty7的特性来实现
Comet功能,Comet原先主要用于CS结构的应用搬到互联网上,因为不能用TCP的长
连接,所以不得不用HTTP的长连接来替代原来的模式,同时国外开放平台也关注很
多新型的API设计,其中就有Twitter的StreamingAPI,这种通过HTTP长连接方式
推送消息到外部ISV(独立软件开发商)的模式引起了我们的注意。因此,我们决定
将Jetty7上的封装近一步升级,支持Comet长连接方式,后端通过事件驱动的模式
主动推送内部消息给外部,避免外部轮询业务接口。这个设计最重要的一点就是如
何用最有效且最少的线程来守护多个长连接,支持到后端事件驱动的数据下行,如
果给每一个长连接支持一个数据推送守护线程,即时性自然最高,但代价就是消耗
众多空置连接的守护线程(详细内容见Blog)。这种模式刚出来的时候,从上到下
都是质疑声,觉得太不符合常规做法,常规做法就是pull,认为开发人员无法接
受,稳定性一定不靠谱。经过2011年的“双十一”,当天几个“尝鲜”的开发者用一台PC就支持几百万笔订单的高速处理,就让很多人明白了,技术要敢想,代码要
敢写,细节要敢专,没什么不可能。也就从这以后,多样化服务TQL、ScheduleAPI、ATS从开放平台的土壤上都长了出来,为更多的场景和更多的终端提
供了各种解决方案和创新实现。
2012年:垂直化。这一年到现在,平台开放淘宝服务900多个,每天调用量为
25亿次,这一年淘宝客由于公司方向转变热潮消退,无线乘势而起,新业务(机彩
票、酒店、理财等)、P4P、数据类服务都开始运营API,开放平台开发者的客户群
体也从C店卖家增加到了B的品牌商和渠道商等。
这是一个业务多变的一年,这也是淘宝内部对开放平台认可的新阶段。第一个
阶段是放任不管,任由开放平台部门开放和封装。第二阶段是由业务方负责支持开
放业务,但开放后的结果概不了解,也无所谓了解。第三阶段就是业务主动要开
放,开放后开始运营服务,培养ISV市场,带动业务的正向发展。
这一年由于业务量的增长以及分析需求到用户纬度,因此,在2011年年底启动
了流式分析集群重构升级的项目,将新的分析集群项目命名为Beatles,希望它能
够象甲壳虫一样,小虫吃树叶,再多都能吃下。2011年底到2012年初,用了近两个
半月的时间做了一次完整的重构,将那么多年的补丁经验和老代码重新设计和实
现,并且将Mater根据业务可垂直切分,最终解决Master归并压力的问题,当然期
间的技术优化点也不少,因为我们的目标从3分钟压缩到了1分钟,而我们的数据量
翻番,统计纬度细化到了用户纬度。(意味着结果也会很大,如果不靠文件做中
转,如何来实现需要更多的分拆和协同设计)
这一年起了两个比较创新的项目:JSSDK和无线SDK(IOS,安卓),这两个SDK
的出现在一定程度上由业务和安全两方面决定。首先,2011年年底启动了社区电子
商务化的项目,也就是现在所说的轻电商(XTao)项目,将更多的网站和淘宝衔接
起来,此时网站间的融合就要求更轻便和简易,最成功的案例就是Facebook,于是2012年年初的时候,拿这FackBook的JSSDK一阵看,就开始动手写了,期间很高兴
拉了UED入伙,这才使得这个JSSDK变得更加靠谱,更加专业。同时有了JSSDK,买
家的服务安全性有所保证,因为原先的REST调用在授权以后是无法知道是用户发起
的还是服务器发起的,而JSSDK从一定程度上还要校验Cookie的有效性,可以部分
保证用户的在场和知情。而下半年的无线SDK,就是苦读一个月的各种文档,然后就
开始动手玩儿了,由于对Java语言、动态语言、脚本语言都有比较多的使用,因
此,Objective-C语言上手并不是那么困难,同时没有涉及过多的MVC的内容,做
SDK基础层的东西还是比较得心应手的,就这样IOS的无线SDK版本就生成了,此时
在开放平台的技术团队内部正在执行一个叫做Hackproject的活动,其中一个自主
项目就是安卓的SDK,因此,一个月后,安卓的SDK顺利诞生了。这两个无线SDK所
担负的职责就是把控无线安全问题,不仅是淘宝,业界其实很多公司都还没理解无
线开放的风险到底有多大,OAuth2基本就无法保证无线的用户安全,因此,如何在
SDK和服务端融入更高级别的安全设计,成了无线SDK诞生的第一个重要需求。
另一方面,开放平台安全体系的构建成为2012年的重点,从两个角度对安全做
了全方位的控制。
第一,用户。用户授权更细化了授权操作范围(细粒度到了数据范畴),授权
时长。所有的信息可监控、归档、快速定位,我们内部叫做TopOcean,简单说来就
是对所有的访问日志做归档,归档的载体是块状文件,归档时对块状文件的所有记
录按照需求建立索引,然后保留索引,上传本地文件到远端分布式文件系统备份。
实时的监控服务调用和应用访问,授权异动。
第二,第三方应用。采用监控集群对所有ISV的服务器做安全扫描,对普通的
Web安全漏洞做扫描,对应用的可用性和响应时间做监控。同时,正式启动“聚石
塔”项目,提供弹性计算和存储能力及可靠的安全网络环境给ISV,帮助ISV提供自
身应用的安全性。
至此为止,5年左右的技术历程已部分展示在了大家的面前,这些只是5年中比较有代表性的一部分,同时技术的发展也只是开放平台的一部分,前5年是技术变革
带动开放平台发展,而接下去的5年将会是业务变革和理解带动开放平台的阶段,对
业务的理解直接决定了开放平台的价值所在。前面轻描淡写地介绍了5年来不同开放
业务的兴衰,其实这背后却有更多耐人寻味的故事,而5年后的今天,淘宝的格局
为:集市(C2C)、天猫(B2C)、一淘(电商搜索返利入口)、无线、新业务、O2O(本地生活)、团购平台(聚划算),这些平台的价值是什么?如何找到自身定
位?如何借助外力发展?如何面对流量入口的兴起、传统互联网企业的电商化、电
商平台的竞争?这些才是开放平台2012年及下一个5年的精彩所在。
第四部分我在淘宝这八年
“所有的进步都是不稳定的,一个问题解决了,我们不得不面对又一个新问
题。”——马丁?路德?金
2011年12月8日那天,有同事恭喜我,我才知道自己在淘宝已经七周年了。很
多人问“七年痒不痒?”老实说,也曾经痒过,但往往都是一痒而过,然后又投入
到水深火热的工作中去。回家之后就想,我在这七年到底收获了什么,且不论成败
与否,这七年的经历,是我人生的宝贵财富。第一年(2004年—2005年)
@正牌七公曾经说过,要是写一本淘宝的历史书,一定有很多人感兴趣,其实我
也很想写写这样一本书。2004年12月8日入职的时候,我和@衲子如幻一起进来,迎
接我的是骆冰和黄裳@岳旭强,骆冰是百阿的班主任,黄裳是我的师父。当时还没有
百淘,先参加了百阿,百阿给我发了一本书叫《完美商店》,介绍的是eBay的故
事,看的时候我就想什么时候我也写一本关于淘宝的故事来。
我进淘宝非常偶然,当时只是看到这个网站做得不错,自己也不想继续做对日
外包的工作了,就过来面试了一把。刚进淘宝的时候,我被震撼了,它跟传统的企
业非常不一样,到处都是生机勃勃的样子,还有前台的@香香的好朋友笑得很亲切,之前见到的公司前台的态度都是冷冰冰的。@武当三丰给我两张笔试题做,后来居然
通过了。财神面试我的时候,问我为什么到这里来,我说很欣赏这家企业发展这么
快,这样的企业一定有很多高手,跟高手在一起成长一定很快。我每说一句,他点
头“嗯哼”一下,以至于后来我跟我老婆形容公司的CEO时,她只记得那个喜欢“嗯
哼”的人。
来淘宝做的事情是做Java开发,但是之前我只做过3个月的Java项目,连
Eclipse都不熟(我来之前恶补了一下快捷键的操作)。一开始做事是在@岳旭强手
把手的指导下做的,当时非常依赖旁边的几个老员工——多隆、正风、进宝、我
行、不同、范禹、天川。做的事情也没有一个成熟的流程,常常是大家在论坛看到
有人需要什么功能,我们问问PD是不是需要做,然后就写代码,提交给测试人员
(给自在、郭芙、宝驹),最后就让青青打包,让剑英发布。我还很清楚地记得做
的第一个需求是,有卖家说不想把货卖给信誉为一颗心以下的买家;有卖家不想卖
给某个省市的买家,我就给卖家一个工具,让其限制某些买家不能买。于是我就在
发布商品的流程和生成订单的流程中,找到合适的地方,加了几个合适的参数,写
了几段合适的代码,就发布上去了,但是这个功能一直没敢启用。直到3年之后,2008年要拆分Denali的时候,这段代码都在,但都没有发挥作用。
做完第一个需求后,自己写的代码在系统上运行了,一下子有了信心。当时HR
成立了百淘的项目,我先去百淘二期干了几天(本来要我参加一期的,但当时忙,延迟到了二期,现在百淘已经过一百期了),回来就投入到一个更牛的项目——支
付宝。
支付宝一开始生存在淘宝系统上,但到2004年年底的时候,老马的慧眼看到了
支付宝的未来。当时请了Sun公司的人把淘宝的第一个PHP版本变成了Java版,之
后,就让他们做独立的支付宝系统。我和天川从淘宝派出来做支付宝和淘宝相关的
业务,当时除了Sun公司的人和淘宝的人,还来了一位标志性的人物@fenng,他是
这个项目的DBA,记得他刚来杭州时,家里要装宽带,运营商服务不周到,被他骂了
好久。后来(2010年)他在微博上大战中国电信已经相当有经验了。项目组中还有
另外几个让我非常佩服的人——鲁肃、苗人凤,二人后来成了支付宝的首席系统架
构师和业务架构师。就这么跟着这样一帮牛人干了3个月,支付宝在五一节的时候上
线了。还记得几个DBA在做数据迁移时候的囧样,数据结构已经面目全非了,@正牌
七公、@fenng、多隆、鲁肃搞了三天三夜。我们熬夜的时候还有杭州的卖家跑来看
我们,有一位是璧君,后来直接加入了淘宝。
当时那热火朝天的岁月令我至今难忘,我三天三夜没回家的时候,我老婆还打
电话过来问“你到底还爱不爱我了?”我说:“怎么会不爱呢?”
进淘宝的第一年,我的级别是P1,现在已经没有P1了,后来调整过,我当时进
来应该是现在的P3,记得那年年底的时候,三丰给了我4分的评价(超出期望),然
后升级为P4,那是我成长最快的一段时期。
第二年(2005年—2006年)
做完支付宝,公司举办了一场硕大的庆祝仪式,带我们一帮人去了千岛湖,玩
得很爽,但我有点不安,因为我与他们在一起才3个月,实际上只做了3个功能,一
个是创建支付宝交易的接口、一个是接收支付宝订单状态的接口、一个是绑定和解
绑支付宝账号的功能,而其他牛人设计出了一个巨大的系统,我处于深深的拜服
中。半年之后,淘宝网组织的郊游又去了千岛湖,后来,另外两个项目的庆祝也去
了千岛湖,以至于我都认识那边的道路了。
从千岛湖回来,真正苦逼的日子开始了,我很长一段时间都在做善后的工作,就是支付宝系统中的一些问题。由于支付宝和淘宝是两个独立的系统,系统之间的
通信是一个大问题,而银行与支付宝也需要通信,于是问题就经常出现:用户在银
行付款后,未必能通知到支付宝,支付宝收到通知后,未必能通知到淘宝,于是用
户的钱没了,淘宝的系统上却显示未付款,很让人崩溃。我和鲁肃尝试了很多种办
法,一开始用MQ,但并发量上来之后老丢消息,消息的时间顺序也会错,后来他做
了一个消息中间件系统,这个就是淘宝的Notify的雏形,现在Notify一天能发送几
亿条消息通知,能保证通知到,也能保证不重复通知,还能保证消息有次序,相当
不容易。
三丰看我在支付宝方面做了很多事情,而且跟鲁肃他们合作得这么好,还以为
我水平大有长进,于是在维护着支付宝接口的同时,我开始了做PM(项目经理)的
生涯。据说,我是淘宝的第一个PM,这让我很爽,我在做PM的过程中与SQA一起整
理出了《项目管理流程》《PM工作手册》《系统设计模板》等开创性的工作,有些
东西沿用到了现在。但后来有人提出敏捷概念的时候,我又在反思,我是不是误导
了淘宝的项目开发模式很多年?
我的PM生涯从2005年持续到2008年,这三年又大致分两个阶段,一个是“新手
上路”阶段,自己摸索着做了“商品详情拆分”、“收藏夹改造”、“支付宝认
证”几个项目;另外一个是“死去活来”阶段,做了“我的淘宝AJAX版”、“招财进宝”、“淘宝旅行”。为什么是死去活来?因为后面这三个项目死了两个,活了
一个。
“商品详情拆分”是在2005年开始做的,三丰说让我当项目经理,我看到“经
理”两个字就吓得半死,但后来知道该项目组就我和拖雷两个人。要做的事情非常
......
第一部分淘宝技术发展1
引言:光棍节的狂欢
个人网站
LAMP
Oracle支付宝旺旺
第二部分淘宝技术发展2
Java时代
脱胎换骨
坚若磐石
创造技术
TFS
Tair
第三部分淘宝技术发展3
分布式时代
服务化
中间件
HSF
NotifyHSF
TDDL
Session框架
开放平台
第四部分我在淘宝这八年
第一年(2004年—2005年)
第二年(2005年—2006年)
第三年(2006年—2007年)第四年(2007年—2008年)
第五年(2008年—2009年)
第六年(2009年—2010年)
第七年(2010年—2011年)
第八年(2011年—2012年)
第五部分牛P列传
正明——集团核心系统高级研究员
正祥——淘宝高级研究员,OceanBase项目负责人
毕玄——集团核心系统资深技术专家
放翁——淘宝开放平台项目负责人
作为技术专家
作为孩子父亲
作为美女的老公
业余生活丰富多彩
吴翰清——阿里云集团信息安全中心高级安全专家
云铮——数据平台与产品部资深技术专家
淘宝传奇工程师多隆的程序世界第一部分淘宝技术发展1
“所有的进步都是不稳定的,一个问题解决了,我们不得不面对又一个新问
题。”——马丁?路德?金
引言:光棍节的狂欢
“时间到,开抢!”坐在电脑前早已等待多时的小美一看时间已到2011年11月
11日零时,便迫不及待地投身于淘宝商城一年一度的大型网购促销活动——“淘宝
双11购物狂欢节”。小美打开早已收藏好的宝贝——某品牌的雪地靴,飞快的点击
购买、付款,一回头发现3000双靴子已被抢购一空。
小美跳起来,大叫一声“欧耶!”
小美不知道,就在11日零点过后的这一分钟里,全国有342万人和她一起涌入淘
宝商城。当然,她更不知道,此时此刻,在淘宝杭州的一间办公室里,灯火通明,这里是“战时指挥部”,淘宝技术部的一群工程师正紧盯着网站的流量和交易数
据。白板上是他们刚刚下的赌注,赌谁能最准确地猜中流量峰值和全天的交易总
额。他们的手边放着充足的食物和各类提神的饮料。
一阵急促的电话铃声响起,是前线部门询问数据的,工程师大声报着:“第1分
钟,进入淘宝商城的会员有342万人”。过了一会儿,工程师主动拿起电话:“交易
额超过1亿元人民币了,现在是第8分钟。”接下来,“第21分钟,刚突破2亿
元”,“第32分钟,3亿元了”,“第1个小时,4.39亿元”。这些数据随后出现在
微博上,引起了一片惊呼。
“完蛋了!”突然有人大喝一声,所有的眼睛都紧张地盯着他,只见他挠挠
头,嘿嘿地笑道“我赌得少了,20亿元轻松就能过了,我再加5亿元。”他跑到白板
边上把自己的赌注擦去,写上25,接下来有人写上28,有人写上30,有人到微博上
开下盘口,同事们纷纷转载下注。接下来的这24个小时,战时指挥部的工程师们都
不能休息,他们盯着网站的各种监控指标,适时调整机器,增减功能。顶住第一波
高峰之后,这些人开始忙里偷闲地给自己买东西,大家互相交流着哪家买的移动硬
盘靠谱,哪家衣服适合自己的女朋友,不时有人哀嚎宝贝被人抢了、信用卡额度不够了。同时,旁边白板上的赌注越下越大。
11月11日,这个棍子最多的日子被网民自我调侃地变成了一个节日——“光棍
节”,而淘宝网又用疯狂的折扣促销给它赋予了另外一个意义——“购物狂欢
节”。2011年11月11日这一天,淘宝商城与淘宝网交易额之和突破52亿元人民币,这个数字是“购物天堂”香港一天零售总额8.5亿元的6倍。
网民感受到的是疯抢的喜悦,而网站的技术人员感受到的却是“压力山大”。
就如同你家办酒席,宴请左邻右舍,这个办起来容易,倘若宴请十里八乡所有的
人,吃饭的人固然开心,但却不是一般人家能够办得起来的。能办得起来如此盛宴
者,需要强大的财力和物力、组织能力、技术实力(例如做这么多菜,你的炒锅一
定要是“分布式的”、“可复制的”、“可扩展的”,洗菜和切菜要有“工作流引
擎”,跑堂的要计算一下最优路径,甚至连厨房的下水道都要重新设计)。
淘宝能够举办如此盛宴,网站的技术实力可见一斑。至2011年年底,淘宝网拥
有全国最大的Hadoop分布式计算集群之一(2000多个节点,CPU:24000core,Memory:48000GB,Disk:24000块),日新增数据50TB,有40PB海量数据存储,分布在全国各地80多个节点的CDN网络,支撑的流量超过800Gbps。淘宝的搜索引擎
能够对数十亿的商品数据进行实时搜索,另外,还拥有自主研发的文件存储系统和
缓存系统,以及Java中间件和消息中间件系统,这一切组成了一个庞大的电子商务
操作系统。从商业数据上看,Amazon的财报显示2011年完成了大约480亿美元的交
易额,eBay的2011年财报显示全年完成了大约600亿美元的交易额(不包括其独立
的汽车交易平台)。无论从交易额、商品数量还是从同比增速等指标上看,淘宝网
均远超于此,是目前全球最大的电子商务平台。(由于淘宝是非上市公司,未公布
2011年的业绩,以上内容来自淘宝网技术副总裁@_行癫的微博)。
以上这些技术数据可能已经让一些人产生了不适的感觉,为了让更多的人读懂
这本书,我们用下面这段文字描述一下小美访问淘宝网的时候,从技术的角度来
看,网站上发生了什么样的事情。
参考资料来自《你刚才在淘宝上买了一件东西》(来自阿里员工卡特)
你发现快要过年了,于是想给你的女朋友买一件毛衣,你打开了
www.taobao.com,这时你的浏览器首先查询DNS服务器,将www.taobao.com转换
成IP地址。不过你首先会发现,在不同的地区或者不同的网络(电信、联通、移
动)下,转换后的IP地址很可能是不一样的,这首先涉及到负载均衡的第一步,通
过DNS解析域名时,将你的访问分配到不同的入口,同时尽可能保证你所访问的入口
是所有入口中可能较快的一个(这和后文的CDN不一样)。
你通过这个入口成功地访问了www.taobao.com实际的入口IP地址,这时产生了
一个PV(PageView,页面访问量。每日每个网站的总PV量是形容一个网站规模的重
要指标。淘宝网全网在平日(非促销期间)的PV大概是16~25亿个之间)。同时作
为一个独立的用户,你这次访问淘宝网的所有页面均算作一个
UV(UniqueVisitor,用户访问)。最近臭名昭著的12306.cn的日PV量最高峰在10亿个左右,而UV量却远小于淘宝网十余倍,这其中的原因相信大家都知道。
因为同一时刻访问www.taobao.com的人数过于巨大,所以,即便是生成淘宝首
页页面的服务器,也不可能仅有一台,仅用于生成www.taobao.com首页的服务器就
可能有成百上千台,那么你的一次访问时生成页面给你看的任务便会被分配给其中
一台服务器完成。这个过程要保证公正、公平、平均(即这成百上千台服务器每台
负担的用户数要差不多),这一很复杂的过程由几个系统配合完成,其中最关键的
便是LVS(LinuxVirtualServer,世界上最流行的负载均衡系统之一,是由目前在
淘宝网供职的章文嵩博士开发的)。
经过一系列复杂的逻辑运算和数据处理,这次用于给你看的淘宝网首页的HTML
内容便成功生成了。对Web前端稍微有点常识的人都应该知道,浏览器下一步会加载
页面中用到的CSS、JS(JavaScript)、图片等样式、脚本和资源文件。但是可能
相对较少的人才会知道,你的浏览器在同一个域名下并发加载的资源数量是有限
的,例如IE6和IE7是两个,IE8是6个,chrome各版本不大一样,一般是4~6个。
我刚刚看了一下,我访问淘宝网首页需要加载126个资源,那么如此小的并发连接数
自然会加载很久。所以前端开发人员往往会将上述这些资源文件分布在多个域名
下,变相地绕过浏览器的这个限制,同时也为下文的CDN工作做准备。
据不可靠消息称,在2011年“双十一”当天高峰,淘宝的访问流量最巅峰达到
871GBs,这个数字意味着需要178万个4MBs的家庭宽带才能负担得起,也完全有
能力拖垮一个中小城市的全部互联网带宽。显然,这些访问流量不可能集中在一
起,并且大家都知道,不同地区、不同网络(电信、联通等)之间互访会非常缓
慢,但是你却很少发现淘宝网访问缓慢,这便是CDN(ContentDeliveryNetwork,即内容分发网络的作用)。淘宝在全国各地建立了数十个甚至上百个CDN节点,利用
一些手段保证你访问的(这里主要指JS、CSS、图片等)站点是离你最近的CDN节
点,这样便保证了大流量的分散已及在各地访问的加速。
这便出现了一个问题,那就是假若一个卖家发布了一个新的宝贝,上传了几张
新的宝贝图片,那么淘宝网如何保证全国各地的CDN节点中都会同步存在这几张图片
供用户使用呢?这就涉及大量的内容分发与同步的相关技术。另外,淘宝上拥有海
量的宝贝图片等静态文件,这些文件的总容量也达到了数
PB(1PB=1024TB=1048576GB),为了快速存取这些文件,淘宝开发了分布式文件
系统TFS(TaoBaoFileSystem)来处理这类问题。
好了,这时你终于加载完成淘宝首页,然后习惯性地在首页搜索框中输入“毛
衣”二字并按回车键,这时你又产生了一个PV,然后,淘宝网的主搜索系统便开始
为你服务,它首先对你输入的内容基于一个分词库进行分词操作。众所周知,英文
是以词为单位的,词和词之间靠空格隔开,而中文是以字为单位,句子中所有的字
连起来才能描述一个意思。例如,英文句子“Iamastudent”用中文表示,则
为“我是一个学生”。计算机可以很简单地通过空格知道student是一个单词,但
是不太容易明白“学”、“生”两个字合起来才表示一个词。把中文的汉字序列切
分成有意义的词,就是中文分词,有些人也称为切词。“我是一个学生”分词的结
果是“我 是 一个 学生”。
是进行分词操作之后,还需要根据你输入的搜索词进行购物意图分析。用户进
行搜索时常常有如下几类意图。
-浏览型:没有明确的购物对象和意图,边看边买,用户比较随意和感性。
Query注1例如:“2010年10大香水排行”、“2010年流行毛衣”、“zippo有多
少种类?”;
-查询型:有一定的购物意图,体现在对属性的要求上。Query例如:“适合老
人用的手机”、“500元手表”;
-对比型:已经缩小了购物意图,具体到某几个产品。Query例如:“诺基亚
E71E63”、“akgk450px200”;注1Query即查询。为了在数据库或搜索引擎中寻
找某一特定文件、网站、记录或一系列记录,由搜索引擎或数据库送出的信息。
——作者注89第一部分:淘宝技术发展
-确定型:已经做了基本决定,重点考察某个对象。Query例如:“诺基亚N97”、“IBMT60”。通过对你的购物意图的分析,主搜索会呈现出完全不同的结
果。
之后的数个步骤后,主搜索系统便根据上述以及更多复杂的条件列出了搜索结
果,这一切是由一千多台搜索服务器完成的。然后你开始逐一点击浏览搜索出的宝
贝,查看宝贝详情页面。经常网购的亲们会发现,当你买过一个宝贝之后,即便是
商家多次修改了宝贝详情页,你仍然能够通过“已买到的宝贝”查看当时的快照。
这是为了防止商家对在商品详情中承诺过的东西赖账不认。显然,对于每年数十亿
甚至上百亿笔交易的商品详情快照进行保存和快速调用不是一件简单的事情。这其
中又涉及数套系统的共同协作,其中较为重要的是Tair(淘宝自行研发的分布式KV
存储方案)。
接下来,无论你是否真的进行了交易,你的这些访问行为都会如实地被系统记
录下来,用于后续的业务逻辑和数据分析。这些记录中的访问日志记录便是最重要
的记录之一,但是从前面我们得知,这些访问是分布在各个地区多个不同的服务器
上的,并且由于用户众多,这些日志记录都非常庞大,达到TB级别也非常正常。那
么,为了快速、及时、同步地传输这些日志数据,淘宝研发了TimeTunnel,用于进
行实时的数据传输,然后交给后端系统进行计算报表等操作。
你的浏览数据、交易数据以及其他很多数据记录均会被保留下来,使得淘宝存
储的历史数据轻而易举地便达到了数十甚至更多个PB。如此巨大的数据量存储在阿
里巴巴集团的数据仓库中,并且其中有些数据使用了压缩比高达1:120的极限存储技
术。之后这些数据会通过一个叫做云梯的基于Hadoop的由3000多台服务器组成的超
大规模数据系统,以及一个基于阿里巴巴集团自主研发的ODPS系统的数据系统,不
断地进行分析和挖掘。
淘宝从这些数据中能够知道小到你是谁,你喜欢什么,你的孩子几岁了,你是
否在谈恋爱,喜欢玩魔兽世界的人喜欢什么样的饮料等,大到各行各业的零售情况、各类商品的兴衰消亡等海量的信息。
说了这么多,其实也只是叙述了淘宝上正在运行的成千上万个系统中的寥寥几
个。即便是你仅仅访问一次淘宝的首页,所涉及的技术和系统规模都是你完全无法
想象的,是淘宝2000多名顶级的工程师们的心血结晶,其中甚至包括长江学者、国
家科学技术最高奖得主等众多牛人。同样,百度、腾讯等的业务系统也绝不比淘宝
简单。你需要知道的是,你每天使用的互联网产品看似简单易用,背后却凝聚着难
以想象的智慧与劳动。
(本文所涉及的技术与数据均来源于互联网)
为了有一个更直观的对比,我们说一个同行,他在2011年光棍节之前做促销,数据流量达到了12Gbps(他们有这么大的流量,老板很高兴,在微博上公布了这个
数据),这时的流量达到了极限,网站几乎挂掉,用户无法下订单。而淘宝网光棍
节当天网络的流量最高达到800Gbps,带给各家银行和快递公司的流量也让他们如
临大敌(后来,他们以能够撑住淘宝带来的流量为荣而到处宣传)。另外,如果你
在网上购买过火车票,更能体会到网站能支持多大的流量有多重要。但这不是一朝
一夕就能做出来的,也不是有钱就能办到的。
以上对比的这些网站,也许读者很容易就能猜到是哪一家,这里绝对没有嘲笑
他们的意思,采用通常的网站技术方案能做到这种程度已经不错了。任何网站的发
展都不是一蹴而就的,通常是在什么阶段采用什么技术。在发展的过程中,网站会
遇到各种各样的问题,正是这些原因才推动着技术的进步和发展,而技术的发展反
过来又会促进业务的更大提升。二者互为因果,相互促进。如今淘宝网的流量已经
是全球排名第12、国内排名第3(至2011年年底,eBay全球排名第20,国内前两名
是百度和腾讯)。淘宝网的系统也从使用一台服务器,到采用万台以上的服务器。
本书就为大家描述淘宝网在整个发展过程中,所有主动和被动的技术变革的前因后
果,这由很多有趣的故事组成。
正如同很多人或组织成功了以后,就会为自己的出身编造一个美丽的传说。关
于淘宝网的出身,网上也有非常多的传说,下面我们就从它的出生开始讲起。
个人网站
LAMP
2003年4月7日,马云在杭州成立了一个神秘的组织。他叫来十位员工,要他们
签了一份协议,这份协议要求他们立刻离开阿里巴巴集团,去做一个神秘的项目。
这个项目要求绝对保密,老马戏称“连说梦话被老婆听到都不行,谁要是透漏出
去,我将追杀到天涯海角”。这份协议是英文版的,匆忙之间,大多数人根本来不
及看懂,但出于对老马的信任,都卷起铺盖离开了阿里巴巴。
他们去了一个神秘的据点——湖畔花园小区的一套未装修的房子里,房子的主
人是马云。这伙人刚进去的时候,马云给他们布置了一个任务,就是在最短的时间
内做出一个个人对个人(C2C)的商品交易的网站。这里出一个问题考考大家,看你
适不适合做淘宝的创业团队:亲,要是让你来做,你怎么做?
在说出这个答案之前,我们先介绍一下这个创业团队的成员:三个开发工程师
(虚竹、三丰、多隆)、一个UED工程师(二当家)、三个运营工程师(小宝、阿
珂、破天)、一个经理(财神),以及马云和他的秘书。当时对整个项目组来说,压力最大的就是时间,为什么时间这么重要呢?火云邪神先生说过“天下武功无坚
不破,唯快不破”,还有一个原因就是当时eBay和易趣在资本方面正打得不可开
交,我们是趁虚而入的,等他们反应过来就危险了。那怎么在最短的时间内把一个
网站从零开始建立起来呢?了解淘宝历史的人都知道淘宝是在2003年5月10日上线
的,2003年4月7日到5月10日,这之间只有一个月时间。要是你在这个团队里,你
怎么做?不是“抄一个来”,我们的答案是——“买一个来”。
买一个网站显然比做一个网站要省事,但是他们的梦想可不是做一个小网站而
已,要做大,就不是随便买一个就行的,要有比较低的维护成本,要能够方便地扩展和二次开发。那么接下来就是第二个问题:买一个什么样的网站?答案是:轻量
一点的,简单一点的。于是买了这样一个架构的网站:
LAMP(Linux+Apache+MySQL+PHP),这个直到现在还是一个很常用的网站架构模
型,其优点是:无须编译,发布快速,PHP语言功能强大,能做从页面渲染到数据访
问所有的事情,而且用到的技术都是开源、免费的。
当时我们是从一个美国人那里买来的一个网站系统,这个系统的名字叫做
PHPAuction(其官方网站http:www.phpauction.netAuction,即是拍卖的意
思,这个名字很直白,一眼就可看出这个系统是用什么语言做的、用途是什么),PHPAuction有好几个版本,我们买的是最高版的,功能比较多,而且最重要的是对
方提供了源代码。最高版比较贵,花了我们差不多2000美元(貌似现在降价了,只
要946美元,在他们的网站上有明码标价的信息)。买来之后不是直接就能用的,需
要很多本地化的修改,例如,修改一些数据类型,增加后台管理的功能,页面模板
改得漂亮一点,页眉和页脚加上自己的站点简介等。其中最有技术含量的是对数据
库进行了一个修改,原来是从一个数据库进行所有的读写操作,现在把它拆分成一
个主库、两个从库,并且读写分离。这么做的好处有几点:存储容量增加了,有了
备份,使得安全性增加了,读写分离使得读写效率得以提升(写要比读更加消耗资
源,分开后互不干扰)。这样整个系统的架构就如下图所示。
其中,pearDB是一个PHP模块,负责数据访问层。另外,他们也用开源的论坛
系统PHPBB(http:www.phpbbchina.com)搭建了一个小的论坛社区,在当时,论坛几乎是所有网站的标配。虚竹负责机器采购、配置、架设等,三丰和多隆负责
编码,他们把交易系统和论坛系统的用户信息打通,给运营人员开发出后台管理的
功能(Admin系统),把交易类型从只有拍卖这一种增加为拍卖、一口价、求购商
品、海报商品(意思是还没推出的商品,先挂个海报出来,这是快速增加商品数的
一个好方法)四种。(PHPAuction系统里只有拍卖的交易,Auction即拍卖的意
思。@_行癫在微博中提到:今天,eBay所有的交易中,拍卖交易仍然占40%,而在
中国,此种模式在淘宝几乎从一开始就未能占据优势,如今在主流的交易中几乎可
以忽略不计。背后的原因一直令人费解,我大致可以给出其中一种解释,eBay基本
上只在发达国家展开业务,制造业外包后,电子商务的基本群体大多只能表现为零
散的个体间交易。)
在开发过程中,这个项目的代号是BMW(没错!就是宝马的意思)。这个是二当
家提出的建议,二当家特别喜欢宝马,他希望我们的网站也如同宝马一样漂亮、快
速、安全,充满乐趣。二当家现在的座驾就是一辆宝马X5,算是得偿所愿了。在上
线的时候需要给这个网站取个名字,为了不引起eBay的注意,这个名字要撇开与阿
里巴巴的关系,所以“阿里爷爷”、“阿里舅舅”之类的域名是不能用的。这时
候,美女阿珂提供了一个很好听的名字“淘宝”。因为她家里有人热爱收藏古董,经常去市场上淘宝贝,而她本人也非常热爱逛街,享受“淘”的乐趣,她觉得“淘
宝”两个字特别符合网站的定位(阿珂说想到这个名字的时候,脑子里一道闪电劈
过,真的是“灵光一闪”。后来“支付宝”的名字也是阿珂取的)。于是这个大名
就定了下来,淘宝网横空出世了。
在接下来的大半年时间里,这个网站迅速显示出了它的生机。这里有必要提一
下当时的市场环境,非典(SARS)的肆虐使得大家都不敢出门,尤其是去类似商场
等人多的地方。另外,在神州大地上最早出现的C2C网站易趣也正忙得不亦乐乎,2002年3月,eBay以3000万美元收购了易趣公司33%的股份,2003年6月以1.5亿美元收购了易趣公司剩余67%的股份。当时,淘宝网允许买卖双方留下联系方式,允许
同城交易,整个操作过程简单轻松。而eBay是收费的,为了收取交易佣金,eBay禁
止买卖双方这么做,这必然增加了交易过程的难度。而且eBay为了全球统一,把易
趣原来的系统替换成了美国eBay的系统,用户体验一下全变了,操作起来非常麻
烦,很多易趣的卖家在那边都混不下去了,这等于是把积累的用户拱手送给了淘
宝。为了不引起eBay的注意,淘宝网在2003年里一直声称自己是一个“个人网
站”。由于这个创业团队强大的市场开拓和运营能力,淘宝网的发展非常迅猛,2003年年底就吸引了注册用户23万个,每日31万个PV,从2003年5月到同年年底成
交额达3371万元。这没有引起eBay的注意,却引起了阿里巴巴内部很多员工的注
意,他们觉得这个网站以后会成为阿里巴巴强劲的对手,甚至有人在内网发帖,忠
告管理层要警惕这个刚刚起步的网站,但管理层似乎无动于衷。(这个团队的保密
工作做得真好!)
在市场和运营的后方,淘宝网的技术团队也在快速地做着系统的改进和创新。
这里还有一个有趣的故事,eBay和易趣早期都有员工在论坛上响应用户的需求,eBay的论坛用粉红色背景来区分员工的发言,易趣的员工在论坛上的昵称都选各种
豆豆,例如“黄豆豆”、“蚕豆豆”、“黑眼豆豆”等。淘宝在讨论运营策略的时
候提到这个问题,老马也要求所有的员工都去论坛上回答用户的问题。最早回答问
题的任务落在小宝头上,我们用什么名字好呢?“淘淘”、“宝宝”、“淘宝
宝”、“宝宝淘”?小宝都不满意,认为太女性化了,辱没了他堂堂一个七尺汉
子。讨论了很久之后,小宝灵光乍现,干脆取个名字叫“小宝”吧,小宝带七个老
婆来开店,迎接各位客官,很有故事性和现场感。于是接下来很多武侠小说中的人
物开始在淘宝论坛中行侠仗义,这些昵称下面标志着“淘宝店小二”,他们回答着
各种各样的问题,快速响应着用户的各种需求。如果是技术上能解决的,几个人商
量一下,马上就开发、测试、发布上线。公司给这几个人租了房子,他们合住在湖
畔花园旁边的小区里(男女分开),每天睁开眼就去公司,半夜两三点收工睡觉,响应用户的需求非常快。反过来对比一下,易趣被eBay收购之后,系统更换成了全
球通用的版本,响应用户的一个需求需要层层审批,据说,买个办公桌都要走两个
月流程,反应速度自然慢了下来。
当时淘宝第一个版本的系统中已经包含了商品发布、管理、搜索、商品详情、出价购买、评价投诉、我的淘宝等功能(现在主流程中也是这些模块。在2003年10
月增加了一个功能节点:“安全交易”,这是支付宝的雏形)。随着用户需求和流
量的不断增长,系统做了很多日常改进,服务器由最初的一台变成了三台,一台负
责发送Email、一台负责运行数据库、一台负责运行WebApp。一段时间之后,商品
搜索的功能占用数据库资源太大了(用like搜索的,很慢),2003年7月,多隆又
把阿里巴巴中文站的搜索引擎iSearch搬了过来。
如此快节奏的工作,其实大家都累得不轻,有人就提议大家随时随地锻炼身
体,可是当时SARS横行,在一个一百多平方米的房子里,怎么锻炼呢?高挑美女阿
珂提议大家练习提臀操,这样有助于保持身材,这个建议遭到男士的一致反对,后
来虚竹就教大家练习倒立,这个大家都能接受。于是这个倒立的传统一直延续至
今,与花名文化、武侠文化一并传承了下来。
随着访问量和数据量的飞速上涨,问题很快就出来了,第一个问题出现在数据
库上。MySQL当时是第4版的,我们用的是默认的存储引擎MyISAM,这种存储引擎在
写数据的时候会把表锁住。当Master同步数据到Slave的时候,会引起Slave写,这
样在Slave的读操作都要等待。还有一点是会发生Slave上的主键冲突,经常会导致
同步停止,这样,你发布的一些东西明明已经成功了,但就是查询不到。另外,当
年的MySQL不比如今的MySQL,在数据的容量和安全性方面也有很多先天的不足(和
Oracle相比)。
Oracle支付宝旺旺
讲到这里,顺便先辟个谣,网上有很多这样骗转发的励志段子:“1998年,马
化腾等一伙人凑了50万元创办了腾讯,没买房;1998年,史玉柱借了50万元搞脑白
金,没买房;1999年,丁磊用50万元创办了163.com,没买房;1999年,陈天桥炒
股赚了50万元,创办盛大,没买房;1999年,马云等18人凑了50万元注册了阿里巴
巴,没买房。如果当年他们用这50万元买了房,现在估计还在还着银行的贷款
吧。”事实上,阿里巴巴和淘宝网都是在马云自己的房子里创办的,阿里巴巴是
1999年初发布上线的。所以,关于马云买房子的事情,真相是这样的。
淘宝网作为个人网站发展的时间其实并不长,由于它太引人注目了,马云在
2003年7月就宣布这个是阿里巴巴旗下的网站,随后在市场上展开了很成功的推广运
作。最著名的就是利用中小网站来做广告,突围eBay在门户网站上对淘宝的广告封
锁。这时候,eBay终于看到淘宝网这个后起之秀了,他对竞争者的态度就是“封杀
他”。eBay买断了新浪、搜狐、网易的电子商务类型的广告,签署了排他性协议,切断了淘宝在这上面做广告的路子。大路不通,我们就独辟蹊径,上网比较早的人
应该还记得那些在右下角的弹窗和网站腰封上一闪一闪的广告,“淘宝网”几个字
总是如影随形地出现在任何中小型网站上。市场部那位到处花钱买广告的家伙太能
花钱了,一出手就是几百万元,他被我们称为“大少爷”。
“大少爷”们做的广告,带来的就是迅速上涨的流量和交易量。在2003年年
底,MySQL已经撑不住了,技术的替代方案非常简单,就是换成Oracle。换为
Oracle的原因除了它容量大、稳定、安全、性能高之外,还有人才方面的原因。在
2003年的时候,阿里巴巴已经有一支很强大的DBA团队了,有鲁国良、冯春培、汪
海(七公)这样的人物,后来还有冯大辉(@fenng)、陈吉平(拖雷)。这样的人
物牛到什么程度呢?Oracle给全球的技术专家颁发一些头衔,其中最高级别的叫
ACE(就是扑克牌的“尖儿”,够大的吧),被授予这个头衔的人目前全球也只有
300多名(公布名单的网址为:http:apex.oracle.complsotnf?
p=19297:3),当年全球只有十几名,而阿里巴巴就有4名。有如此强大的技术后
盾,把MySQL换成Oracle是顺理成章的事情。
但更换数据库不是只换个库就可以的,其访问方式和SQL语法都要跟着变,最重
要的一点是,Oracle的性能和并发访问能力之所以如此强大,有一个关键性的设计
——连接池,连接池中放的是长连接,是进程级别的,在创建进程的时候,它就要
独占一部分内存空间。也就是说,这些连接数在固定内存的OracleServer上是有限
的,任何一个请求只需要从连接池中取得一个连接即可,用完后释放,这不需要频
繁地创建和断开连接,而连接的创建和断开的开销是非常大的。但对于PHP语言来
说,它对数据库的访问都是很直接的,每一个请求都要一个连接。如果是长连接,应用服务器增多时,连接数就多了,就会把数据库拖挂,如果是短连接,频繁地连接后再断开,性能会非常差(而Java语言有很多现成的连接池)。那如何是好呢?
我们打探到eBay用了一个连接池的工具,是BEA卖给他们的。我们知道,BEA的东西
都很贵,我们买不起,就放弃了找BEA的念头,于是多隆在网上寻寻觅觅,找到一个
开源的连接池代理服务SQLRelay(http:sqlrelay.sourceforge.net),这个
东西能够提供连接池的功能,多隆对它进行了一些功能改进之后,系统的架构就变
成了如下形式。
数据一开始是放在本地的,七公带领的DBA们对Oracle做调优的工作,也对SQL
进行调优。后来数据量变大后,本地存储无法满足了,买了
NAS(NetworkAttached储),Storage,网络附属存
NetApp(NetworkAppliance,美国网域存储技术有限公司)的NAS作为数据库的存
储设备,加上OracleRAC(RealApplicationClusters,实时应用集群)来实现负
载均衡。七公说这实际上是走了一段弯路,NAS的NFS(NetworkFileSystem)协议传输的延迟很严重,但那时侯不懂。后来采购了Dell和EMC合作的SAN低端存储,性
能一下提升了十几倍,这才比较稳定了。再后来,数据量更大了,存储的节点一拆
二、二拆四,RAC又出问题了,这才踏上了购买小型机的道路。在那段不稳定的时间
里,七公曾经在机房住了5天5夜,差点被辐射成蜘蛛侠。
替换完数据库后,时间到了2004年春天,俗话说“春宵一刻值千金”,但这些
人的春宵却不太好过,他们在把数据的连接放在SQLRelay之后就噩梦不断,这个代
理服务经常会死锁,如同之前的MySQL死锁一样。虽然多隆做了很多修改,但当时那
个版本内部处理的逻辑不对,问题很多,最快的解决办法就是“重启”它的服务。
这在白天还好,只要连接上机房的服务器,把进程杀掉,然后开启就可以了。但是
最痛苦的是它在晚上也要死掉,于是工程师们不得不24小时开着手机,一旦收
到“SQLRelay进程挂起”的短信,就从春梦中醒来,打开电脑,连上机房的网络,重启服务,后来干脆每天睡觉之前先重启一下。做这事最多的据说是三丰,他现在
是淘宝网的总裁。现在我们知道,任何牛B的人物,都有一段苦B的经历。
微博上有人说“好的架构是进化来的,不是设计来的”。的确如此,其实还可
以再加上一句“好的功能也是进化来的,不是设计来的”。在架构的进化过程中,业务的进化也非常迅猛。最早的时候,买家打钱给卖家都是通过银行转账汇款,有
些骗子收了钱却不发货,干脆逃之夭夭。这是一个很严重的问题,一个人这么干了
之后,很快就有更多的人学会了(这就是传说中的“病毒传播”)。然而魔高一
尺,道高一丈,淘宝网这伙人开始研究防骗子的解决方案,他们看了PayPal的支付
方式,发现不能解决问题。研究了类似QQ币的东西,想弄个“淘宝币”出来,发现
也不行。后来这几个聪明的脑袋把这些想法糅合起来,突然想到了“担保交易”这
种第三方托管资金的办法。于是在2003年10月,淘宝网上线了一个功能,叫做“安
全交易”,卖家如果选择支持这种功能,买家就会把钱交给淘宝网,等他收到货之
后,淘宝网再把钱给卖家,这就是现在的“支付宝”。这个功能最早是让卖家可选
的,因为这会延迟他收款的周期。但一旦卖家用了这个之后,就发现交易量猛增,一年之后,几乎所有的卖家都选择担保交易,到后来干脆所有的交易都必须走担保
交易。在2012年支付宝的年会上,支付宝公布2011年的交易笔数已经是PayPal的两
倍。这个划时代的创新,其实就是在不断思索过程中的一个灵光乍现。
当时开发“安全交易”功能的是茅十八和他的徒弟苗人凤(茅十八开发到一半
去上海读MBA了,苗人凤现在是支付宝的首席业务架构师),开发与银行网关对接功
能的是多隆。当时多数银行的网站已经支持在线支付了,但多隆告诉我,他们的网
关五花八门,用什么技术的都有,我们必须一家一家地去接。而且银行的网关不保
证用户付钱后就一定能扣款成功,不保证扣款成功后就一定通知淘宝,也不保证通
知淘宝后就一定能通知到,以及不保证通知到了就不重复通知。这害苦了苗人凤,他必须每天手工核对账单,少一分钱都睡不着觉,因为对不齐账就一定是有人的钱
找不到地方了,这可是天大的问题。另外,他为了测试这些功能,去杭州所有的银
行都办理了一张银行卡。一大堆银行卡摆在桌子上,不知道的人还以为他一定很有
钱(高富帅啊),其实里面都只是十元八元的。现在我们再一次知道,任何牛B的人
物,都必须有一段苦B的经历。
有人说淘宝打败易趣(eBay中国)是靠免费,其实这只是原因之一。如果说和
易趣过招的第一招是免费,这让用户无须成本就能进来,那么第二招就是“安全支
付”,这让用户放心付款,不必担心被骗。在武侠小说中,真正的高手飞花摘叶即
可伤人,他们不会局限于一两招,一旦出手,则连绵不绝。而淘宝的第三招就
是“旺旺”。其实淘宝旺旺也不是自己生出来的,是从阿里巴巴的“贸易通”复制
过来的。从2004年3月开始,“叮咚!叮咚!”这个经典的声音就回荡在所有淘宝买
家和卖家的耳边,“亲,包邮不?”“亲,便宜5毛行不?”这亲切的砍价声造就了
后来的“淘宝体”。有人说中国人就是爱砍价,虽然笔者体会不到砍价成功后有多
少成就感,但每次我去菜市场,看到大妈们砍价砍得天昏地暗,那满足的劲头堪比
捡到了钱,我就深刻地理解了淘宝旺旺在交易过程中的价值。我猜eBay也体会不到
砍价的乐趣,他们一直不允许买卖双方在线聊天,收购了Skype之后也没有用到电子
商务中去。
旺旺在推出没多久,就惹了一个法律方面的麻烦。有个做雪饼的厂家找上门
来,说我们侵权了,他们家的雪饼很好吃,牛奶也做得不错,我们都很喜欢。然后
我们就在旺旺的前面加了两个字,叫做“淘宝旺旺”。最早做旺旺开发的人只有一
个——无崖子,我们叫他“旺旺之父”,为了支持他的工作,我们工作用的IM工具仅限于旺旺,旺旺在线数上新高之后,他请我们吃鸭脖子。有时候为了吃到鸭脖
子,我们盯着在线数看,快到整数量的时候,自己赶紧去挂几个小号上去。还有一
个很卡哇伊的设计师MM——奇灵,开发出了一套旺旺表情,这套表情比所有的聊天
软件的表情都大,也更加生动,一直沿用到现在,我们叫奇灵为“旺旺之母”。
在那个野蛮生长的阶段,其实很多产品都是想到什么就做什么,例如,我们还
搭建过一个聊天室,但似乎淘宝网不是一个闲聊的地方,这个聊天室门可罗雀,一
段时间后就关闭掉了。
SQLRelay的问题搞得三丰等人很难睡个囫囵觉,那一年开半年会的时候,公司
特地给三丰颁了一个奖项,对他表示深切的安慰。但不能总这样通过不断地重启来
保证系统的稳定性。于是,2004年上半年开始,整个网站就开始了一个脱胎换骨的
手术。
第二部分淘宝技术发展2
所有的进步都是不稳定的,一个问题解决了,我们不得不面对又一个新问
题。”——马丁?路德?金Java时代
脱胎换骨
我的师父黄裳曾经说过“好的架构图充满美感”。一个架构好不好,从审美的
角度就能看出来。后来我看了很多系统的架构,发现这个言论基本成立。反观淘宝
以前两个版本的架构,如下图所示,你看哪个比较美?
显然,第一个比较好看,第二个显得头重脚轻,这也注定了它不是一个稳定的
版本,只存活了不到半年的时间。2004年初,SQLRelay的问题解决不了,数据库必
须要用Oracle,那么从哪里动刀呢?只有换开发语言了。换什么语言好?用Java。
Java是当时最成熟的网站开发语言,它有比较良好的企业开发框架,被世界上主流
的大规模网站普遍采用。另外,有Java开发经验的人才也比较多,后续维护成本会
比较低。
到2004年上半年,淘宝网已经运行了一年的时间,这一年积累了大量的用户,也快速开发了很多功能,当时这个网站已经很庞大了,而且新的需求还在源源不断
地增加。把一个庞大的网站的开发语言换掉,无异于脱胎换骨,在换的过程中还不
能拖慢业务的发展,这无异于边换边跑,对时间和技术能力的要求都非常高。做这
样的手术,需要请第一流的专家来主刀。现在再考一下大家:亲,如果你在这个创
业团队中,请什么样的人来做这
件事?我们的答案是请Sun公司的人。没错,就是创造Java语言的那家公司,世界上没有比他们更懂Java的了。除此之外,还有一个不为人知的原因,我刚才说
到Java被世界上主流的大规模网站普遍采用,其中有一个网站就是eBay,那时侯
eBay的系统刚刚从C++改到Java,而且就是请Sun的工程师给改造成Java架构的,这下你懂了吧?他们不仅更懂Java,而且更懂eBay。
Sun公司的这帮工程师的确很强大,在笔者2004年年底来淘宝的时候,他们还
在,我有幸与他们共事了几个月。现在摆在他们面前的问题是用什么办法把一个庞
大的网站从PHP语言迁移到Java?而且要求在迁移的过程中,不停止服务,原来系
统的bugfix和功能改进不受影响。亲,你要是架构师,你怎么做?有人的答案是写
一个翻译器,如同把中文翻译成英文一样,自动翻译。我只能说你这个想法太超前
了,“tooyoung,toosimple,sometimesnaive”。当时没有,现在也没有人能做到。他们的大致方案是给业务分模块,一个模块一个模块地渐进式替换。如用户模
块,老的member.taobao.com继续维护,不添加新功能,新功能在新的模块上开
发,跟老的模块共用一个数据库,开发完毕之后放到不同的应用集群上,另开一个
域名member1.taobao.com,同时再替换老的功能,替换一个,就把老的模块上的
功能关闭一个,逐渐把用户引导到member1.taobao.com,等所有的功能都替换完
之后,关闭member.taobao.com上。从设计上来看,这个member1的二级域名应该
是一个过渡状态,但我们把member域名的代码下线以后,发现很难把member1切换
回member,因为有些地方把链接写死了,于是后来很长时间里我们都是在用
member1.taobao.com这样奇怪的域名。一年后,有另外一家互联网公司开始做电
子商务了,我们发现他们的域名也叫member1.xx.com、auction1.xx.com,复制
得毫无保留,我们只能会心一笑。
说了开发模式,再说说用到的JavaMVC框架,当时的struts1.x是用得比较多的
框架,但是用过webwork和struts2的人可能知道,struts1.x在多人协作方面有很
多致命的弱点,由于没有一个轻量框架作为基础,因此,很难扩展,这样架构师对
于基础功能和全局功能的控制就很难做到。而阿里巴巴的18个创始人之中,有个架
构师周悦虹,他在JakartaTurbine的基础上做了很多扩展,打造了一个阿里巴巴自
己用的MVC框架
WebX(http:www.openwebx.orgdocsWebx3_Guide_Book.html),这个框架
易于扩展,方便组件化开发,它的页面模板支持JSP和Velocity等,持久层支持
ibatis和hibernate等,控制层可以用EJB和Spring(Spring是后来才有的)。项
目组选择了这个强大的框架。另外,当时Sun在全世界大力推广他们的EJB,虽然淘
宝的架构师认为这个东西用不到,但他们还是极力坚持。在经历了很多次的技术讨
论、争论甚至争吵之后,这个系统的架构就变成了下图的形式。
MVC框架是阿里的WebX,控制层用了EJB,持久层是ibatis。另外,为了缓解数
据库的压力,商品查询和店铺查询放在搜索引擎中。这个架构图是不是好看了一点
了?
Sun的这帮工程师开发完淘宝的网站之后,用同样的架构又做了一个很牛的网
站,叫“支付宝”。(上一篇说过支付宝最初是淘宝上的“安全交易”功能,这个
功能后来独立出来,成立了一个网站,也成立了一个公司,就是现在的支付宝。把
支付宝从淘宝分出去的人,就是Sun公司的这几个人。)下图是支付宝的第一次员工
大会。
上面的架构中,引入了搜索引擎iSearch(前文说过,iSearch其实是在LAMP
系统运行一段时间之后被多隆引进的,换为Oracle之后只是替换一下数据源)。其
实这个搜索引擎的原理很简单,就是把数据库里的数据dump(倾倒)成结构化的文
本文件后,放在硬盘上,提供Web应用以约定的参数和语法来查询这些数据。这看起
来不难,难的是数以亿计的信息,怎么做到快速更新呢?这好比你做了一个网站,在百度上很快就能搜到,你一定很满意了。但如果你发布一件商品,在淘宝上过1个
小时还搜不到,你肯定要郁闷了。另一个难点是如何保证非常高的容量和并发量?
再往后面就要考虑断句和语义分析的问题,以及推荐算法等更加智能的问题。这些
内容先不详细介绍,因为搜索引擎的技术已经足以写好几本书了。
其实在任何时候,开发语言本身都不是系统的瓶颈,业务带来的压力更多的存
在于数据和存储方面。前面也说到,MySQL撑不住之后换为Oracle,Oracle的存储
一开始在本机上,后来在NAS上,NAS撑不住了用EMC的SAN存储,再后来,Oracle
的RAC撑不住了,数据的存储方面就不得不考虑使用小型机。在2004年夏天,DBA七
公、测试工程师郭芙和架构师行癫,踏上了去北京测试小型机的道路。他们带着小型机回来的时候,我们像欢迎领袖一样欢迎他们,因为那是我们最值钱的设备,价
格表上的数字吓死人。小型机买回来之后,我们争相合影,然后Oracle就运行在了
小型机上,存储方面,从EMC低端CX存储到Sunoemhds高端存储,再到EMCdmx高端
存储,一级一级地往上跳。
到2004年底,淘宝网已经有4百多万种商品了,日均4千多万个PV,注册会员达
400万个,全网成交额达10亿元。
到现在为止,我们已经用上了IBM的小型机、Oracle的数据库、EMC的存储,这
些东西都是很贵的,那些年可以说是花钱如流水。有人说过“钱能解决的问题,就
不是问题”,但随着淘宝网的发展,在不久以后,钱已经解决不了我们的问题了。
花钱买豪华的配置,也许能支持1亿个PV的网站,但淘宝网的发展实在是太快了,到
了10亿个PV怎么办?到了百亿怎么办?在几年以后,我们不得不创造技术,解决这
些只有世界顶尖的网站才会遇到的问题。后来我们在开源软件的基础上进行自主研
发,一步一步地把IOE(IBM小型机、Oracle、EMC存储)这几个“神器”都去掉
了。这些神器就如同《西游记》中那些神仙的兵器,他们身边的妖怪们拿到这些兵
器能把猴子打得落荒而逃。但最牛的神仙是不依赖这些神器的,他们挥一挥衣袖、翻一下手掌就威力无比了。
坚若磐石
已经有读者在迫不及待地问怎么去掉了IOE?别急,在去掉IOE之前还有很长的
路要走(在后面讲到TDDL的时候,会提到去IOE的一些事情)。行癫等人买回小型机之后,我们用上了Oracle。然后七公带着一帮DBA做优化SQL和存储方面的工作,行癫带着几个架构师研究数据库的扩展性。Oracle本身是一个封闭的系统,用
Oracle怎么做扩展呢?用现在一个时髦的说法就是做“分库分表”。
我们知道,一台Oracle的处理能力是有上限的,它的连接池有数量限制,查询
速度与容量成反比。简单地说,在数据量上亿、查询量上亿的时候,就到它的极限
了。要突破这种极限,最简单的方式就是多用几个Oracle数据库。但一个封闭的系
统做扩展,不像分布式系统那样直接加机器就可以了。我们的做法是把用户的信息
按照ID来存放到两个数据库中(DB1和DB2),把商品的信息和卖家信息放在两个对
应的数据库中,把商品类目等通用信息放在第三个库中(DBcommon)。这么做的目
的是除了增加了数据库的容量之外,还有一个就是做容灾,即万一一个数据库挂
了,整个网站上还有一半的商品可以买。
数据库这么分后,应用程序就会出现麻烦,如果我是卖家,查看我的商品没有
问题,我们都在一个库里。但如果我是一个买家,买的商品有DB1的,也有DB2的,要查看“我已买到的宝贝”的时候,应用程序怎么办?必须到两个数据库中分别查
询对应的商品。要按时间排序怎么办?两个库中“我已买到的宝贝”全部查出来在
应用程序中做合并。另外,分页怎么处理?关键字查询怎么处理?专业点的说法就
是数据的Join没法做了。这些工作交给程序员来做也许会更麻烦,于是行癫出手
了,他写了一个数据库路由的框架DBRoute,统一处理了数据的合并、排序、分页
等操作,让程序员像使用一个数据库一样操作多个数据库里的数据,这个框架在淘
宝的Oracle时代一直在使用。但是后来随着业务的发展,这种分库的第二个目的
——“容灾”的效果没有达到。像评价、投诉、举报、收藏、我的淘宝等很多地
方,都必须同时连接DB1和DB2,哪个库挂了都会导致整个网站挂掉。
上一篇说过,采用EJB其实是和Sun的工程师妥协的结果,在他们离开之后,EJB也逐渐被冷落了下来。在2005年和2006年的时候,Spring大放异彩,于是在控
制层用Spring替换掉了EJB,给整个系统精简了很多代码。
上一篇还说过,为了减少数据库的压力,提高搜索的效率,我们引入了搜索引
擎。随着数据量的继续增长,到了2005年,商品数有1663万个,PV有8931万个,注
册会员有1390万个,这给数据存储带来的压力依然很大,数据量大,速度就慢。
亲,除了搜索引擎、分库分表,还有什么办法能提升系统的性能?一定还有招数可以用,这就是缓存和CDN(内容分发网络)。
你可以想象,9000万次的访问量,有多少是在商品详情页面?访问这个页面的
时候,数据全都是只读的(全部从数据库中读出来,不写入数据库),在那个时
候,我们的架构师多隆大神做了一个基于BerkeleyDB的缓存系统,把很多不太变动
的只读信息放了进去。其实最初这个缓存系统还比较弱,我们并不敢把所有能缓存
的信息都往里面放,一开始先把卖家的信息放里面,然后把商品属性放里面,再把
店铺信息放里面,但是像商品详情这类字段太大的放进去受不了。说到商品详情,这个字段比较恐怖,有人统计过,淘宝商品详情打印出来平均有5米长,在系统里其
实放在哪里都不招人待见。笔者清楚地记得,我来淘宝之后担任项目经理做的第一
个项目就是把商品详情从商品表中移出来。它最早与商品的价格、运费等信息放在
一个表中,拖慢了整张表的查询速度,而很多时候查询商品信息是不需要查看详情
的。于是在2005年的时候,我把商品详情放在数据库的另外一张表中,再往后,这
个大字段被从数据库中请了出来,先是放入了缓存系统,到现在是放进了文件系统
TFS中。
到现在为止,整个商品详情的页面都在缓存里面了,眼尖的读者可能会发现现
在的商品详情不全是“只读”的信息了,这个页面上有个信息叫“浏览量”(这个
信息是2006年加上去的),这个数字每刷新一次,页面就要“写入”存储一次,这
种高频度实时更新的数据能用缓存吗?通常来说,这种是必须放进数据库的,但是
悲剧的是,我们在2006年开发这个功能的时候,把浏览量写入数据库,发布上线1个
小时后,数据库就挂掉了,每天几亿次的写入,数据库承受不了。那怎么办?亲,……先不回答你,后面讲到缓存Tair的时候再说。(下图不是广告,请把注意力从
左边移到右边中间,看看浏览量这个数据在哪里。)
CDN这个工作相对比较独立,跟别的系统一样,一开始我们采用的也是商用系
统。后来随着流量的增加,商用的系统已经撑不住了,LVS的创始人章文嵩博士带人
搭建了淘宝自己的CDN网络。在本文的引言中,我说过淘宝的CDN系统支撑了
800Gbps以上的流量,作为对比,我们可以看一下国内专业做CDN的上市公司
ChinaCache的介绍——“ChinaCache是中国第一的专业CDN服务提供商,向客户提
供全方位网络内容快速分布解决方案。作为首家获信产部许可的CDN服务提供商,目
前ChinaCache在全国50多个大中城市拥有近300个节点,全网处理能力超过
500Gbps,其CDN网络覆盖中国电信、中国网通、中国移动、中国联通、中国铁通和
中国教育科研网等各大运营商。”——淘宝一家的流量比他们的加起来还要多,这
样你可以看出淘宝在CDN上的实力,这在全世界都是数一数二的(其实我们一开始用
的商用CDN就是ChinaCache,它们支撑了很长时间)。另外,因为CDN需要大量的服
务器,要消耗很多能源(消耗多少?在前两年我们算过一笔账,淘宝上产生一个交
易,消耗的电量足以煮熟4个鸡蛋)。这两年,章文嵩的团队又在研究低功耗的服务
器,在绿色计算领域也做了很多开创性的工作,我们定制的基于英特尔凌动处理器
的低功耗服务器已经部署到了CDN机房,降低了很大的能耗。这方面的内容可以看后
面笔者对章文嵩博士的专访。
回想起刚用缓存那段时间,笔者还是个菜鸟,有一个经典的错误常常犯,就是
更新数据库的内容时,忘记通知缓存系统,结果在测试的时候就发现我改过的数据
在页面上没有变化。后来做了一些页面上的代码,修改CSS和JS的时候,用户本地缓存的信息没有更新,页面上也会乱掉,在论坛上被人说的时候,我告诉他用
Ctrl+F5组合键(清除本地缓存刷新页面),然后赶紧修改脚本文件的名称,重新
发布页面。
我们对数据分库、放弃EJB、引入Spring、加入缓存、加入CDN等工作,看起来
没有章法可循,其实都是围绕着提高容量、提高性能、节约成本来做的,由于这些
是不算大的版本变迁,我们姑且叫它2.1版,这个版本从构图上看有三只脚,是不是
稳定了很多?
在这个稳定的版本下,淘宝网的业务有了突飞猛进的发展,2005年5月,微软的
MSN门户大张旗鼓地进入中国,淘宝网成为它的购物频道。2005年中,盛大进军机
顶盒业务,其电视购物的功能也是淘宝网开发的。虽然因为水土不服或者政策的原
因,这两个业务现在都看不到了,但他们曾经是中国互联网行业的大事件。那位和
微软谈合作的人是@胖胡斐,他花起钱来也是大手笔的,我们就管他叫“二少爷”,他现在是蘑菇街的COO。
另外,老马也从来都不缺少娱乐精神,他看到湖南卫视的超女如此成功,也想
借鉴一下这种模式。就在2005年底,淘宝网和湖南卫视合作推出了一档节目,叫
做“超级Buyer秀”。这是一个定位于“超级会网购的人”的一个选秀节目,以百万
年薪为诱饵,让大家分享自己的网购经历,网友投票选出最终胜者。这个从海选到
表演,历时一年多,广告做得铺天盖地。虽然节目最终没有超女那样火爆,这也
让“淘宝网就是网购”的形象通过湖南卫视更加深入人心。
到2006年,淘宝网已经有了1.5亿个的日均PV,商品数达5千多万个,注册用户
3千多万个,全网成交额达169亿元。
创造技术
TFS
回顾一下上面几个版本,1.0版的PHP系统运行了将近一年的时间(2003年5月
—2004年1月),服务器由一台发展到多台;后来数据库撑不住了,将MySQL换成了
Oracle,引入了搜索引擎(2004年1月—2004年5月,叫1.1版本);然后不到半年
的时间又把开发语言换成了Java(2004年2月—2005年3月,叫2.0版本),数据服
务逐步采用了IOE;随着数据量和访问量的增长,我们进行数据分库、加入缓存、使
用CDN(2004年10月—2007年1月,叫2.1版本)。这几个版本中间有些时间上的重
合,因为很多架构的演化并没有明显的时间点,它是逐步进化而来的。
在描述2.1版本的时候,我写的标题是《坚若磐石》,这个“坚若磐石”是因为
这个版本终于稳定下来了,在这个版本的系统上,淘宝网运行了两年多的时间。这
期间有很多优秀的人才加入,也开发了很多优秀的产品,例如,商品的类目属性、支付宝认证系统、招财进宝项目、淘宝旅行、淘宝彩票、淘宝论坛等,甚至在团购
网站风起云涌之前,淘宝网在2006年就推出了“团购”的功能。
在这些产品和功能的最底层,其实还是商品管理和交易管理这两大功能。这两
大功能在2.1版本中都有很大的变化。商品管理起初是要求卖家选择7天到期还是14
天到期,到期之后自动下架,必须重新发布才能上架,上架之后就变成了新的商品
信息(ID变过了)。另外,如果商品在这个期间成交了,之后再有新货,必须发布
一个新的商品信息。这么做有几个原因,一是参照拍卖商品的时间设置,要在某日
期前结束挂牌;二是搜索引擎不知道同样的商品哪个排在前面,那就把挂牌时间长
的排前面(这样就必须在某个时间把老的商品下架,否则它会一直排在前面);第
三是成交信息和商品ID关联,这个商品如果多次编辑还是同一个ID的话,成交记录
中的商品信息会不断改变;还有一个不为人知的原因是我们的存储有限,不能让所
有的商品老存放在主库中。这种处理方式简单粗暴,但还算是公平。不过这样会导
致很多需求都无法满足,例如,卖出一件商品之后就无法更改价格,否则前面已经
成交的那个价格都变了,而且同样的商品,上一次销售后的很多好评都无法在下一个商品上体现出来;再如,我买过的商品结束后只看到交易的信息,不知道卖家是
否还会卖。基于这些需求,我们在2006年下半年把商品和交易拆开,一个商家的一
种商品有一个唯一的ID,上下架都是同一个商品。那么如果卖家修改价格和库存等
信息,已成交的信息怎么处理?那就在买家每交易一次的时候,都记录下商品的快
照信息,有多少次交易就有多少个快照。这样买卖双方比较爽了,但这给系统带来
了什么?存储的成本大幅度上升了!
存储的成本高到什么程度呢?数据库方面用了IOE,一套下来就是千万级别的,那几套下来就是——好多钱啊。另外,淘宝网还有很多文件需要存储,最主要的就
是图片、商品描述、交易快照,一个商品要包含几张图片和一长串的描述信息,而
每一张图片都要生成几张规格不同的缩略图。在2010年,淘宝网的后端系统上保存
着286亿个图片文件。图片在交易系统中非常重要,大家常说“一张好图胜千
言”、“无图无真相”,淘宝网的商品照片,尤其是热门商品图片的访问流量是非
常大的。在淘宝网整体流量中,图片的访问流量要占到90%以上,而且这些图片平均
大小为17.45KB,小于8KB的图片占整体图片数量的61%,占整体系统容量的11%。这
么多的图片数据、这么大的访问流量,给淘宝网的系统带来了巨大的挑战。对于大
多数系统来说,最头疼的就是大规模的小文件存储与读取,因为磁头需要频繁寻道
和换道,因此,在读取上容易带来较长的延时。在大量高并发访问量的情况下,简
直就是系统的噩梦。我们该怎么办?
同样的套路,在某个规模以下采用现有的商业解决方案,达到某种规模之后,商业的解决方案无法满足,只有自己创造解决方案了。对于淘宝的图片存储来说,转折点在2007年。这之前,一直采用商用存储系统,应用NetApp公司的文件存储系
统。随着淘宝网的图片文件数量以每年3倍的速度增长,淘宝网后端NetApp公司的
存储系统也从低端到高端不断迁移,直至2006年,即使是NetApp公司最高端的产品
也不能满足淘宝网存储的要求。从2006年开始,我们决定自己开发一套针对海量小
文件存储的文件系统,用于解决自身图片存储的难题。这标志着淘宝网从使用技术
到了创造技术的阶段。
2007年之前的图片存储架构如下图所示。
在一次架构师大会上,章文嵩博士总结了几点商用存储系统的局限和不足。
第一,商用存储系统没有对小文件存储和读取的环境进行有针对性的优化;第
二,文件数量大,网络存储设备无法支撑;第三,整个系统所连接的服务器越来越
多,网络连接数已经达到网络存储设备的极限;第四,商用存储系统扩容成本高,10TB的存储容量需要几百万元,而且存在单点故障,容灾和安全性无法得到很好的
保证。
谈到在商用系统和自主研发之间的经济效益方面的对比,章文嵩博士列举了以
下几点经验。
第一,商用软件很难满足大规模系统的应用需求,无论是存储、CDN还是负载均
衡,在厂商实验室端,都很难实现如此大的数据规模测试。
第二,在研发过程中,将开源和自主开发相结合,会有更好的可控性,若系统
出了问题,完全可以从底层解决问题,系统扩展性也更高。
第三,在一定规模效应的基础上,研发的投入都是值得的。下图演示的是一个
自主研发和购买商用系统的投入产出比,实际上,图中交叉点的左边,购买商用系
统都是更加实际和经济性更好的选择,只有在规模超过交叉点的情况下,自主研发
才能收到较好的经济效果。实际上,规模化达到如此程度的公司并不多,不过淘宝
网已经远远超过了交叉点。
第四,自主研发的系统可在软件和硬件的多个层次之间不断优化。
历史总是惊人的巧合,在我们准备研发文件存储系统的时候,Google走在了前面,2007年,他们公布了GFS(GoogleFileSystem)的设计论文,这给我们带来了
很多借鉴的思路。随后我们开发出了适合淘宝使用的图片存储系统
(TaoBaoFileSystem,TFS)。3年之后,我们发现历史的巧合比我们想象的还要
神奇,几乎跟我们同时,中国的另外一家互联网公司也开发了他们的文件存储系
统,甚至取的名字都一样——TFS,太神奇了!(猜猜是哪家)
2007年6月,TFS正式上线运营。在生产环境中应用的集群规模达到了200台
PCServer(146GB×6SAS15KBRaid5),文件数量达到上亿级别;系统部署存储容
量为140TB;实际使用存储容量为50TB;单台支持随机IOPS200+,流量为3MBs。
说到TFS的系统架构,首先要描述清楚业务需求,淘宝对图片存储的需求大概可
以描述如下:
文件比较小;并发量高;读操作远大于写操作;访问随机;没有文件修改的操
作;要求存储成本低;能容灾,能备份。显然,应对这种需求时要用分布式存储系
统;由于文件大小比较统一,可以采用专有文件系统;由于并发量高,读写随机性
强,需要更少的IO操作;考虑到成本和备份,需要用廉价的存储设备;考虑到容
灾,需要能平滑扩容。
参照GFS并做了大量的优化之后,TFS1.0版的架构图如下。
从上面的架构图可看出:集群由Server和多台Data一对NameServer构成,NameServer的两台服务器互为双机,这就是集群文件系统中管理节点的概念。
在这个系统中:
-每个DataServer运行在一台普通的Linux主机上;
-以Block文件的形式存放数据文件(一个Block的大小一般为64MB);
-Block存储多份是为了保证数据安全;
-利用ext3文件系统存放数据文件;
-磁盘raid5做数据冗余;
-文件名内置元数据信息,用户自己保存TFS文件名与实际文件的对照关系,这
使得元数据量特别小。
淘宝TFS文件系统在核心设计上最大的取巧在于,传统的集群系统中元数据只有
1份,通常由管理节点来管理,因而很容易成为瓶颈。而对于淘宝网的用户来说,图
片文件究竟用什么名字来保存他们并不关心,因此,TFS在设计规划上考虑在图片的
保存文件名上暗藏了一些元数据信息,例如,图片的大小、时间、访问频次等信
息,包括所在的逻辑块号。而在实际的元数据上,保存的信息很少,因此,元数据
结构非常简单。仅仅只需要一个FileID就能够准确定位文件在什么地方。由于大量
的文件信息都隐藏在文件名中,整个系统完全抛弃了传统的目录树结构,因为目录
树开销最大。拿掉后,整个集群的高可扩展性可极大地提高。实际上,这一设计理
念和目前业界的“对象存储”较类似。
在TFS上线之前,淘宝网每个商品只允许上传一张图片,大小限定在120KB之
内,在商品详情中的图片必须使用外站的服务。那时侯发布一件商品确实非常麻
烦,笔者曾经想卖一台二手电脑,我先把照片上传到Google相册,在发布到淘宝网
之后发现Google相册被墙(即被屏撇,无法访问),我的图片别人看不到,当时很
郁闷。在TFS上线后,商品展示图片开放到5张,商品描述里面的图片也可以使用淘
宝的图片服务,到现在为止,淘宝网给每个用户提供了1GB的图片空间。技术和业务
就是这么互相借力推动着的,业务满足不了的时候,技术必须创新,技术创新之
后,业务有了更大的发展空间。
TFS发布之后,又经历了多个版本的修改,到1.3版的时候已经比较成熟了。
2009年6月,TFS1.3版本上线,集群规模大大扩展,部署到淘宝的图片生产系统
上,整个系统已经从原有200台PC服务器扩增至440台PC服务器
(300B×12SAS15KBRPM)+30台PC服务器(600B×12SAS15KBRPM)。支持文件数量
也扩容至百亿级别;系统部署存储容量为1800TB;当前实际存储容量为995TB;单
台DataServer支持随机IOPS900+,流量为15MB+;目前NameServer运行的物理内
存是217MB(服务器使用千兆网卡)。
TFS1.3版本逻辑结构图如下图所示。
在TFS1.3版本中,工程师们重点改善了心跳和同步的性能,最新版本的心跳和
同步在几秒钟之内就可完成切换,同时进行了一些新的优化,包括元数据存储在内
存中、清理磁盘空间等。
性能上也做了优化,包括如下内容。
-采用ext4文件系统,并且预分配文件,减少ext3等文件系统数据碎片带来的
性能损耗;
-单进程管理单块磁盘的方式,摒除RAID5机制;
-带有HA机制的中央控制节点,在安全稳定和性能复杂度之间取得平衡;
-缩减元数据大小,将更多的元数据加载入内存,提升访问速度;y跨机架和IDC的负载均衡及冗余安全策略;
-完全平滑扩容。
对于整个图片服务来说,仅有TFS还是不够的,整个图片服务机器的拓扑结构如
下图所示。
整个图片存储系统就像一个庞大的服务器,有处理单元、缓存单元和存储单
元。前面已经介绍过后台的TFS集群文件存储系统,在TFS前端,还部署着200多台
图片文件服务器,用Apache实现,用于生成缩略图的运算。
值得一提的是,根据淘宝网的缩略图生成规则,缩略图都是实时生成的。这样
做的好处有两点:一是为了避免后端图片服务器上存储的图片数量过多,大大节约
后台存储空间的需求,我们计算过,采用实时生成缩略图的模式比提前全部生成好缩略图的模式节约90%的存储空间。也就是说,存储空间只需要后一种模式的10%。
二是,缩略图可根据需要实时生成,这样更加灵活。
图片文件服务器的前端则是一级缓存和二级缓存,前面还有全局负载均衡的设
置,用于解决图片的访问热点问题。图片的访问热点一定存在,重要的是,让图片
尽量在缓存中命中。目前淘宝网在各个运营商的中心点设有二级缓存,整体系统中
心店设有一级缓存,加上全局负载均衡,传递到后端TFS的流量就已经非常均衡和分
散了,对前端的响应性能也大大提高。根据淘宝的缓存策略,大部分图片都尽量在
缓存中命中,如果缓存中无法命中,则会在本地服务器上查找是否存有原图,并根
据原图生成缩略图,如果都没有命中,则会考虑去后台TFS集群文件存储系统上调
取。因此,最终反馈到TFS集群文件存储系统上的流量已经被大大优化了。
淘宝网将图片处理与缓存编写成基于Nginx的模块,我们认为,Nginx是目前性
能最高的HTTP服务器(用户空间),代码清晰,模块化非常好。淘宝网使用
GraphicsMagick进行图片处理,采用了面向小对象的缓存文件系统,前端有
LVS+Haproxy将原图和其所有的缩略图请求都调度到同一台Image Server(图片服
务器)。
在文件定位上,内存用Hash算法做索引,最多一次读盘。另外会有很多相同的
图片重复上传上来,去除重复文件也是采用Hash算法来做的。写盘方式则采用
Append方式写,并采用了淘汰策略FIFO,主要考虑降低硬盘的写操作,没有必要进
一步提高Cache命中率,因为ImageServer和TFS位于同一个数据中心,读盘效率还
是非常高的。
目前淘宝网的TFS已经开源(见code.taobao.org),业界的同仁可以一起使
用和完善这个系统。
Tair
TFS的开发让淘宝的图片功能得到了充分的发挥。同TFS一样,很多技术都是在
产品的推动下得到发展的。在介绍下面的技术之前,有必要说说前些年我们做过的
几个产品。
先说一个比较悲剧的——“团购”,这个团购可不是现在满大街挂的那种
Groupon类型的模式,在Groupon产生之前,在2006年,淘宝的产品经理一灯就提
出了“团购”这种产品。一灯最初的设想是让买家在社区发起团购,“团长”找到
足够的人之后,去跟卖家砍价,这类似于现在蘑菇街的“自由团”。但由于种种原
因,在开发的时候,对产品的功能做了裁剪,与最初的设想比起来偏离了一点,变
成了让卖家设置团购价,在买家达到指定的数量之后,以团购价成交。这个功能看
起来是结合了淘宝“一口价”和“荷兰拍”的另一种交易模式,但最终没有支撑下
去,这种交易方式最大的弱点就是让买家看到了卖家的底牌,即便达不到团购的数
量,他们也往团购的价格上砍。当时为了提高流量,淘宝网开辟了团购专区,实诚
的卖家在达不到团购数量的时候,被砍价砍亏了,狡猾的卖家干脆提高原价,利用
这个专区做促销。在接下来的两年里,这个产品沦落成了促销工具(话说现在满大
街的团购,其实也就是促销)。这个产品让研发人员对“产品”这个概念有了深刻
的认识。
再说一个更加悲剧的——“我的淘宝”。“我的淘宝”是给会员管理自己的商
品、交易、收货地址、评价、投诉的地方,这个地方必须在登录之后才能看到,所
以风格与外观完全不一样,很长时间都没有优化过,样子丑,用户操作也不方便,如果一个人有很多商品,上下架需要一个一个地操作,非常麻烦(想想那些卖书
的)。这时候一个重要人物承志(现在的蘑菇街CEO)登场了,他给我们演示了最牛
的前端交互技术,就是Gmail上那种AJAX的交互方式,可以拖动,可以用鼠标右
键,也可以用组合键,操作完毕还不刷新页面,管理商品如有神助,帅呆了。我是
这个项目的项目经理,一灯是产品经理,我们再拉上万剑和一伙工程师就开始行动
了。我们热火朝天地干了三个月,快要完成的时候,老马突然出现在我身后,看我操作了一遍新版“我的淘宝”之后,问我这是不是客户端软件,我说是网页,他抓
狂了,说这跟客户端软件一样,链接下面的下画线都没有,上下架用文件夹表示,他都不知道怎么操作,卖家肯定也不会玩。
页面如下图所示:看看这神乎其技的翻页条、精致的文件夹结构、人性化的多
选框,还有一个类似Excel的冻结窗口的功能,这有多么性感啊!
老马果然是神一样的人物,他说的应验了,淘宝历史上第一个群体性事件爆发
了,试用完新版本的“我的淘宝”之后,很多卖家愤怒了,说不会玩儿。一灯就和
承志一起商量怎么把页面改得像网页一点,改了半个月,愤怒依然没有平息。我很
无奈地看着这两个人在那里坚持,然后跟老板们商量怎么办。后来我们到论坛上让
大家投票要不要使用新版“我的淘宝”,投票结果是一半以上的人反对。于是这十
来个人做了3个月的系统被杀掉了。这让我非常沮丧,但最痛苦的还不是这个,我们
下线之后,另外一拨卖家不满了,说这么好的功能怎么没有了?这个产品带给我们
的是新技术(AJAX、prototype框架)的尝试,以及新技术对用户操作习惯的改
变,一定要慎之又慎。另外,还有一点没有总结好的教训,就是应对群体事件的时
候,我们手足无措,在后来“招财进宝”和淘宝商城出现群体性事件的时候,我发
现悲剧在重演。
说到“招财进宝”,这个是最悲剧的产品。在2006年“五一”的时候,一个划
时代的项目启动了。财神说要用最好的项目阵容,我被选中了,这一下让我觉得我
能划分到最好的员工之类,在“我的淘宝”这个产品中严重受伤的心又痊愈了。这
是一个商品P4P的系统,就是按成交付费。我们认为已经有很多卖家有钱了,但淘宝
上这么多的商品,他们很难被找到,卖家愿意花钱让商品排在前面。我们允许卖家购买广告位,把他的商品按一定算法给出排名(类似于百度的竞价排名,但不仅仅
看他出了多少钱,还要看信用、成交量、被收藏数量等,这个算法弄得巨复杂)。
这是一个多么牛的盈利模式啊!
这个系统进行得很顺利,但发布的时候,更大的群体性事件出来了,买家们质
疑:你们不是承诺三年不收费吗?收广告费不是收费吗?后来我们的竞争对手又推
波助澜,公关公司和圈子里各路大侠上蹿下跳,甚至同行推出了“一键搬家”的功
能来收纳我们的会员。一时间,舆论哗然,各种矛头都指了过来。为了收场,我们
又一次在论坛中让用户投票决定产品是否下线,同“我的淘宝”一样,以悲剧收
场。也如同“我的淘宝”一样,下线后,一拨尝到甜头的卖家说,这么好的功能怎
么没有了?(直到Yahoo中国合并之后,开发了淘宝直通车,才以类似的产品形态满
足了这部分需求。)
虽然“招财进宝”失败了,但这个项目中对技术的探索更加深入,其中用到了
用户行为追踪、AJAX等,而且有一个技术的细节非常经典,淘宝商品详情页面每天
的流量有几个亿,里面的内容都是放在缓存里的,做“招财进宝”的时候,我们要
给卖家显示他的商品被浏览的次数(见下图),这个数字必须实时更新,而用缓存
一般都是异步更新的,所以,一开始根本没考虑把这个数据放入缓存里。我们的商
品表里增加了这样一个字段,每增加一个PV,该字段就要更新一次。发布一个小时
后,数据库就挂掉了。数据库撑不住怎么办?一般的缓存策略是不支持实时更新
的,这时候多隆大神想了个办法,在Pache上面写了一个模块,这个数字根本不经过
下层的WebApp容器(只经过Apache)就写入一个集中式的缓存区了,这个缓存区的
数据再异步更新到数据库。这就是我前面提到的,整个商品详情的页面都在缓存中
了,把缓存用到了极致。
接下来,我们就说说缓存的技术吧。
淘宝在很早就开始使用缓存技术了,在2004年的时候,我们使用一个叫做
ESI(EdgeSideIncludes)的缓存(Cache)。在决定采用ESI之前,多隆试用了
Java的很多Cache,但都比较重,后来用了OracleWebCache,也经常挂掉,OracleWebCache也支持ESI,多隆由此发现了ESI这个好东东。ESI是一种数据缓
冲缓存服务器,它提供将Web网页的部分(这里指页面的片段)进行缓冲缓存的技
术及服务。以往的数据缓冲服务器和信息传送服务以“页”为单位制作,复制到数
据缓冲服务器中,这用于处理静态页面很有效,但在面对动态内容的时候,就很难
得到高效率。在ESI中是部分的缓冲网页,使用基于XML的标记语言,指定想要缓冲
的页面部分。由此,页面内分为动态地变更部分和静态的不变更部分,只将静态的
部分有效地发送到服务器中。淘宝网的数据虽然大部分都是动态产生的,但页面中
的静态片段也有很多,例如,页面的头、尾,商品详情页面的卖家信息等(如下图
右侧),这些最早都是从ESI缓存中读取的。
ESI解决了页面端静态片段的缓存,聪明的读者可能马上就想到了,在后端的那
些数据能不能使用缓存?显然也是可以的,而且是必需的。例如,一个大卖家的商
品和店铺,一天的浏览量可能是几百万个,一个小卖家的可能只有几个,那么这个
大卖家的用户信息要是每次都从数据库中读取,显然不划算,要是把这个信息放在
内存中,每次都从内存里取,性能要好很多。这种应用场景就是memcached这种
Key-Value缓存的用武之地。只可惜,在淘宝急需要memcached的时候,它还没有
崭露头角(它于2003年6月出现,但近几年才火爆起来,当时没发现它)。我们的架
构师多隆大神再一次出手写了一个缓存系统,叫TBstore,这是一个分布式的基于
BerkeleyDB的缓存系统,推出之后,在阿里巴巴集团内部使用非常广泛,特别是对
于淘宝,TBstore上应用了ESI(就是上面说过的那个ESI)、Checkcode(验证
码)、Description(前文说过的商品详情)、Story(心情故事,商品信息里面的
一个大字段,长度仅次于商品详情)、用户信息等内容。
TBstore的分布式算法实现:根据保存的Key(关键字),对key进行Hash算
法,取得Hash值,再对Hash值与总Cache服务器数据取模。然后根据取模后的值,找到服务器列表中下标为此值的Cache服务器。由JavaClientAPI封装实现,应用
无须关心。
TBstore有一个优点,这也是它的弱点,它的存储是基于BerkeleyDB的,而
BerkeleyDB在数据量超过内存的时候,就要往磁盘上写数据了,所以,它是可以做
持久化存储的。但是一旦往磁盘写入数据,作为缓存的性能就大幅下降。
这时又有一个项目,推动了淘宝在缓存方面的技术提升。在2007年,我们把淘
宝的用户信息独立出来,形成一个中心系统UIC(UserInformationCenter),因
为淘宝所有的功能都要依赖于用户信息,所以这个模块必须单独拿出来,否则以后
的系统无法扩展。把UIC拿出来以后,应用系统访问UIC,UIC访问数据库取得用户
信息,粗算一下,每天要取几十亿条的用户信息,若直接查询数据库,数据库肯定
会崩溃,这里必须要用缓存。于是多隆专门为UIC写了一个缓存系统,取名叫做
TDBM。TDBM抛弃了BerkeleyDB的持久功能,数据全部存放在内存中。到2009年,多隆又参考了memcached的内存结构,改进了TDBM的集群分布方式,在内存利用率
和吞吐量方面又做了大幅提升,推出了TDBM2.0系统。
下图是一个关键应用的实时监控信息,第一行是UIC的缓存命中率,可以看到有
99.2%之高。换句话说,也就是给数据库减少了99.2%的压力。
由于TDBM、TBstore的数据接口和用途都很相似,开发团队把二者合并,推出
了淘宝自创的Key-Value缓存系统——Tair(TaoBaoPair的意思,Pair即Key-
Value数据对)。Tair包括缓存和持久化两种存储功能。Tair作为一个分布式系
统,由一个中心控制节点和一系列的服务节点组成,我们称中心控制节点为
ConfigServer,服务节点是DataServer。ConfigServer负责管理所有的
DataServer,维护DataServer的状态信息。DataServer对外提供各种数据服务,并以心跳的形式将自身的状况汇报给ConfigServer。ConfigServer是控制点,而
且是单点,目前采用一主一备的形式来保证其可靠性。所有的DataServer地位都是
等价的。Tair的架构图如下图所示。
系统部署结构如下图所示。
目前,Tair支撑了淘宝几乎所有系统的缓存信息。Tair已开源,地址为
code.taobao.org。
在创造了TFS和Tair之后,整个系统的架构如下图所示。
在这个时候,研发部对搜索引擎iSearch也进行了一次升级,之前的搜索引擎
是把数据分到多台机器上,但是每份数据只有一份,现在是每份数据变成多份,整
个系统从一个单行的部署变成了矩阵,能够支撑更大的访问量,并且做到很高的可
用性。
到2007年,淘宝网日均PV达到2.5亿个,商品数超过1亿个,注册会员数达5千
多万个,全网成交额达433亿元。 第三部分淘宝技术发展3
“所有的进步都是不稳定的,一个问题解决了,我们不得不面对又一个新问
题。”——马丁?路德?金
分布式时代
服务化
在系统发展的过程中,架构师的眼光至关重要,作为程序员,只要把功能实现
即可,但作为架构师,要考虑系统的扩展性、重用性,对于这种敏锐的感觉,有人
说是一种“代码洁癖”。淘宝早期有几个架构师具备了这种感觉,周悦虹开发的
Webx是一个扩展性很强的框架,行癫在这个框架上插入了数据分库路由的模块、Session框架等。在做淘宝后台系统的时候,同样需要这几个模块,行癫指导我把
这些模块单独打成JAR包。另外,在做淘宝机票、彩票系统的时候,页面端也有很多
东西需要复用,最直观的是页眉和页脚,一开始,我们的每个系统中都复制了一
份,但奇妙的是,那段时间页脚要经常修改,例如,把“雅虎中国”改成“中国雅
虎”,过一段时间又加了一个“口碑网”,再过一段时间变成了“雅虎口碑”,最
后又变成了“中国雅虎”。后来我就把这部分Velocity模板独立出来做成了公用的
模块。
上面说的都是比较小的复用模块,到2006年,我们做了一个商品类目属性的改
造,在类目中引入了属性的概念。项目的代号叫做“泰山”,如同它的名字一样,这是一个举足轻重的项目,这个改变是一个划时代的创新。在这之前的三年时间
内,商品的分类都是按照树状一级一级的节点来分的,随着商品数量的增长,类目
也变得越来越深,且越来越复杂,这样,买家如果要查找一件商品,就要逐级打开
类目,找商品之前要弄清商品的分类。而淘宝运营部门管理类目的小二也发现了一
个很严重的问题,例如,男装里有T恤、T恤下面有耐克、耐克有纯棉的,女装里也
有T恤、T恤下面还是有耐克、耐克下面依然有纯棉的,那是先分男女装,再分款式、品牌和材质呢,还是先分品牌,再分款式、材质和男女装呢?弄得很乱。这时
候,一位大侠出来了——一灯,他说品牌、款式、材质等都可以叫做“属性”,属
性是类似Tag(标签)的一个概念,与类目相比更加离散、灵活,这样也缩减了类目
的深度。这个思想的提出一举解决了分类的难题!从系统的角度来看,我们建立
了“属性”这样一个数据结构,由于除了类目的子节点有属性外,父节点也可能有
属性,于是类目属性合起来也是一个结构化的数据对象。这个做出来之后,我们把
它独立出来作为一个服务,叫做Catserver(CategoryServer)。跟类目属性密切
关联的商品搜索功能独立出来,叫做Hesper(金星)。Catserver和Hesper供淘宝
的前后台系统调用。
现在淘宝的商品类目属性已经是全球最大的,几乎没有什么类目的商品在淘宝
上找不到(除了违禁的),但最初的类目属性改造完之后,我们很缺乏属性数据,尤其是数码类。从哪里弄这些数据呢?我们跟“中关村在线”合作,拿到了很多数
据,那个时候,很多商品属性信息的后边标注着:“来自中关村在线”。有了类目
属性,给运营工作带来了很大的便利,我们知道淘宝的运营主要就是类目的运营,什么季节推什么商品,都要在类目属性上做调整,让买家更容易找到。例如,夏天
让用户在女装一级类目下标出材质是不是蕾丝的、是不是纯棉的,冬天却要把羽绒
衣调到女装一级类目下,什么流行,就要把什么商品往更高级的类目调整。这样类
目和属性要经常调整,随之而来的问题就出现了——调整到哪个类目,所属商品的
卖家就要编辑一次自己的商品,随着商品量的增长,卖家的工作量越来越大,他们
肯定受不了。到了2008年,我们研究了超市里前后台商品的分类,发现超市前台商
品可以随季节和关联来调整摆放场景(例如著名的啤酒和尿布的关联),后台仓库
里要按照自然类目来存储,二者密切关联,却又相互分开这样卖家发布商品选择的
是自然类目和属性,淘宝前台展示的是根据运营需要摆放商品的类目和属性。改造
后的类目属性服务取名为Forest(森林,与类目属性有点神似。Catserver还用于
提供卖家授权、品牌服务、关键词等相关的服务)。类目属性的服务化是淘宝在系
统服务化方面做的第一个探索。
虽然个别架构师具备了“代码洁癖”,但淘宝前台系统的业务量和代码量还是
呈爆炸式的增长。业务方总在后面催,开发人员不够就继续招人,招来的人根本看不懂原来的业务,只好摸索着在“合适的地方”加一些“合适的代码”,看看运行
起来像那么回事后,就发布上线。在这样的恶性循环中,系统越来越臃肿,业务的
耦合性越来越高,开发的效率越来越低。借用当时比较流行的一句话“你写一段代
码,编译一下能通过,半个小时就过去了;编译一下没通过,半天就过去了。”在
这种情况下,系统出错的概率也逐步增长,常常是你改了商品相关的某些代码,发
现交易出问题了,甚至你改了论坛上的某些代码,旺旺出问题了。这让开发人员苦
不堪言,而业务方还认为开发人员办事不力。
大概是在2007年年底的时候,研发部空降了一位从硅谷来的高管——空闻大
师。空闻是一位温厚的长者,他告诉我们一切要以稳定为中心,所有影响系统稳定
的因素都要解决掉。例如,每做一个日常修改,都必须对整个系统回归测试一遍;
多个日常修改如果放在一个版本中,要是一个功能没有测试通过,整个系统都不能
发布。我们把这个叫做“火车模型”,即任何一个乘客没有上车,都不许发车。这
样做最直接的后果就是火车一直晚点,新功能上线更慢了,我们能明显感觉到业务
方的不满,空闻的压力肯定非常大。
现在回过头来看看,其实我们并没有理解背后的思路。正是在这种要求下,我
们不得不开始改变一些东西,例如,把回归测试日常化,每天晚上都跑一遍整个系
统的回归。另外,在这种要求下,我们不得不对这个超级复杂的系统做肢解和重
构,其中复用性最高的一个模块——用户信息模块开始拆分出来,我们叫它
UIC(UserInformationCenter)。在UIC中,它只处理最基础的用户信息操作,例如,getUserById、getUserByName等。
在另一方面,还有两个新兴的业务对系统基础功能的拆分也提出了要求。在那
个时候,我们做了淘宝旅行(trip.taobao.com)和淘宝彩票
(caipiao.taobao.com)两个新业务,这两个新业务在商品的展示和交易的流程
上都跟主站的业务不一样,机票是按照航班的信息展示的,彩票是按照双色球、数
字和足球的赛程来展示的。但用到的会员功能和交易功能是与主站差不多的,当时
做起来就很纠结,因为如果在主站中做,会有一大半跟主站无关的东西,如果重新做一个,会有很多重复建设。最终我们决定不再给主站添乱了,就另起炉灶做了两
个新的业务系统,从查询商品、购买商品、评价反馈、查看订单这一整个流程都重
新写了一套。现在在“我的淘宝”中查看交易记录的时候,还能发现“已买到的宝
贝”中把机票和彩票另外列出来了,他们没有加入到普通的订单中。在当时,如果
已经把会员、交易、商品、评价这些模块拆分出来,就不用什么都重做一遍了。
到2008年初,整个主站系统(有了机票、彩票系统之后,把原来的系统叫做主
站)的容量已经到了瓶颈,商品数在1亿个以上,PV在2.5亿个以上,会员数超过了
5000万个。这时Oracle的连接池数量都不够用了,数据库的容量到了极限,即使上
层系统加机器也无法继续扩容,我们只有把底层的基础服务继续拆分,从底层开始
扩容,上层才能扩展,这才能容纳以后三五年的增长。
于是我们专门启动了一个更大的项目,即把交易这个核心业务模块拆分出来。
原来的淘宝交易除了跟商品管理耦合在一起,还在支付宝和淘宝之间转换,跟支付
宝耦合在一起,这会导致系统很复杂,用户体验也很不好。我们把交易的底层业务拆分出来,叫交易中心(TradeCenter,TC),所谓底层业务,就如创建订单、减
库存、修改订单状态等原子型的操作;交易的上层业务叫交易管理
(TradeManager,TM),例如,拍下一件普通商品要对订单、库存、物流进行操
作,拍下虚拟商品不需要对物流进行操作,这些在TM中完成。这个项目取了一个很
没有创意的名字——“千岛湖”,开发人员取这个名字的目的是想在开发完毕之
后,去千岛湖玩一圈,后来他们如愿以偿了。这个时候还有一个淘宝商城的项目在
做,之前拆分出来的那些基础服务给商城的快速构建提供了良好的基础。
类目属性、用户中心、交易中心,随着这些模块的逐步拆分和服务化改造,我
们在系统架构方面也积累了不少经验。到2008年年底就做了一个更大的项目,把淘
宝所有的业务都模块化,这是继2004年从LAMP架构到Java架构之后的第二次脱胎换
骨。我们对这个项目取了一个很霸气的名字——“五彩石”(女娲炼石补天用的石
头)。这个系统重构的工作非常惊险,有人称为“给一架高速飞行的飞机换发动
机”。“五彩石”项目发布之后,相关工程师去海南三亚玩了几天。
他们把淘宝的系统拆分成了如下架构。
其中,UIC和Forest在上文已说过,TC、IC、SC分别是交易中心
(TradeCenter)、商品中心(ItemCenter)、店铺中心(ShopCenter),这些
中心级别的服务只提供原子级的业务逻辑,如根据ID查找商品、创建交易、减少库
存等操作。再往上一层是业务系统TM(TradeManager,交易业务)、IM(ItemManager,商品业务)、SM(ShopManager,后来改名叫SS,即
ShopSystem,店铺业务)、Detail(商品详情)。
拆分之后,系统之间的交互关系变得非常复杂,示意图如下所示。
系统这么拆分的好处显而易见,拆分之后的每个系统可以单独部署,业务简
单,方便扩容;有大量可重用的模块便于开发新的业务;能够做到专人专事,让技
术人员更加专注于某一个领域。这样要解决的问题也很明显,分拆之后,系统之间
还是必须要打交道的,越往底层的系统,调用它的客户越多,这就要求底层的系统
必须具有超大规模的容量和非常高的可用性。另外,拆分之后的系统如何通信?这里需要两种中间件系统,一种是实时调用的中间件(淘宝的HSF,高性能服务框
架),一种是异步消息通知的中间件(淘宝的Notify)。另外,一个需要解决的问
题是用户在A系统登录后,到B系统的时候,用户的登录信息怎么保存?这又涉及一
个Session框架。再者,还有一个软件工程方面的问题,这么多层的一套系统,怎
么去测试它?
中间件
HSF
互联网系统的发展看似非常专业,其实在生活中也存在类似的“系统”,正如
一位哲学家说“太阳底下无新事”。我们可以从生活中的一个小例子来看网站系统
的发展,这个例子是HSF的作者毕玄写的。
一家小超市,一个收银员,同时还兼着干点其他的事情,例如,打扫卫生、摆
货。
来买东西的人多起来了,排队很长,顾客受不了,于是增加了一个收银台,雇
了一个收银员。
忙的时候收银员根本没时间去打扫卫生,超市内有点脏,于是雇了一个专门打
扫卫生的。
随着顾客不断增加,超市也经过好几次装修,由以前的一层变成了两层,这个
时候所做的事情就是不断增加收银台、收银员和打扫卫生的人。
在超市运转的过程中,老板发现一个现象,有些收银台排很长的队,有些收银
台排的人不多,了解后知道是因为收银台太多了,顾客根本看不到现在各个收银台
的状况。对于这个现象,一种简单的方法就是继续加收银台。但一方面,超市没地
方可加收银台了,另一方面,作为老板,当然不需要雇太多的人,于是开始研究怎样让顾客了解到收银台的状况,简单地加了一个摄像头和一个大屏幕,在大屏幕上
显示目前收银台的状况,这样基本解决了这个问题。
排队长度差不多后,又出现了一个现象,就是有些收银台速度明显比其他的
慢,原因是排在这些收银台的顾客买的东西特别多,于是又想了一招,就是设立专
门的10件以下的通道,这样买东西比较少的顾客就不用排太长的队了,这一招施展
后,顾客的满意度明显提升,销售额也好了不少,后来就继续用这招应对团购状
况、VIP状况。
在解决了上面的一些烦心事后,老板关注到了一个存在已久的现象,就是白天
收银台很闲,晚上则很忙,于是从节省成本上考虑,决定实行部分员工只在晚上上
班的机制,白天则关闭一些收银台,顾客仍然可以通过大屏幕看到哪些收银台是关
闭的,避免走到没人的收银台去,实行这招后,成本大大降低了。
这个生活中的例子及其解决的方法,其实和互联网网站发展过程中的一些技术
是非常类似的,只是在技术层面用其他名词来表达了而已,例如,有集群、分工、负载均衡、根据QoS分配资源等。
-集群:所有的收银员提供的都是收银功能,无论顾客到哪一个收银员面前,都
可完成付款,可以认为所有的收银员就构成了一个集群,都希望能做到顾客增加的
时候只需增加收银员就行。在现实生活中有场地的限制,而在互联网应用中,能否
集群化还受限于应用在水平伸缩上的支撑程度,而集群的规模通常会受限于调度、数据库、机房等。
-分工:收银员和打扫卫生的人分开,这种分工容易解决,而这种分工在互联网
中是一项重要而复杂的技术,没有现实生活中这么简单,涉及的主要有按功能和数
据库的不同拆分系统等,如何拆分以及拆分后如何交互是需要面临的两个挑战。因此,会有高性能通信框架、SOA平台、消息中间件、分布式数据层等基础产品的诞
生。
-负载均衡:让每个收银台排队差不多长,设立小件通道、团购通道、VIP通道
等,这些可以认为都是集群带来的负载均衡的问题,从技术层面上说,实现起来自
然比生活中复杂很多。
-根据QoS分配资源:部分员工仅在晚上上班的机制要在现实生活中做到不难,而对互联网应用而言,就是一件复杂而且极具挑战的事。
参照生活中的例子来说,在面对用户增长的情况下,想出这些招应该不难,不
过要掌握以上四点涉及的技术就相当复杂了,而且互联网中涉及的其他很多技术还
没在这个例子中展现出来,例如缓存、CDN等优化手段;运转状况监测、功能降级、资源劣化、流控等可用性手段,自建机房、硬件组装等成本控制手段。因此,构建
一个互联网网站确实是不容易的,技术含量十足,当然,经营一家超市也不简单。
从超市的运维可以抽象出系统设计的一些思路,服务拆分之后,如何取得我需
要的服务?在“电视机”上,把每个集群能提供的服务显示出来。你不需要关心哪
个人为你服务,当你有需要的时候,请先看头顶的电视机,它告诉你哪个服务在哪
个区域。当你直接去这个区域的时候,系统会给你找到一个最快速的服务通道。
这就是HSF的设计思想,服务的提供者启动时通过HSF框架向
ConfigServer(类似超市的电视机)注册服务信息(接口、版本、超时时间、序列
化方式等),这样ConfigServer上面就定义了所有可供调用的服务(同一个服务也
可能有不同的版本);服务调用者启动的时候向ConfigServer注册对哪些服务感兴
趣(接口、版本),当服务提供者的信息变化时,ConfigServer向相应的感兴趣的
服务调用者推送新的服务信息列表;调用者在调用时则根据服务信息的列表直接访
问相应的服务提供者,而无须经过ConfigServer。我们注意到ConfigServer并不
会把服务提供者的IP地址推送给服务的调用者,HSF框架会根据负载状况来选择具体
的服务器,返回结果给调用者,这不仅统一了服务调用的方式,也实现了“软负载
均衡”。平时ConfigServer通过和服务提供者的心跳来感应服务提供者的存活状
态。
在HSF的支持下,服务集群对调用者来说是“统一”的,服务之间是“隔
离”的,这保证了服务的扩展性和应用的统一性。再加上HSF本身能提供的“软负载
均衡”,服务层对应用层来说就是一片“私有云”了。
HSF框架以SAR包的方式部署到Jboss、Jetty或Tomcat下,在应用启动的时
候,HSF(High-SpeedServiceFramework,在开发团队内部有一些人称HSF为“好
舒服”)服务随之启动。HSF旨在为淘宝的应用提供一个分布式的服务框架,HSF从
分布式应用层面以及统一的发布调用方式层面为大家提供支持,从而可以很容易地
开发分布式的应用以及提供或使用公用功能模块,而不用考虑分布式领域中的各种
细节技术,例如,远程通讯、性能损耗、调用的透明化、同步异步调用方式的实现
等问题。
从上图HSF的标志来看,它的速度是很快的。HSF是一个分布式的标准Service
方式的RPC(RemoteProcedureCallProtocol,远程过程调用协议)框架,Service的定义基于OSGI的方式,通讯层采用TCPIP协议。关于分布式的服务框架
的理论基础,HSF的作者毕玄写了一篇博文
(http:www.blogjava.netBlueDavarchive20080124177533.html),有关基于OSGI的分布式服务框架,也有一系列的博文
(http:www.blogjava.netBlueDavarchive20080114175054.html)。
从下面这个HSF监控系统的截图中可以更直观地看到一些信息,在两个集群中有
两个服务器(其实有更多的,没有全部截图下来)都提供
com.taobao.item.service.SpuGroupS这一服务,版本号都是1.0.0,这个服务
在ConfigServer上的注册信息中包含超时时间、序列化方式。在后面那条信息中可
看到,在展开的这个集群中服务有835台机器已订阅,这些订阅者有淘宝的服务器
(cart是购物车功能的服务器),也有hitao(淘花网)的服务器。
HSF系统目前每天承担了300亿次以上的服务调用。
一些读者可能会有一个疑问:既然淘宝的服务化是渐进式的,那么在HSF出现之
前,系统之间的调用采用什么方式呢?
这个有点“五花八门”,例如,对于类目的调用方式是:Forest打包成一个
JAR包,在应用启动的时候装载到内存中,仅这一个JAR包所占用的内存就有800MB
之多(因为淘宝的类目数据太庞大了),对于当时一般只有2GB内存的开发机来说,加载完类目信息后,机器运行速度就非常慢。对于用户信息(UIC)来说,一开始的
调用方式是用Hessian接口。还有一些系统是通过WebService、Socket甚至是
HTTP请求来相互调用的。每种调用方式都涉及各种超时、信息的加解密、参数的定
义等问题,由此可见,在没有HSF之前,系统之间的调用是错综复杂的。而随着系统
拆分得越来越多,必须由一个统一的中间层来处理这种问题,HSF正是在这种背景下
诞生的。
NotifyHSF
解决了服务调用的问题,我们再提出一个很早就说过的问题:用户在银行的网关付钱后,银行需要通知到支付宝,但银行的系统不一定能发出通知;如果通知发
出了,不一定能通知到;如果通知到了,不一定不重复通知一遍。这个状况在支付
宝持续了很长时间,非常痛苦。支付宝从淘宝剥离出来的时候,淘宝和支付宝之间
的通信也面临同样的问题,那是2005年的事情,支付宝的架构师鲁肃提出用
MQ(MessageQueue)的方式来解决这个问题,我负责淘宝这边读取消息的模块。但
我们发现消息数量上来之后,常常造成拥堵,消息的顺序也会出错,在系统挂掉的
时候,消息也会丢掉,这样非常不保险。然后鲁肃提出做一个系统框架上的解决方
案,把要发出的通知存放到数据库中,如果实时发送失败,再用一个时间程序来周
期性地发送这些通知,系统记录下消息的中间状态和时间戳,这样保证消息一定能
发出,也一定能通知到,且通知带有时间顺序,这些通知甚至可以实现事务性的操
作。
在“千岛湖”项目和“五彩石”项目之后,淘宝自家的系统也拆成了很多个,他们之间也需要类似的通知。例如,拍下一件商品,在交易管理系统中完成时,它
需要通知商品管理系统减少库存,通知旺旺服务系统发送旺旺提醒,通知物流系统
上门取货,通知SNS系统分享订单,通知公安局的系统这是骗子……用户的一次请
求,在底层系统可能产生10次的消息通知。这一大堆的通知信息是异步调用的(如
果同步,系统耦合在一起就达不到拆分的目的),这些消息通知需要一个强大的系
统提供支持,从消息的数量级上看,比支付宝和淘宝之间的消息量又上了一个层
次,于是按照类似的思路,一个更加强大的消息中间件系统就诞生了,它的名字叫
做Notify。Notify是一个分布式的消息中间件系统,支持消息的订阅、发送和消
费,其架构图如下所示。
NotifyServer在ConfigServer上面注册消息服务,消息的客户端通过
ConfigServer订阅消息服务。某个客户端调用NotifyServer发送一条消息,NotifyServer负责把消息发送到所有订阅这个消息的客户端(这个过程参照HSF一
节,原理是一样的)。为了保证消息一定能发出,且对方也一定能收到,消息数据
本身就需要记录下来,这些信息存放在数据库中(可以是各种数据库)。由于消息
具有中间状态(已发送、未发送等),应用系统通过Notify可以实现分布式事物
——BASE(基本可用(BasicallyAvailable)、软状态(SoftState)、最终一
致(EventuallyConsistent))。NotifyServer可以水平扩展,NotifyClient
也可以水平扩展,数据库也可以水平扩展,从理论上讲,这个消息系统的吞吐量是
没有上限的,现在Notify系统每天承载了淘宝10亿次以上的消息通知。
下图展示了创建一笔交易之后,TC(交易中心)向Notify发送一条消息,后续
Notify所完成的一系列消息通知。
TDDL
有了HSF和Notify的支持,在应用级别中,整个淘宝网的系统可以拆分了,还
有一个制约系统规模的更重要的因素,就是数据库,也必须拆分。
在第二部分中讲过,淘宝很早就对数据进行过分库的处理,上层系统连接多个
数据库,中间有一个叫做DBRoute的路由来对数据进行统一访问。DBRoute对数据进
行多库的操作、数据的整合,让上层系统像操作一个数据库一样操作多个库。但是
随着数据量的增长,对于库表的分法有了更高的要求,例如,你的商品数据到了百
亿级别的时候,任何一个库都无法存放了,于是分成2个、4个、8个、16个、32
个……直到1024个、2048个。好,分成这么多,数据能够存放了,那怎么查询它?这时候,数据查询的中间件就要能够承担这个重任了,它对上层来说,必须像查询
一个数据库一样来查询数据,还要像查询一个数据库一样快(每条查询在几毫秒内
完成),TDDL就承担了这样一个工作。
另外,加上数据的备份、复制、主备切换等功能,这一套系统都在TDDL中完
成。在外面有些系统也用DAL(数据访问层)这个概念来命名这个中间件。
TDDL实现了下面三个主要的特性:
-数据访问路由——将针对数据的读写请求发送到最合适的地方;
-数据的多向非对称复制——一次写入,多点读取;
-数据存储的自由扩展——不再受限于单台机器的容量瓶颈与速度瓶颈,平滑迁
移。
下图展示了TDDL所处的位置。
下图展示了一个简单的分库分表数据查询策略。
下面是TDDL的主要开发者之一沈询讲述的“TDDL的前世今生”——数据层的发
展历程。
CommonDAO的时代
数据切分并不算是一个很新的概念,当商品库切分为两个时,就已经出现了名
字叫做xingdian(笑,那时候行癫已经不写代码了,但从代码的版本信息可以看到
作者)的人写的CommonDAO。
CommonDAO的思路非常简单实用,因为淘宝主要在使用ibatis作为访问数据库
的DAO层,所以,CommonDAO的作用就是对ibatis层做了一个很浅的封装,允许你
通过商品字串ID的第一个字符来访问两台数据库中的一台。
比如,如果字符串ID的第一个字符是0~7,那么走到数据库1去,如果是8~f,则走到数据库2去。同时,也允许用户直接给定数据库的名字来访问数据库。
这应该是最早的数据层原型。
TDDL1.0时代
后来,大家逐渐发现,如果按照业务的发展规模和速度,那么使用高端存储和小型机的Oracle存储的成本将难以控制,于是降低成本就成了必然。
如何能够在不影响业务正常发展的前提下,从一定程度上解决成本的问题呢?
“对一部分数据库使用MySQL”,DBA们的决策是这样,于是,分布式数据层的
重担就落到了华黎的头上。
别看现在数据水平切分似乎已经成了基础知识。在2007年、2008年,如何设计
它还真是让我们伤透了脑筋。
当时的我们,只知道eBay有一个数据层,却不知道如何设计和实现?
于是邀请了当时所有的业务负责人来畅想数据层的样子……
得到了以下需求:
-对外统一一切数据访问;y支持缓存、文件存储系统;
-能够在Oracle和MySQL之间自由切换;
-支持搜索引擎。
然后,我们自己的问题与现在大家所问的问题也是完全一样的。
如何实现分布式Join(连接)?——在跨节点以后,简单的Join会变成M×N台
机器的合并,这个代价比原来的基于数据库的单机Join大太多了。
如何实现高速多维度查询?——就像SNS中的消息系统,A发给B一个消息,那
么A要看到的是我发给所有人的消息,而B要看到的是所有人发给我的消息。这种多
维度查询,如何能够做到高效快捷呢?
如何实现分布式事务?——原始单机数据库中存在着大量的事务操作,在分布
式以后,分布式事务的代价远远大于单机事务,那么这个矛盾也变得非常明显。
华黎带着我和念冰,坐在那里讨论了一个半月,还是没想出来……于是决定先动
起手来。名字是我起的——TaobaoDistributedDatalayer(TDDL,后来有人对它
取了个外号:“头都大了”⊙﹏⊙b)
学习开源的AmoebaProxy。
找到的目标应用是“收藏夹”,首先要做的两个关键的特性是:分库分表和异
构数据库的数据复制。
开始本来希望和B2B的团队合作,因为我们觉得独立的Proxy没有太大必要。而
SQL解析器因为有淘宝特殊的需求,所以也需要重写。
可惜,最后因为B2B的人搬到滨江去了,交流十分不畅,所以最后只是做了拿来
主义,没有对开源的Amoeba和当时的Cobar有所贡献。
回到淘宝,因为有东西可以借鉴,我们在一个多月的时间内就完成了TDDL1.0
版本的工作。上线过程中虽然出了点小问题,不过总体来说是比较成功的。
TDDL2.0时代
随着使用TDDL的业务越来越多,对业务方来说,DBA对于使用MySQL以及数据切
分也积累了比较多的经验,于是决定开始动核心应用了。
“评价”是第一个重要的应用,评价最重要的问题还是在于双向查询、评价、被评价。于是我们的异构数据源增量复制就派上了用场。
然后是“商品”,我们在商品上投入了近半年的时间,失败很多,也成长得最
快。
-容量规划做得不到位,机器到位后因压力过大,直接死掉,于是产生了数据库
容量线上压力模拟测试。
-历史遗留问题,商品几乎是所有的业务都会使用的资源,所以接口设计比较复
杂。很多接口的调用在新架构上很难以低成本的方式实现。而推动业务改动,则需
要大量的时间和成本。
-数据层代码被业务代码侵染,看起来似乎应该是数据层的代码,但实际上又只
有商品在使用。这种问题让数据层的依赖变得更加庞大,边缘代码变得更多,冲突
更明显。
TDDL3.0~TDDL4.0时代
在商品之后,似乎所有的应用都可以使用类似的方式来解决业务增长上量的问
题。但正当我们志得意满的时候,却被“交易”撞了一个满怀。
我一直很感谢交易线的所有同仁,他们是淘宝草根精神的典型代表——功能可
以做得不那么“漂亮”,但必须减少中间环节,真正做到了实用、干净、简洁。我
们在向他们介绍产品的时候,他们对我们的实现细节提出了非常多的质疑,他们认
为整个流程中只有规则、主备切换对他们是有意义的,而解析、合并则是他们所不
需要的功能。
“不需要的功能为什么要放到流程里?增加的复杂度会导致更多的问题”。在
当时,我感到很痛苦,因为我无法回答他们这些质疑之声。
不过,也正是因为这些质疑,让我有了一个契机,重新审视自己所创造出来的
产品。
我问自己:它能够给业务带来什么益处?
对此,我的回答是:
-规则引擎切分规则可以用配置的方式帮助业务隔离具体的数据库地址与用户
的业务逻辑;
-单机主备切换;
-数据源简化和管理。于是,我们就产生了TDDL3.0版本。其主要的作用就是将
代码做了逻辑切分,将单机主备切换和数据源管理独立了出来。这样,可以针对不
同的业务需求,给予不同的逻辑分层。让每一个业务都有适合自己的使用数据库的
方式。
同时,我们开始做工具,RtoolsJADE作为数据库运维平台的组件被提了出
来。在它的帮助下,我们发现能够极大地提升用户在使用单机数据源和多机数据源
时的效率。用户只需要在客户端给定两个属性,就可以立刻开始使用。结果是用户
反馈比以前好了很多。
这也坚定了我们开发工具的决心。
工具平台时代
在尝到工具平台的甜头以后,我们在工具组件上走得更远了。
首先被提出的是“愚公”数据迁移平台。该平台能够在多种异构的数据库中进
行数据的平滑移动,对业务影响很小,并且也允许业务插入自己的业务逻辑。
这个东西主要能够帮助业务进行数据库自动扩容,自动缩容,单机、多机数据
迁移,在Oracle到MySQL数据迁移等场景中都发挥了重要的作用。
然后,又以内部开源的方式提出了“精卫”数据增量复制平台。这个平台基于
数据库的通用数据分发组件,基于开源的Tungsten进行了大量BugFix和结构调优。
在数据的一对多分发以及异步通知给DW和搜索等场景中都发挥了重要的作用。
TDDL的现在
粗略统计下来,TDDL已经走过了4年的时间,满足了近700个业务应用的使用需
求。其中有交易商品评价用户等核心数据,也有不那么有名的中小型应用。量变产
生质变,如何能够更好地帮助这些业务以更低的成本更快地完成业务需求,将成为
数据层未来最重要的挑战。
Session框架
介绍Session框架之前,有必要先了解一下Session。Session在网络应用中称
为“会话”,借助它可提供客户端与服务系统之间必要的交互。因为HTTP协议本身
是无状态的,所以经常需要通过Session来解决服务端和浏览器的保持状态的解决
方案。用户向服务器发送第一个请求时,服务器为其建立一个Session,并为此
Session创建一个标识,用户随后的所有请求都应包括这个标识号。服务器会校对
这个标识号以判断请求属于哪个Session。会话保持有效,默认状况下,直到浏览
器关闭,会话才结束。
Session中存储的内容包括用户信息:昵称、用户ID、登录状态等。
当网站服务器只有一台的时候,用Session来解决用户识别是很简单的,但是
当网站是一个集群的时候,同一用户的两次请求可能被分配到两台不同的服务器上
处理。怎样保证两次请求中存取的Session值一致呢?还有一个问题:网站规模扩
大时,对于一个具有上亿个访问用户的系统来说,当大部分用户的Session信息都
存储在服务端时,要在服务端检索出用户的信息效率就非常低了,Session管理器
不管用什么数据结构和算法都要耗费大量内存和CPU时间。如何解决服务端Session
信息的管理?
解决集群Session共享的问题,通常有以下两种办法。
-硬件负载,将用户请求分发到特定的服务器。
-ySession复制,就是将用户的Session复制到集群内所有的服务器。
这两种方法的弊端也很明显:
-成本较高。
-性能差。当访问量增大的时候,带宽增大,而且随着机器数量的增加,网络负
担成指数级上升,不具备高度可扩展性,性能随着服务器数量的增加急剧下降,而
且容易引起广播风暴。
这种情况下,Tbsession框架闪亮登场了。Tbsession框架致力于解决以下几
个问题。
-Session的客户端存储,将Session信息存储到客户端浏览器Cookie中。
-实现服务端存储,减少Cookie使用,增强用户信息的安全性,避免浏览器对
Cookie数量和大小的限制。
-Session配置统一管理起来,集中管理服务端Session和客户端Cookie的使用
情况,对Cookie的使用做有效的监管。
-支持动态更新,Session的配置动态更新。
简单地说,就是要么用客户端Cookie来解决问题,要不用服务端的集中缓存区
(Tair)的Session来解决登录问题。Tair已在前文介绍过,Session对它的使用
就不再描述了。
为什么这里还要提到用Cookie这种比较“落伍”的方式呢?其实是因为在淘宝
3.0版本以前,我们一直都用Cookie来识别用户,Cookie是放在客户端的,每一次
HTTP请求都要提交到服务端,在访问量比较小的时候,采用Cookie避免了Session
复制、硬件负载等高成本的情况。但随着用户访问规模的提高,我们可以折算一
下,一个Cookie大概是2KB的数据,也就是说,一次请求要提交到服务器的数据是
网页请求数据,再加上2KB的Cookie,当有上亿个请求的时候,Cookie所带来的流
量已经非常可观了,而且网络流量的成本也越来越高。于是在3.0版本中,我们采用
了集中式的缓存区的Session方式。
到此为止,应用服务切分了(TM、IM)、核心服务切分了(TC、IC)、基础服
务切分了(UIC、Forest)、数据存储切分了(DB、TFS、Tair),通过高性能服
务框架(HSF)、分布式数据层(TDDL)、消息中间件(Notify)和Session框架
支持了这些切分。一个美好的时代到来了,高度稳定、可扩展、低成本、快速迭
代、产品化管理,淘宝的3.0系统走上了历史的舞台。
在这个分布式系统的支持下,更多的业务迅速开发出来了,因为任何一个业务
都基于淘宝的商品、交易、会员、评价等基础体系,而这些基础体系就像“云”一
样存在,现在可以随处调用了。Hitao、淘花网、良无限、天猫、一淘、聚划算、各种SNS、各种移动客户端等如雨后春笋般地成长起来了。目前,淘宝已经变成了一个
生态体系,包含C2C、B2C、导购、团购、社区等各种电子商务相关的业务。
既然说是一种“生态体系”,那就不能把所有的业务把控在自己的手中,在开
发3.0版本的过程中,我们就有一个团队把淘宝“开放”出去了,我们把自己的数
据、自己的应用通过接口的方式让更多的开发者调用,他们可以开发出形形色色的
产品,例如,你可以开发出心形的淘宝店铺、菱形的店铺,再放到淘宝上供商家购
买。淘宝再多的员工,其创造力也是有限的,而开放出去之后,让无限的人都可以
参与到这个生态体系的建设中来,这个生态体系才是完整的。下面就是开放平台的
架构师放翁所记述的“开放平台这几年”注11。
开放平台
2006年年底:阿里巴巴提出了Workatalibaba的战略,二十多个人就被拉到湖
畔花园马云的公寓里开始一个叫阿里软件的公司创业。当时对于Workatalibaba有
一个朦朦胧胧的感觉,就是要为中小企业提供一个工作平台,但是工作平台又需要
是一个开放的平台,因为卖家的需求是长尾的,当时火热的Salesforce给了阿里人
(注1作者放翁在文中涉及的所有技术点都可以在
http:blog.csdn.netcenwenchu79中找到详细的内容,同时本文主要介绍开放
平台技术发展历程,产品和业务内容不涵盖在此,因此,受众群体主要是技术人
员。——作者注)一些启示,那就是做一个支持二次开发的工作平台,半开放式地
满足各种卖家的长尾管理需求。此时,软件市场上就开始培养起最早的一批TP(淘
宝开放合作伙伴)。迄今为止,很多非常成功的TP就是从那个时候开始进入淘宝卖
家市场的。
但经过一年的平台建设,发现开发者非常难利用平台做二次开发,只有阿里软
件公司内部的团队构建了三个不同的CRM软件。这时候淘宝来了一个业界的技术牛人
王文彬(花名:菲青),这位淘宝新晋的首席架构师找到阿里软件的平台架构团
队,谈到了当时业界还非常新颖的一种技术平台——开放平台。由于阿里软件已经
在做类似的开放工作,希望能够以合作的方式来试水开放平台。当时双方都是一种
尝试的态度,因此,最后敲定投入一个人花两周时间,看是否能够做出原型,如果
可以,就继续做,如果出不了原型,就此结束。两周时间里,负责阿里软件的架构
师放翁参看着美国雅虎的开放模式就搞出了开放平台的第一个雏形,没想到就这样
开启了5年的开放之路。后面会根据时间轴来说一下开放平台的产品和技术的变革,每一年会发生很多事情,但是调出的一点一滴是当年最有感触的。
2007年:萌芽。SOA盛行的年代,内部架构服务化成为开放的第一步,内部服
务不做好隔离,开放就意味着风险不可控。支付宝今天的服务框架SOFA(类
ESB)、淘宝的HSF(OSGI)、阿里软件的ASF(SCA)都是那个年代的产物,但服务化带来的痛却是一样的,不论是OSGI还是SCA之类的服务框架,本身的服务化规约
设计都类似,但难题也都摆在每个架构师和开发者面前:服务单元Bundle的粒度控
制,服务之间依赖管理,性能与规范的冲突,调试与隔离的平衡。这些都使得一线
开发者和平台框架实现者出现非常多的矛盾,而这个过程能活下来的框架最后都是
摒弃了很多企业级的设计思路,因为SOA架构从企业级产品演变而来,而服务化后的
内部平台要面对的开放平台天生就是互联网的产物。
2008年:雏形。2008年年底,平台开放淘宝服务30个,每天调用量2000次,这
一年开放平台的开发者面向的客户主要是阿里巴巴上的中小企业和淘宝C店卖家。开
放平台建设初期要解决的就是三个问题:
-服务路由。(外部可以获取内部信息)
-服务接口标准化。(统一方式的获得各种标准化信息)
-授权。(外部合法的获取内部信息)
服务路由其实就是写一个高效的HttpAgent,服务接口标准化就是对象文本化
(JSON,XML)。今天在各大开放平台广为使用的OAuth协议,当前处于0.6版本,没有任何实际的互联网开放平台使用,直到Google于2008年年底慢慢地对外推广开
放的时候,OAuth被封装到Google的OpenSDK中,才使得很多中小型互联网公司使
用这种看似复杂的两阶段授权交互模式。淘宝初期采用的是自有协议,因为OAuth2
以前的逻辑较复杂且使用不方便,直到2011年才开始支持OAuth2,同时做了部分的
安全增强。授权解决了开放最大的一个问题:用户安全的对应用访问其数据受信。
用户从此不用赤裸裸地将用户名和密码交给一个应用软件,应用也可以在允许的范
围内(操作、数据、授权时长)充分利用用户授权来玩转创意。
用户名密码UserAPP用户名密码网站UserAPP应用受信令牌用户名密码授权网站
有了上面的三板斧(路由、数据规范和授权),开放平台正式开门迎客了,没有对
外做任何的推广,日均调用数据就猛增到了1000次,此时两个互联网的新兴技术
Memcached和Hadoop开始在开放平台中尝试。今天看来,这两个技术已经被大规模
地使用,Memcached无疑是最好的选择,但当时号称分布式缓存的Memcached其实
是集中式缓存的一种,真正的分布式缓存还都在纠结于一致性和效率的问题(第2、3阶段提交)。此时需要有一种方式能够保证效率(可扩展)和稳定性,于是我们封
装了Memcached客户端,提升当时BIO的Java客户端的性能,同时引入了客户端负载
均衡和容灾的设计,这种设计已经被应用在现在很多大型分布式系统中。另一方
面,每天上千万的访问也让技术和产品对访问的行为有很强的分析需求,此时,Hadoop在雅虎的充分利用引起了我们的重视(当时的雅虎技术创新一直都是业界的
领头人),通过仅有的两台机器和一堆技术文档,我们摸索着搭建了公司内部的第
一个Hadoop集群,而所写的Hadoop入门实践也成为当时Hadoop入门的基础文档,对于每天2000次调用量的日志分析需求来说,Hadoop用得游刃有余,但随着业务的
不断发展,Hadoop离线分析所带来的问题也凸显出来,MR程序面对灵活多变的分析
需求,显得不易维护且效率低下(数据反复读取分析),于是我们也开始思考怎样
改进这个新玩意儿。
2009年:产品化。到2009年年底,平台开放淘宝服务100多个,每天调用量为
4000次,这一年开放平台的开发者面对的主要是淘宝C店卖家,卖家工具成为服务市
场的主流。这一年也是变化的一年,阿里软件年中的分拆使得开放平台的归属有些
微妙,一种情况是留在阿里云,作为集团的基础设施,另一种情况就是跟着主要的
业务需求方淘宝走,最后我们还是说服了博士,结束了阿里软件的老平台,淘宝正
式开始自己的开放之路。来到淘宝后,业务开放迅猛增长,从30个API猛增到了100
个API,没有对外做任何业务推广,平台调用量到了年底翻番。此时技术上的挑战又
聚焦到了性能上,一次APICall的业务消耗平均在30~40ms,开放平台当时的平台
处理消耗平均在10ms左右。我们做了数据打点和分析,发现最大的消耗在于互联网
数据的接收,同时大量的图片数据上行,更是加大了平台处理时间。另外,从访问
日志分析中可以看到很多无效的请求也占用了非常多的处理时间,这也意味着无效
请求和有效请求一样在消耗着有限的容器线程资源。于是我们开始尝试自己封装字
节流解析模块,按需解析上行数据,一来可以提升数据分析的性能(并行业务和数
据增量分析操作),二来可以用最小代价处理异常请求(当发现不满足业务规范
时,则立刻丢弃后续所有的数据),这块实现被叫做LazyParser,主要的实现重点
就是最小化数据缓存来进行并行业务和数据解析操作,上线后效果不错,整个系统
平均处理时间从10ms降低到了4ms。(包含了异常处理的优化和解析性能的提升)
另一方面,Hadoop的MR问题也日益突出,一大堆MR的Class(类)维护成本
高、性能问题也随之出现。此时我们开始尝试抽象分析业务场景,想到的是是否能
够通过配置就可以完成各种统计分析需求。要用配置替代代码,其实就看是否可以
穷举代码所实现的各种统计需求。当回顾SQL的理念时,发现其实所有的统计在切割成为KV作为输入输出时,所涵盖的需求无非是Max、Min、Average、Sum、Count、Distinct(这个是2012年实现的,用了bloomfilter和AtomicLong),再
复杂一些无非就是上述几个操作结果的数学表达式运算。因此,KV输入和KV输出的
离散统计配置需求已经抽象出来了,接着就是把统计完的一组组KV根据K来做
Groupby(分组),就生成了传统意义上的报表(K,v1,v2…)。从此以后,每天
的统计需求都通过配置来改变,再也没有一大堆MR代码,同时一次数据输入就可以
完成所有分析的处理,性能上得到了极大的提高。
虽然Hadoop每日分析抽象出模型配置解决了性能和易用性的问题,但是对于即
时分析却不太适合,当时出于监控的需求,希望能够一个小时就可以对数据做一次
增量的分析,用于监控服务整体的调用情况,保证对异常问题的即时排查。由于一
天4000次的调用量还不算很大,因此,当时就直接考虑采用MySQL分库分表的方
式,然后定时做SQL的查询,结果发现效果不错。当然,这个过程又产生了一个小组
件,要直到4000次的日志数据写磁盘和DB双份必然会带来不少的IO消耗,同时这
个系统并不是账务系统,丢掉一点日志也没关系。因此,就采取了异步批量数据外
写的设计(多线程守护各自的一块Buffer页,定时外刷或者满页外刷),这样在双
写的情况下,单机的Load也没有超过0.7。
但快到年底的时候,发生了一件事情让我们头痛不已,同时也成了开放平台的
一个“隐形炸弹”。一天晚上,突然发生平台大规模拒绝服务的告警,观察整个集
群发现,业务处理时间从平均的30~40ms,上升到了1s,仔细观察发现,某一个业
务的响应时间大幅攀升,从原来20ms的响应时间飙升到了1s以上,此时由于HTTP请
求的同步性,导致前端服务路由网关的集群线程都释放得非常慢,阻塞处理这个业
务的请求,而其他正常的业务(淘宝开放平台背后的服务由不同的团队维护,处理
时间从1ms到200ms都有)也无法被访问,因此,才有了开始的全线告警的产生。后
来发现是这个业务团队的一次发布中忽略了数据库索引建立导致服务耗时增加,但
这个问题开始时不时地拜访开放平台,开放平台稳定性受制于任何一个业务方,这
是不可接受的。对于这个问题,起先考虑集群拆分,即将重要业务和不重要业务拆
分,但考虑到实施成本(不同服务的利用率差异很大)和业务隔离是否彻底(重点
业务也会相互影响),最终放弃了这个想法。当时又想到了软负载切割Haproxy和LVS,一个是七层的网络软负载切割,一个是四层的负载切割,由于涉及业务,于是
考虑用七层的软负载切割,尝试一台Haproxy挂7台虚拟机,然后运行期可动态调
整,配置在出现问题的时候可人工干预切割流量。就这样,我们有了告警以后可以
手动切割的半人工方式干预措施。但我们依然晚上睡不踏实……(期间考虑过Web请
求异步化和Servlet3的模式来规避同步HTTP带来的平台阻塞,但当时唯一支持
Servlet3的Jetty和Tomcat做压力测试,效果都很不稳定)
2010年:平台化。到2010年年底,平台开放淘宝服务300多个,每天调用量为8
亿次,这一年淘宝正式开始对外宣传开放,淘宝开放年赢在淘宝,目前很多年收入
上千万的TP在这个时候成了先锋(2010年以前的可以叫做先烈),产品层面上,这
一年除了卖家工具的继续发展,SNS热潮的兴起带动了淘江湖的买家应用,游戏应用
的淘金者蜂蛹而入,开放的服务也继续保持300%的增速,覆盖面从卖家类延伸到了
买家类,从简单的API提供,到了淘宝网站支持深度集成应用到店铺和社区。
在8亿次访问量的情况下,再用MySQL做流式分析已经不可能了,分析时间要求
也从一个小时提升到了20分钟,此时经过快一年半的Hadoop使用和学习,再加上对
分布式系统的了解,正式开始写第一版的流式分析系统,MR的抽象依旧保留,而底
层的数据计算分析改用其他方式,这个“其他方式”和Hadoop的差异在于:
-分析任务数据来源于远端服务器日志(主要通过Pull,而非Push)。
-任务分配和调度采用被动分配(有点类似于VolunteerComputing的模式),Mater轻量的管理任务,Slave加入即可要求执行任务,对任务执行的情况不监控,只简单通过超时来重置任务状态。
-任务统一由Master来做最后的Reduce,Slave可以支持做Shuffle来减少数据
传输量和Master的合并压力,Master负责统一输出结果到本地。
总的来说,就是数据来源变了,数据不通过磁盘文件来做节点计算交互(只在
内存使用一次就丢掉了),简化任务调度,简化数据归并。这样第一版本的流式分
析出来了,当然,后面这些设计遇到的挑战让这个项目不断在演进,演进的各种优
化几年后发现都在Hadoop或者Hive之类的设计中有类似的做法。(参看Blog,地址
为http:blog.csdn.netcenwenchu79,根据时间轴可以看到各种结构优化和性
能优化的过程)这个系统三台虚拟机撑住了8亿次的日志即时分析,MySQL日志分析
就此结束。
这一年另一个重大改变就是更多的人对开放的价值有所认同,淘宝从一个部门
的开放走到了淘宝公司的开放,什么叫做部门开放?就是在10年以前大部分的API开
放都是开放平台这个团队来做封装维护,30个API还可以支撑,100个API已经让一
个专业的小团队应接不暇(当然不得不承认,迄今为止,淘宝最有全局业务知识的
还属这个团队的成员),300多个API这种势头基本上就无法由一个团队来做了,业
务变更带来的接口不稳定经常被投诉。因此,我们启动了服务轻量化的“长征项
目”,逐渐通过工具和平台将服务接入变成自动化的方式,将原来开放一个服务需
要点对点,手把手花一周时间实施完成的过程,通过自动化服务发布平台,一个人
一天时间就可以发布一个服务,并且服务的文档中,多语言版本SDK都自动生成。这
样就具备了服务轻量化的基础,然后将各个新开放的业务采用这种模式接入,而老
业务逐渐归还给各个业务方去维护。这样,服务的“稳定性”(业务方面)得到了
非常大的提升,用户对于服务的满意度也得到了极大的提高。
但这个担子放下了,那个担子又挑上了,在上面谈到后台应用不稳定导致平台
整体不稳定的问题在轻量化以后出现的频率和次数更多了,因为发布和维护都落到
了后台部门,此时对于各个系统的把控就更弱了,KPI中的稳定性指标基本就没法定
了。唯一能够彻底解决问题的办法就是HTTP服务异步化+事件驱动+虚拟隔离线程
池。2010年年中对Jetty7做了一次压测,发现Continuations的效果已经可以上正
式的环境了,于是开始在Jetty7的基础上做HTTP服务异步化+事件驱动的封装,同
时也实现了一个虚拟隔离线程池做配合。具体设计细节这里就不再多说,参看
Blog,简单描述原理如下:
-将前端容器线程和业务处理隔离。(类似NIO和BIO的设计差异)
-业务处理如果依赖于外部系统,则采用事件驱动的方式来减少线程等待,同时
提高线程占用资源的利用率。(从这点上说,理想和现实还是有很多细节差异的,在实现的时候必须根据依赖系统消耗时间占总时间的比例看是否需要事件驱动,事
件驱动带来的切换消耗是比较大的)
-通过一个大的线程池虚拟设置不同的业务可消耗的最大资源数,来充分共享资
源在异常情况下限制业务占用过多的资源(任务处理开始排队,而非无度地占用资
源)。
这个组件上线以后,没过几天就发生了一个典型的案例,一个业务在下午2点开
始响应时间从10ms上升到了40ms,然后继续上升到200ms,当时给这个业务模拟设
置最大的线程资源数是20个,就发现那时候由于RT时间提升,线程资源释放得慢,20个慢慢地被消耗完了,此时这个业务的队列开始从0到100,再到200……(当然,防止内存过多地被占用,会丢弃超过队列长度的业务处理),而其他业务还是正常
地使用着资源,平台平稳,到了下午4点多,业务方收到告警修复以后,RT时间下降
到了10ms,队列中的请求数量开始减少,最后队列清空,线程资源占用下降到正常
水平。
从此以后,震子开心地和我说:开放平台稳定性的KPI可以随便大胆地写几个9
了。
2011年:市场化。到2011年年底,平台开放淘宝服务758个,每天调用量19亿
次,这一年SNS热潮消退,游戏逐渐淡出,卖家市场依旧生意火爆,营销工具崭露头
角,成为开发者新宠,淘宝客成为开放新宠(这一年返利网和团购一样火,只是前者收钱,后者烧钱)。
就在开放平台前景一片大好的时候,出现了一个让开放转变和收缩的导火索,一家做营销工具的公司“团购宝”每天凌晨都会通过接口同步客户设置的一些优惠
商品信息到淘宝网,结果那天凌晨,微博上突然有很多人说某些店都是一块钱的便
宜货,要知道这种事情在微博盛行的时代,传播速度之快,影响之大,当即很多卖
家商品都被1块钱拍下。最后发现是线下的商品价格不知道怎么全被修改成1块钱,然后凌晨一同步,就导致出现了上面的一幕。从那时候开始,开放平台的KPI中增加
了一个重中之重的功能:安全,包括后面的很多技术产品都围绕安全展开。此时第
一个被波及提升能力的系统就是流式分析集群,20分钟一轮的数据分析要求压缩到3
分钟,同时数据量已经从每天8亿条增长到了每天19亿条,花了两个月时间断断续续
地优化集群结构设计和单机处理能力,对于其中经历的内容,有一天我翻Hadoop的
优化过程时看到了相似的场景,具体就不在这里赘述,详细内容可参考Blog。简单
地说,包括四个方面:充分利用多核能力用计算换内存;磁盘换内存,用并行设计
来保证整体业务时间消耗不变甚至减少;SlaveShuffle来减少Mater的合并压力;
数据压缩减少数据传输消耗和内存占用。
另一方面,由于2010年对于Jetty7的充分理解和封装,此时看到了又一个新技
术的契机,2010年去美国参加Javaone,当时看到有老外用Jetty7的特性来实现
Comet功能,Comet原先主要用于CS结构的应用搬到互联网上,因为不能用TCP的长
连接,所以不得不用HTTP的长连接来替代原来的模式,同时国外开放平台也关注很
多新型的API设计,其中就有Twitter的StreamingAPI,这种通过HTTP长连接方式
推送消息到外部ISV(独立软件开发商)的模式引起了我们的注意。因此,我们决定
将Jetty7上的封装近一步升级,支持Comet长连接方式,后端通过事件驱动的模式
主动推送内部消息给外部,避免外部轮询业务接口。这个设计最重要的一点就是如
何用最有效且最少的线程来守护多个长连接,支持到后端事件驱动的数据下行,如
果给每一个长连接支持一个数据推送守护线程,即时性自然最高,但代价就是消耗
众多空置连接的守护线程(详细内容见Blog)。这种模式刚出来的时候,从上到下
都是质疑声,觉得太不符合常规做法,常规做法就是pull,认为开发人员无法接
受,稳定性一定不靠谱。经过2011年的“双十一”,当天几个“尝鲜”的开发者用一台PC就支持几百万笔订单的高速处理,就让很多人明白了,技术要敢想,代码要
敢写,细节要敢专,没什么不可能。也就从这以后,多样化服务TQL、ScheduleAPI、ATS从开放平台的土壤上都长了出来,为更多的场景和更多的终端提
供了各种解决方案和创新实现。
2012年:垂直化。这一年到现在,平台开放淘宝服务900多个,每天调用量为
25亿次,这一年淘宝客由于公司方向转变热潮消退,无线乘势而起,新业务(机彩
票、酒店、理财等)、P4P、数据类服务都开始运营API,开放平台开发者的客户群
体也从C店卖家增加到了B的品牌商和渠道商等。
这是一个业务多变的一年,这也是淘宝内部对开放平台认可的新阶段。第一个
阶段是放任不管,任由开放平台部门开放和封装。第二阶段是由业务方负责支持开
放业务,但开放后的结果概不了解,也无所谓了解。第三阶段就是业务主动要开
放,开放后开始运营服务,培养ISV市场,带动业务的正向发展。
这一年由于业务量的增长以及分析需求到用户纬度,因此,在2011年年底启动
了流式分析集群重构升级的项目,将新的分析集群项目命名为Beatles,希望它能
够象甲壳虫一样,小虫吃树叶,再多都能吃下。2011年底到2012年初,用了近两个
半月的时间做了一次完整的重构,将那么多年的补丁经验和老代码重新设计和实
现,并且将Mater根据业务可垂直切分,最终解决Master归并压力的问题,当然期
间的技术优化点也不少,因为我们的目标从3分钟压缩到了1分钟,而我们的数据量
翻番,统计纬度细化到了用户纬度。(意味着结果也会很大,如果不靠文件做中
转,如何来实现需要更多的分拆和协同设计)
这一年起了两个比较创新的项目:JSSDK和无线SDK(IOS,安卓),这两个SDK
的出现在一定程度上由业务和安全两方面决定。首先,2011年年底启动了社区电子
商务化的项目,也就是现在所说的轻电商(XTao)项目,将更多的网站和淘宝衔接
起来,此时网站间的融合就要求更轻便和简易,最成功的案例就是Facebook,于是2012年年初的时候,拿这FackBook的JSSDK一阵看,就开始动手写了,期间很高兴
拉了UED入伙,这才使得这个JSSDK变得更加靠谱,更加专业。同时有了JSSDK,买
家的服务安全性有所保证,因为原先的REST调用在授权以后是无法知道是用户发起
的还是服务器发起的,而JSSDK从一定程度上还要校验Cookie的有效性,可以部分
保证用户的在场和知情。而下半年的无线SDK,就是苦读一个月的各种文档,然后就
开始动手玩儿了,由于对Java语言、动态语言、脚本语言都有比较多的使用,因
此,Objective-C语言上手并不是那么困难,同时没有涉及过多的MVC的内容,做
SDK基础层的东西还是比较得心应手的,就这样IOS的无线SDK版本就生成了,此时
在开放平台的技术团队内部正在执行一个叫做Hackproject的活动,其中一个自主
项目就是安卓的SDK,因此,一个月后,安卓的SDK顺利诞生了。这两个无线SDK所
担负的职责就是把控无线安全问题,不仅是淘宝,业界其实很多公司都还没理解无
线开放的风险到底有多大,OAuth2基本就无法保证无线的用户安全,因此,如何在
SDK和服务端融入更高级别的安全设计,成了无线SDK诞生的第一个重要需求。
另一方面,开放平台安全体系的构建成为2012年的重点,从两个角度对安全做
了全方位的控制。
第一,用户。用户授权更细化了授权操作范围(细粒度到了数据范畴),授权
时长。所有的信息可监控、归档、快速定位,我们内部叫做TopOcean,简单说来就
是对所有的访问日志做归档,归档的载体是块状文件,归档时对块状文件的所有记
录按照需求建立索引,然后保留索引,上传本地文件到远端分布式文件系统备份。
实时的监控服务调用和应用访问,授权异动。
第二,第三方应用。采用监控集群对所有ISV的服务器做安全扫描,对普通的
Web安全漏洞做扫描,对应用的可用性和响应时间做监控。同时,正式启动“聚石
塔”项目,提供弹性计算和存储能力及可靠的安全网络环境给ISV,帮助ISV提供自
身应用的安全性。
至此为止,5年左右的技术历程已部分展示在了大家的面前,这些只是5年中比较有代表性的一部分,同时技术的发展也只是开放平台的一部分,前5年是技术变革
带动开放平台发展,而接下去的5年将会是业务变革和理解带动开放平台的阶段,对
业务的理解直接决定了开放平台的价值所在。前面轻描淡写地介绍了5年来不同开放
业务的兴衰,其实这背后却有更多耐人寻味的故事,而5年后的今天,淘宝的格局
为:集市(C2C)、天猫(B2C)、一淘(电商搜索返利入口)、无线、新业务、O2O(本地生活)、团购平台(聚划算),这些平台的价值是什么?如何找到自身定
位?如何借助外力发展?如何面对流量入口的兴起、传统互联网企业的电商化、电
商平台的竞争?这些才是开放平台2012年及下一个5年的精彩所在。
第四部分我在淘宝这八年
“所有的进步都是不稳定的,一个问题解决了,我们不得不面对又一个新问
题。”——马丁?路德?金
2011年12月8日那天,有同事恭喜我,我才知道自己在淘宝已经七周年了。很
多人问“七年痒不痒?”老实说,也曾经痒过,但往往都是一痒而过,然后又投入
到水深火热的工作中去。回家之后就想,我在这七年到底收获了什么,且不论成败
与否,这七年的经历,是我人生的宝贵财富。第一年(2004年—2005年)
@正牌七公曾经说过,要是写一本淘宝的历史书,一定有很多人感兴趣,其实我
也很想写写这样一本书。2004年12月8日入职的时候,我和@衲子如幻一起进来,迎
接我的是骆冰和黄裳@岳旭强,骆冰是百阿的班主任,黄裳是我的师父。当时还没有
百淘,先参加了百阿,百阿给我发了一本书叫《完美商店》,介绍的是eBay的故
事,看的时候我就想什么时候我也写一本关于淘宝的故事来。
我进淘宝非常偶然,当时只是看到这个网站做得不错,自己也不想继续做对日
外包的工作了,就过来面试了一把。刚进淘宝的时候,我被震撼了,它跟传统的企
业非常不一样,到处都是生机勃勃的样子,还有前台的@香香的好朋友笑得很亲切,之前见到的公司前台的态度都是冷冰冰的。@武当三丰给我两张笔试题做,后来居然
通过了。财神面试我的时候,问我为什么到这里来,我说很欣赏这家企业发展这么
快,这样的企业一定有很多高手,跟高手在一起成长一定很快。我每说一句,他点
头“嗯哼”一下,以至于后来我跟我老婆形容公司的CEO时,她只记得那个喜欢“嗯
哼”的人。
来淘宝做的事情是做Java开发,但是之前我只做过3个月的Java项目,连
Eclipse都不熟(我来之前恶补了一下快捷键的操作)。一开始做事是在@岳旭强手
把手的指导下做的,当时非常依赖旁边的几个老员工——多隆、正风、进宝、我
行、不同、范禹、天川。做的事情也没有一个成熟的流程,常常是大家在论坛看到
有人需要什么功能,我们问问PD是不是需要做,然后就写代码,提交给测试人员
(给自在、郭芙、宝驹),最后就让青青打包,让剑英发布。我还很清楚地记得做
的第一个需求是,有卖家说不想把货卖给信誉为一颗心以下的买家;有卖家不想卖
给某个省市的买家,我就给卖家一个工具,让其限制某些买家不能买。于是我就在
发布商品的流程和生成订单的流程中,找到合适的地方,加了几个合适的参数,写
了几段合适的代码,就发布上去了,但是这个功能一直没敢启用。直到3年之后,2008年要拆分Denali的时候,这段代码都在,但都没有发挥作用。
做完第一个需求后,自己写的代码在系统上运行了,一下子有了信心。当时HR
成立了百淘的项目,我先去百淘二期干了几天(本来要我参加一期的,但当时忙,延迟到了二期,现在百淘已经过一百期了),回来就投入到一个更牛的项目——支
付宝。
支付宝一开始生存在淘宝系统上,但到2004年年底的时候,老马的慧眼看到了
支付宝的未来。当时请了Sun公司的人把淘宝的第一个PHP版本变成了Java版,之
后,就让他们做独立的支付宝系统。我和天川从淘宝派出来做支付宝和淘宝相关的
业务,当时除了Sun公司的人和淘宝的人,还来了一位标志性的人物@fenng,他是
这个项目的DBA,记得他刚来杭州时,家里要装宽带,运营商服务不周到,被他骂了
好久。后来(2010年)他在微博上大战中国电信已经相当有经验了。项目组中还有
另外几个让我非常佩服的人——鲁肃、苗人凤,二人后来成了支付宝的首席系统架
构师和业务架构师。就这么跟着这样一帮牛人干了3个月,支付宝在五一节的时候上
线了。还记得几个DBA在做数据迁移时候的囧样,数据结构已经面目全非了,@正牌
七公、@fenng、多隆、鲁肃搞了三天三夜。我们熬夜的时候还有杭州的卖家跑来看
我们,有一位是璧君,后来直接加入了淘宝。
当时那热火朝天的岁月令我至今难忘,我三天三夜没回家的时候,我老婆还打
电话过来问“你到底还爱不爱我了?”我说:“怎么会不爱呢?”
进淘宝的第一年,我的级别是P1,现在已经没有P1了,后来调整过,我当时进
来应该是现在的P3,记得那年年底的时候,三丰给了我4分的评价(超出期望),然
后升级为P4,那是我成长最快的一段时期。
第二年(2005年—2006年)
做完支付宝,公司举办了一场硕大的庆祝仪式,带我们一帮人去了千岛湖,玩
得很爽,但我有点不安,因为我与他们在一起才3个月,实际上只做了3个功能,一
个是创建支付宝交易的接口、一个是接收支付宝订单状态的接口、一个是绑定和解
绑支付宝账号的功能,而其他牛人设计出了一个巨大的系统,我处于深深的拜服
中。半年之后,淘宝网组织的郊游又去了千岛湖,后来,另外两个项目的庆祝也去
了千岛湖,以至于我都认识那边的道路了。
从千岛湖回来,真正苦逼的日子开始了,我很长一段时间都在做善后的工作,就是支付宝系统中的一些问题。由于支付宝和淘宝是两个独立的系统,系统之间的
通信是一个大问题,而银行与支付宝也需要通信,于是问题就经常出现:用户在银
行付款后,未必能通知到支付宝,支付宝收到通知后,未必能通知到淘宝,于是用
户的钱没了,淘宝的系统上却显示未付款,很让人崩溃。我和鲁肃尝试了很多种办
法,一开始用MQ,但并发量上来之后老丢消息,消息的时间顺序也会错,后来他做
了一个消息中间件系统,这个就是淘宝的Notify的雏形,现在Notify一天能发送几
亿条消息通知,能保证通知到,也能保证不重复通知,还能保证消息有次序,相当
不容易。
三丰看我在支付宝方面做了很多事情,而且跟鲁肃他们合作得这么好,还以为
我水平大有长进,于是在维护着支付宝接口的同时,我开始了做PM(项目经理)的
生涯。据说,我是淘宝的第一个PM,这让我很爽,我在做PM的过程中与SQA一起整
理出了《项目管理流程》《PM工作手册》《系统设计模板》等开创性的工作,有些
东西沿用到了现在。但后来有人提出敏捷概念的时候,我又在反思,我是不是误导
了淘宝的项目开发模式很多年?
我的PM生涯从2005年持续到2008年,这三年又大致分两个阶段,一个是“新手
上路”阶段,自己摸索着做了“商品详情拆分”、“收藏夹改造”、“支付宝认
证”几个项目;另外一个是“死去活来”阶段,做了“我的淘宝AJAX版”、“招财进宝”、“淘宝旅行”。为什么是死去活来?因为后面这三个项目死了两个,活了
一个。
“商品详情拆分”是在2005年开始做的,三丰说让我当项目经理,我看到“经
理”两个字就吓得半死,但后来知道该项目组就我和拖雷两个人。要做的事情非常
......
您现在查看是摘要介绍页, 详见PDF附件(4570KB,195页)。





