淘宝技术发展历程(五)-Java时代:坚若磐石
已经有读者在迫不及待的问怎么去掉了 IOE,别急,在去掉 IOE 之前还有很长的路要走。行癫他们买回来小型机之后,我们用上了 Oracle,七公带着一帮 DBA 在优化 SQL 和存储,行癫带着几个架构师在研究数据库的扩展性。Oracle 本身是一个封闭的系统,用 Oracle 怎么做扩展?用现在一个时髦的说法就是做“分库分表”。
我们知道一台 Oracle 的处理能力是有上限的,它的连接池有数量限制,查询速度跟容量成反比。简单的说,在数据量上亿、查询量上亿的时候,就到它的极限了。要突破这种极限,最简单的方式就是多用几个 Oracle 数据库。但一个封闭的系统做扩展,不像分布式系统那样轻松。我们把用户的信息按照 ID 来放到两个数据库里面(DB1/DB2),把商品的信息跟着卖家放在两个对应的数据库里面,把商品类目等通用信息放在第三个库里面(DBcommon)。这么做的目的除了增加了数据库的容量之外,还有一个就是做容灾,万一一个数据库挂了,整个网站上还有一半的数据能操作。
数据库这么分了之后,应用程序有麻烦了,如果我是一个买家,买的商品有 DB1 的也有 DB2 的,要查看“我已买到的宝贝”的时候,应用程序怎么办?必须到两个数据库里面分别查询出来对应的商品。要按时间排序怎么办?两个库里面“我已买到的宝贝”全部查出来在应用程序里面做合并。还有分页怎么处理?关键字查询怎么处理?这些东西交给程序员来做的话会很悲催,于是行癫在淘宝的第一个架构上的作品就来解决了这个问题,他写了一个数据库路由的框架 DBRoute,这个框架在淘宝的 Oracle 时代一直在使用。后来随着业务的发展,这种分库的第二个目的 —— 容灾的效果就没有达到。像评价、投诉、举报、收藏、我的淘宝等很多地方,都必须同时连接 DB1 和 DB2,哪个库挂了都会导致整个网站挂掉。
上一篇说过,采用 EJB 其实是和 Sun 的工程师妥协的结果,在他们走了之后,EJB 也逐渐被冷落了下来。在 2005、2006年的时候,Spring 大放异彩,正好利用 Spring 的反射(IoC)模式替代了 EJB 的工厂模式,给整个系统精简了很多代码。
上一篇还说过,为了减少数据库的压力,提高搜索的效率,我们引入了搜索引擎。随着数据量的继续增长,到了 2005 年,商品数有 1663 万,PV 有 8931 万,注册会员有 1390 万,这给数据和存储带来的压力依然山大,数据量大,性能就慢。亲,还有什么办法能提升系统的性能?一定还有招数可以用,这就是缓存和 CDN(内容分发网络)。
你可以想象,九千万的访问量,有多少是在商品详情页面?访问这个页面的时候,数据全都是只读的(全部从数据库里面读出来,不写入数据库),如果把这些读操作从数据库里面移到内存里,数据库将会多么的感激涕零。在那个时候我们的架构师多隆大神,找到了一个基于 Berkeley DB 的开源的缓存系统,把很多不太变动的只读信息放了进去。其实最初这个缓存系统还比较弱,我们并没有把整个商品详情都放在里面,一开始把卖家的信息放里面,然后把商品属性放里面,商品详情这个字段太大,放进去受不了。说到商品详情,这个字段比较恐怖,有人统计过,淘宝商品详情打印出来平均有 5 米长,在系统里面其实放在哪里都不招人待见。笔者清楚的记得,我来淘宝之后担任项目经理做的第一个项目就是把商品详情从商品表里面给移出来。这个字段太大了,查询商品信息的时候很多都不需要查看详情,它跟商品的价格、运费这些放在一个表里面,拖慢了整个表的查询速度。在 2005 年的时候,我把商品详情放在数据库的另外一张表里面,再往后这个大字段被从数据库里面请了出来,这也让数据库再一次感激涕零。
到现在为止,整个商品详情的页面都在缓存里面了,眼尖的读者可能会发现现在的商品详情不全是“只读”的信息了,这个页面上有个信息叫“浏览量”,这个数字每刷新一次页面就要“写入”数据库一次,这种高频度实时更新的数据能用缓存吗?如果不用缓存,一天几十亿的写入,数据库会怎么样?一定会挂掉。那怎么办?亲……先不回答你(下图不是广告,让你看看浏览量这个数据在哪里)
CDN 这个工作相对比较独立,跟别的系统一样,一开始我们也是采用的商用系统。后来随着流量的增加,商用的系统已经撑不住了,LVS 的创始人章文嵩博士带人搭建了淘宝自己的 CDN 网络。在本文的引言中我说过淘宝的 CDN 系统支撑了 800Gbps 以上的流量,作为对比我们可以看一下国内专业做 CDN 的上市公司 ChinaCache 的介绍 —— “ChinaCache……是中国第一的专业 CDN 服务提供商,向客户提供全方位网络内容快速分布解决方案。作为首家获信产部许可的 CDN 服务提供商,目前 ChinaCache 在全国 50 多个大中城市拥有近 300 个节点,全网处理能力超过 500Gbps,其 CDN 网络覆盖中国电信、中国网通、中国移动、中国联通、中国铁通和中国教育科研网等各大运营商。” —— 这样你可以看得出淘宝在 CDN 上面的实力,这在全世界都是数一数二的。另外因为 CDN 需要大量的服务器,要消耗很多能源(消耗多少?在前两年我们算过一笔帐,淘宝上产生一个交易,消耗的电足以煮熟 4 个鸡蛋)。这两年章文嵩的团队又在研究低功耗的服务器,在绿色计算领域也做了很多开创性的工作。淘宝 CDN 的发展需要专门一个章节来讲,想先睹为快的可以看一下笔者对章文嵩的专访。
回想起刚用缓存那段时间,笔者还是个小菜鸟,有一个经典的错误常常犯,就是数据库的内容更新的时候,忘记通知缓存系统,结果在测试的时候就发现我改过的数据怎么在页面上没变化呢。后来做了一些页面上的代码,修改 CSS 和 JS 的时候,用户本地缓存的信息没有更新,页面上也会乱掉,在论坛上被人说的时候,我告诉他用 Ctrl+F5 刷新页面,然后赶紧修改脚本文件的名称,重新发布页面。学会用 Ctrl+F5 的会员对我佩服的五体投地,我却惭愧的无地自容。
有些技术的发展是顺其自然的,有些却是突如其来的。到 2007 年的时候,我们已经有几百台应用服务器了,这上面的 Java 应用服务器是 WebLogic,而 WebLogic 是非常贵的,比这些服务器本身都贵。有一段时间多隆研究了一下 JBoss,说我们换掉 WebLogic 吧,于是又省下了不少银两。那一年,老马举办了第一届的“网侠大会”,会上来的大侠中有一位是上文提到的章文嵩,还有一位曾经在 JBoss 团队工作,我们也把这位大侠留下了,这样我们用起 JBoss 更加有底气了。
这些杂七杂八的修改,我们对数据分库、放弃 EJB、引入 Spring、加入缓存、加入 CDN、采用开源的 JBoss,看起来没有章法可循,其实都是围绕着提高容量、提高性能、节约成本来做的,由于这些不算大的版本变迁,我们姑且叫它 2.1 版吧,这个版本从构图上来看有 3 只脚,是不是稳定了很多?
架构图如下: