马云说过“一个好的东西往往是是说不清楚的”,姑且不论这句话的对与错。但我真的很佩服《淘宝技术这十年》这本书的作者子柳,能够通过淘宝的一些故事,按照时间顺序和IT发展的各种技术描述清楚,而且过程中读起来非常有意思。
该读书笔记中参杂了很多原文的知识,因为我实在无法割舍,都挺有意思的;同时记录一些有用的知识,通过这本书能介绍些学过的知识或面试中可能出现的题目及作者所思,文章还是非常有趣的,希望对大家有所帮助!
我的师傅黄裳曾经说过“好的架构图充满美感”。一个架构好不好,从审美的角度就能看出来;后来我看了很多系统的架构,发现这个言论基本成立。反观淘宝以前两个版本的架构,如下图所示,你看哪个比较美?
显然第一个比较好看,第二个显得头重脚轻,这也注定了它不是一个稳定的版本,只存活了不到半年的时间。2004年初,SQLRelay的问题解决不了(不能总这样通过不断地重启保证系统的稳定性),数据库必须要用Oracle,那么从哪里动刀呢?只有换开发语言了。换什么语言好?用Java。
Java是当时最成熟的网站开发语言,它有比较良好的企业开发框架,被世界上主流的大规模网站普遍采用。另外,有Java开发经验的人才也比较多,后续维护成本会比较低。
到2004年上半年,淘宝网已经运行了一年的时间,这一年积累了大量的用户,也快速开发了很多功能,当时这个网站已经很庞大了,而且新的需求还在源源不断地增加。把一个庞大的网站的开发语言换掉无异于脱胎换骨。在换的过程中还不能拖慢业务的发展,这无异于边换边跑,对时间和技术能力的要求都非常高。
做这样的手术,需要请第一流的专家来主刀,现在再考一下大家:亲,如果你在这个创业团队中,请什么样的人来做这件事呢?
PS:我的想法是请多隆,不是说“有困难找多隆”吗?他就相当于武侠小说中的扫地僧,也是淘宝的“神”。但他可能也需要自己学习吧!所以这样的答案也是不正确的,《淘宝技术这十年》读书笔记最后一篇博客我也将介绍淘宝网众多的大牛,其中第一位就是多隆。顺便说说,大家知道马云最喜欢的金庸小说里的人物是谁吗?没错,他就是风清扬。当时看到一个新闻,说马云想出演《笑傲江湖》风清扬一角色,找了很多关系,最后还是被导演无情的拒绝了,不知道消息是否真实,但确实挺有意思的!
我们的答案是请Sun公司的人。没错,就是创造Java语言的那家公司,世界上没有比他们更懂Java的了。除此之外,还有一个不为人知的原因,我刚才说到Java被世界上主流的大规模网站普遍采用,其中有一个网站就是eBay,那时eBay的系统刚刚从C++改到Java,而且就是请Sun的工程师改造成Java架构的,这下你懂了吧?他们不仅更懂Java,而且更懂eBay。
Sun公司的这帮工程师的确很强大,在笔者2004年年底淘宝的时候,他们还在,我有幸与他们公事了几个月。现在摆在他们面前的问题是用什么办法把一个庞大的网站从PHP语言迁移到Java?而且要求在迁移过程中不停止服务,原来系统的bugfix和功能改进不受影响。亲,你是架构师你怎么做?
有人的答案是写一个翻译器,如同把中文翻译成英文一样,自动翻译(现在机器翻译是自然语言处理的重要应用)。我只能说你这个想法太超前了,“too young,too simple, sometimes native”。当时没有,现在也没有人能做到。
他们的大致方案是给业务分模块,一个模块一个模块地渐进式替换。如用户模块,老的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,复制得毫无保留,我们只能会心一笑。
说了开发模式,再说说用到的Java MVC框架。当时struts1.x是用得比较多的框架,但是用过webwork和struts2的人可能知道,struts1.x在多人协作方面有很多致命的弱点。由于没有一个轻量框架作为基础,因此很难扩展,这样架构师对于基础功能和全局功能的控制就很难做到。
而阿里巴巴的18个创始人中有个架构师周悅虹,他在Jakarta Turbine的基础上做了很多扩展,打造另一个阿里巴巴自己用的MVC框架WebX:
http://www.openwebx.org/docs/Webx3_Guide_Book.html
这个框架易于扩展,方便组件化开发,它的页面模板支持JSP和Velocity等,持久层支持ibatis和hibernate等,控制层可以用EJB和Spring(Spring是后来才有的)。项目组选择了这个强大的框架。
另外,当时Sun在全世界大力推广他们的EJB,虽然淘宝的架构师认为这个东西用不到,但他们还是极力坚持。在经历了很多次的技术讨论、争吵之后,这个系统的架构就变成了下图的形式。
MVC框架是阿里的WebX,控制层用了EJB,持久层是ibatis。另外为了缓解数据库的压力,商品查询和店铺查询放在搜索引擎中。这个架构图是不是好看了一点?
Sun的这帮工程师开发淘宝网后,用同样的架构又做了一个很牛的网站,叫“支付宝”。(上一篇说过支付宝最初是淘宝的“安全交易”功能,这个功能后来独立出来,成立了一个网站,也成立了一个公司,就是现在的支付宝。把支付宝从淘宝分出去的人,就是Sun公司的这几个人。)下图是支付宝第一次员工大会。
上面的结构中,引入了搜索引擎iSearch(它是在LAMP[Linux+Apache+MySQL+PHP]系统运行一段时间之后被多隆引进的,换为Oracle之后知识替换一下数据源)。其实这个搜索引擎的原理很简单,就是把数据库里的数据dump(倾倒)成结构化的文本文件后,放在硬盘上,提供Web应用以约定的参数和语法来查询这些数据。
这看起来不难,难的是数以亿计的信息,怎么做到快速更新呢?这好比你做了一个网站,在百度上很快就能搜到,你一定很满意了。但是如果你发布一件商品,在淘宝上过了1个小时还搜不到,你肯定很郁闷。另一个难点是如何保证非常高的容量和并发量?再往后面就要考虑断句和语义分析的问题,以及推荐算法等更加智能的问题。这些内容先不详细介绍,因为搜索引擎的技术已经足以写好几本书了。
其实在任何时候,开发语言本身都不是系统的瓶颈,业务带来的压力更多的存在于数据和存储方面。前面也说到,MySQL撑不住之后换位Oracle,Oracle的存储一开始在本机上,后来在NAS上,NAS撑不住了用EMC的SAN存储,再后来,Oracle的RAC撑不住了,数据的存储方面就不得不考虑使用小型机。在2004年夏天,DBA七公、测试工程师郭芙和架构师行癫,踏上了去北京测试小型机的道路。他们带着小型机回来的时候,然后Oracle就运行在小型机上;存储方面,从EMC低端CX存储到Sun
oemhds高端存储,再到EMC dmx高端存储,一级一级地往上跳。
到2004年底,淘宝网已经有4百多万种商品了,日均4千多万个PV,注册会员达到400万个,全网成交额达10亿元。
到现在为止,我们已经用上了IBM的小型机、Oracle的数据库、EMC的存储,这些东西都是很贵的。有人说过“钱能解决的问题,就不是问题”,但随着淘宝网的发展,在不久以后,钱已经解决不了我们的问题了。花钱买豪华的配置,也许能支持1亿个PV的网站,但淘宝网的发展太快,到了10亿个PV怎么办?到了百亿怎么办?
在几年以后,我们不得不创造技术,解决这些只有世界顶尖的网站才会遇到的问题。后来我们在开源软件的基础上进行自主研发,一步步把IOE(IBM小型机、Oracle、EMC存储)这几个“神器”都去掉了。这些神器就如同《西游记》中那些神仙的兵器,他们身边的妖怪们拿到这些兵器能把猴子打得落荒而逃。但最牛的神仙不依赖这些神器,他们挥一挥衣袖、翻一下手掌就威力无比了。
PS:在这部分我们看到了很多Java相关的技术,包括MVC(模型model-视图view-控制器controller)框架、hibernate、Spring、搜索引擎技术、IOE等;同时看到了遇到的一个接一个的问题及当时的解决方案。
已经有读者在迫不及待地想知道怎么去掉IOE了?别急,在去掉IOE之前还有很长的路要走。
行癫等人买回小型机之后,我们用上了Oracle;然后七公带着一帮DBA做优化SQL和存储方面的工作,行癫带着几个架构师研究数据库的扩展性。Oracle本身是一个封闭的系统,用Oracle怎么做扩展呢?用现在一个时髦的说法就是“分库分表”。
我们知道一台Oracle的处理能力是由上限的,它的连接池有数量限制,查询速度和容量成反比。简单地说,在数据量上亿、查询量上亿的时候,就到它的极限了。要突破这种极限,最简单的方式就是多用几个Oracle数据库。
但一个封闭的系统做扩展,不像分布式系统那样直接加机器就可以了。我们的做法是把用户的信息按照ID来存放到两个数据库中(DB1和DB2),把商品的信息和卖家信息放在两个对立的数据库中,把商品类目等通用信息放在第三个库中(DBcommon)。这么做的目的除了增加了数据库的容量之外,还有一个就是做容灾,即万一一个数据库挂了,整个网站上还有一半的商品可以买。
数据库这么分后,应用程序就会出现麻烦,如果我是卖家,查看我的商品没有问题,我们都在一个库里。但如果我是一个买家,买的商品有DB1的,也有DB2的,要查看“我已买到的宝贝”的时候,应用程序怎么办?必须到两个数据库中分别查询对应的商品。要按时间排序怎么办?两个库中“我已买到的宝贝”全部查出来在应用程序中做合并。另外,分页怎么处理?关键字查询怎么处理?专业点的说法就是数据的Join没法做了。这些工作交给程序员来做也许会更麻烦,于是行癫出手了,他写了一个数据库路由的框架DBRoute,统一处理了数据的合并、排序、分页等操作,让程序员像使用一个数据库一样操作多个数据库里的数据,这个框架在淘宝的Oracle时代一直在使用。
但是后来随着业务的发展,这种分库的第二目的——“荣灾”的效果没有达到(数据库挂了,整个网站上还有一半的商品可以买)。像评价、投诉、举报、收藏、我的淘宝等很多地方,都必须同时连接DB1和DB2,哪个库挂了都会导致整个网站挂掉。
PS:讲到这里涉及到了很多数据库方面的知识,如“XXX管理系统”这样的网站大家一定都不陌生,数据库的增删改查,JSP\PHP\ASP结合数据库的这些网站都是很常见的课程项目或毕业设计。回过头来,这些东西都不是很难;如果让你去解决一个真实的网站中遇到的问题、去实现这样一个框架解决实际问题,那才是真正的厉害。同时说到数据库,你可能会想到包括数据的增删改查、各种交叉查询、Join操作、ACID特性、事务加锁、存储过程触发器等知识。
上一篇说过,采用EJB其实是和Sun的工程师妥协的结果,在他们离开后,EJB也逐渐冷落下来。在2005年和2006年的时候,Spring大放异彩,于是控制层用Spring替换掉了EJB,给整个系统精简了很多代码。
同时为了减少数据库的压力,提高搜索的效率,我们引入了搜索引擎。随着数据量的增长,到了2005年,商品数有1663万个,PV有8931万个,注册会员有1390万个,这给数据存储带来的压力依然很大,数据量大,速度就慢。亲,除了搜索引擎、分库分表,还有什么办法能提升系统的性能?一定还有招数,这就是缓存和CDN(内容分发网络)。
你可以想象9000万次的访问量,有多少是在商品详情页面?访问这个页面的时候,数据全都是只读的(全部从数据库中读出来,不写入数据库),在那个时候,我们的架构师多隆大神做了一个基于Berkeley
DB的缓存系统,把很多不太变动的只读信息放了进去。
其实最初这个缓存系统还比较弱,我们并不敢把所有能缓存的信息都往里面放,一开始先把卖家的信息放里面,然后把商品属性放里面,再把店铺信息放里面,但是像商品详情这类字段太大的放进去受不了。说到商品详情,这个字段比较恐怖,有人统计过,淘宝商品详情打印出来平均有5米长。笔者记得,我来淘宝之后担任项目经理做的第一个项目就是把商品详情从商品表中移除来,它最早与商品价格、运费等信息放在一个表中,拖慢了整张表的查询速度,而很多查询商品信息是不需要查看详情的。
于是在2005年的时候,我把商品详情放在数据库的另外一张表中,再往后,这个大字段被从数据库中请了出来,先是放入缓存系统,到现在放进了文件系统TFS(Taobao File System)中。
到现在为止,整个商品详情的页面都在缓存里面了,眼尖的读者可能会发现现在的商品详情不全是“只读”的信息了,这个页面上有个信息叫“浏览量”(2006年加上去的),这个数字每刷新一次,页面就要“写入”存储一次,这种高频度实时更新的数据能用缓存吗?
通常来说,这种是必须放进数据库的,但悲剧的是,我们在2006年开发这个功能的时候,把浏览量写入数据库,发布上线1个小时后,数据库就挂掉了,每天几亿次的写入,数据库承受不了。那怎么办?亲,先不回答你,下一篇讲到缓存Tair的时候再说。
注意下图不是广告,请把注意力从左边移到右边,看看浏览量这个数据在哪里。
在这个稳定的版本下,淘宝网发展迅猛,2005年5月微软的MSN门户大张旗鼓地进入中国,淘宝网成为它的购物频道。2005年盛大进军机顶盒业务,其电视购物的功能也是淘宝网开发的。虽然因水土不服或政策的原因,这两个业务现在都看不到了,但是他们曾经是中国互联网行业的大事件。
另外老马也从来不缺少娱乐精神,他看到湖南卫视的超女如此成功,也想借鉴这种模式。2005年底,淘宝网和湖南卫视合作推出“超级Buyer秀”,让大家分享自己的网购经历。虽然没有超女火爆,但也让“淘宝网就是网购”的形象加深人心。
到2006年,淘宝网已经有了1.5亿个日均PV,商品数达到5千万个,注册用户3千万个,全网成交额达169亿元。
最后回顾下这四张图的变迁和几个版本:
1.0版的PHP系统运行了将近一年的时间(2003年5月-2004年1月),服务器由1台发展到多台;
后来数据库撑不住了,将MySQL换成了Oracle,引入了搜索引擎(2004年1月-2004年5月),叫1.1版本;
然后不到半年的时间又把开发语言换成了Java(2004年2月-2005年3月),叫2.0版本,数据服务逐步采用了IOE(IBM小型机、Oracle、EMC存储);
随着数据量和访问量的增长,我们进行数据分库、加入缓存、使用CDN(2004年10月-2007年1月),叫2.1版本。
《淘宝技术这十年》读书笔记 (二).Java时代的脱胎换骨和坚若磐石
原文地址:http://blog.csdn.net/eastmount/article/details/45194907