已经有读者在迫不及待地问怎么去掉了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万次的访问量,有多少是在商品详情页面?访问这个页面的时候,数据全都是只读的(全部从数据库中读出来,不写入数据库),在那个时候,我们的架构师多隆大神做了一个基于 Berkeley DB 的缓存系统,把很多不太变动的只读信息放了进去。其实最初这个缓存系统还比较弱,我们并不敢把所有能缓存的信息都往里面放,一开始先把卖家的信息放里面,然后把商品属性放里面,再把店铺信息放里面,但是像商品详情这类字段太大的放进去受不了。说到商品详情,这个字段比较恐怖,有人统计过,淘宝商品详情打印出来平均有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亿元。