123456789

02月 13, 2007

引用 eBay是怎样练成的

归类于: 未分类 — misuisui @ 7:03 pm



引用


风轻扬eBay是怎样练成的

eBay是目前世界上最大的电子商务网站(Am I right?),目前已有2亿多注册用户,每天PV超过10亿,执行260多亿次SQL操作,在这么高的负载下仍然能提供非常稳定的服务(可用性达 99.94%),其架构设计一定有很多过人之外。Bay的技术人员Dan Pritchett和Randy Shoup前段时间在SD Forum上介绍了eBay的架构设计,现简述如下。


除最基本的Web服务器和数据库服务器之外,eBay的网站完全使用自主开发的软件,开发人员达几百人。从1995年eBay成立以来, eBay网站的架构经历了多次演变。最初的V1.0版本开发只用了一个周末,使用Perl,应用各层都部署在一台机器上,数据存储采用文件系统+GDBM (动态哈希表)相结合的方式。1.0用了两年,到了1997年系统中的条件达到5万时就顶不住了,于是开发的2.0,在逻辑上是三层架构,物理上是二层,应用层使用C++编写的内嵌于ISS的dll实现,数据库也独立出来使用Oracle。各系统都只使用一台服务器(Web服务器是有多台,但是不同的 Web服务器提供不同的服务)。再过了两年,99年升级到2.1,其中部分前台服务器使用集群,并将搜索功能独立出来,同时升级了数据库服务器的硬件。好景不长,一年还没用下来又不行了,于是升级到2.3,所有前台服务器都使用了集群,数据库加了个Standby。结果发现还是不行,二个月之后立马升级到 2.4,数据库按业务划分了一下,使用多台服务器了(终于跨出了关键性的一步啊)。接下来的V2.5按数据库划分得更细了。02年之后又升级到3.0,使用Java技术重写整个应用。


eBay在架构设计上主要关系三个可伸缩性:数据库存储可伸缩性、应用层可伸缩性和搜索服务可伸缩性,现一一道来。


数据库存储的可伸缩性实现的第一招是根据功能将数据库服务器加以分组,分为用户、条目、账号、反馈、事务等70多个类别。组内可伸缩性实现则有两种方式:master/slave或数据分区,数据分区有使用取模实现,也有使用映射数据库实现。为减少数据库的负载,数据库层不包含业务逻辑,没有存储过程,参照完全性检查、联接、排序等占CPU的工作移到应用中去作。同时很少使用事务,绝大部分操作都用auto commit模式。为减少对事务的依赖,应用程序需要非常仔细的安排数据库操作的顺序,对于部分不可避免的数据不一致则使用异步的故障处理脚本来处理。需要不使用事务增加了开发的难度,但也避免了数据库死锁和提高的数据库的并发度。


应用层主要涉及负载的分布和依赖关系最小化两个方面。eBay不使用大部分的J2EE特性,只使用servlet和一个定制的连接池,应用层完全不维护状态信息(session使用cookie或scratch数据库维护),并尽可能的对常用的metadata等信息做了缓存。应用程序严格的分为呈现层、业务层和集成层。其中集成层即数据访问层(Data Access Layer),实际上是eBay自己实现的一个Java ORM组件,负责所有CRUD操作,并支持动态数据路由服务(即逻辑数据库服务器-

为减少应用之间的依赖关系,应用代码按功能区划分为买出、购买等多个独立模块,共享的模块如用户认证、个性化等组织成Domain,应用只依赖于Domain,不依赖于其它应用,Domain中各模块之间也无相关依赖关系。应用服务器和数据库服务器也根据业务类型划分为多个集群,不同集群的开发、部署可并行进行。


eBay的全文检索系统原来使用的是第三方开发的一个系统,但到2002年就遇到了性能瓶颈,当时更新一次索引需要9个小时,使用了最高档的设备也满足不了需求。eBay对全文检索的要求很高,产品列表、竞标等信息要求实时更新、很多查询要求返回所有结果、存储有按关键字、分类和结构化属性组织等多种形式。由于没有现成产品能满足所有需求,eBay开发了自己的全文检索系统,其中有很多创新性的功能。实时供给器平台负责将更新从主数据库可靠广播到多个检索节点,索引支持实时更新,支持内存索引。索引系统是高度分布式的,索引机有多组副本,一组又包含多台机器。缓存技术也被应用于搜索系统中,主要是缓存常用搜索或非常耗资源的搜索的结果。


由此可见即使强大如eBay,最初的系统都是很菜的,后来一步步走向分布式才解决了一个又一个瓶颈,可见分布式是大势所趋。也可以看到功能分解或面向对象中的CRC原则在网站架构设计中的重要性,若是功能划分不清晰,业务单元之间的依赖关系过于复杂,要设计一个好的架构是难上加难。详细的ppt在此


引用 [zz]活用设计模式

归类于: 未分类 — misuisui @ 7:03 pm



引用



好文,这就是典型的“兵无常势,水无常形,运用之妙,存乎一心”吧,任何事情其实无不如此。



zhousen[zz]活用设计模式


一、 设计模式的隐喻
武功套路是习武的门径。新手要一招一式地练习套路,烂熟于心之后,熟能生巧,在实战之中即可见招拆招、运用自如——此时习武之人已从“新手”成长为“好手”。“高手”则没有套路,实战之中只有自然反应,然而一招一式浑然天成、恰到好处,似有似无、无中生有。“高手”之上还有“高高手”,他们达到的境界非我等凭借金氏武侠小说可以揣测。
设计模式之于设计,好比套路之于武术。“新手”要一个接一个地学习模式,“好手”能够活用模式,“高手”则没有模式。
设计模式的“内功”是面向对象的基本原则。这些原则是“神”,模式是“形”。高手拼的是“内功”,对面向对象基本原则有了深刻的领悟,才能用好设计模式,避免“走火入魔”。
一般在设计模式著作的前几章都会介绍面向对象的基本原则,这几章非常重要。学通了这几章,后面的模式就不过如此了。学完了设计模式,也最好翻过头来重新看看这几章,保证会有新的领悟。


二、 为什么使用设计模式
对任何设计都可以凭主观(对设计很难做出客观评价)判断得出它是一个好的设计,还是一个坏的设计。使用设计模式是为了避免坏的设计。Martin叔叔在他的著作《敏捷软件开发 原则、模式与实践》中描述了拙劣设计的症状:



  • 僵化性(Rigidity):设计难以改变。
  • 脆弱性(Fragility):设计易于遭到破坏。
  • 牢固性(Immobility):设计难以重用。
  • 粘滞性(Viscosity):难以做正确的事情。
  • 不必要的复杂性(Needless Complexity):过分设计。
  • 不必要的重复(Needless Repetition):过多的重复。
  • 晦涩性(Opacity):混乱的表达。



三、 什么时候使用设计模式
Martin叔叔的书中有段话:
  
在学习它们(设计原则和模式)的时候,请记住,敏捷开发人员不会对一个庞大的预先设计应用那些原则和模式。相反,这些原则和模式被应用在一次次的迭代中,力图使代码以及代码所表达的设计保持干净。
  
在这段容易被读者忽略的文字中,我体会到这样几层含义:



  • 代码是设计(这是Martin叔叔强调的一个观点,这个观点可以参考《敏捷软件开发 原则、模式与实践》一书的附录D);
  • 设计模式是为了使设计适应变化;
  • 设计模式是重构的工具;
  • 设计一开始就要保持干净、简单,以后仍然要保持干净、简单;
  • 不能过度使用设计模式。


使用设计模式的目的是为了适应未来的变化,变化之所以存在是因为它的不可预知性——如果可以预知,则不能称其为变化。如何判断哪些需求可能变化,哪些需求可能不变,并且在最大程度上保持设计的干净、简单,这是些工艺问题,而不是工程问题。既然是工艺问题,那么就只能给出原则,不能给出标准。使用设计模式的大体原则可能是:对未来极有可能发生变化的问题给出最简单、修改成本最低的解。
  
四、 避免过度使用设计模式
易维护的程序首先要易理解,这一点远甚于其他。在易理解的代码上才好维护。过分地使用设计模式会增加程序的复杂性和晦涩性,让程序不易理解,从而降低了程序的易维护性。
Switch语句曾经遭致诟病,许多重构的例子就是拿Switch开刀。我认为Switch语句是高效的语句,可以写出极优雅、简单的代码。在很多情况下,直接使用Switch语句比把它拆成若干个Class更“干净”。
再比如,有一段四百多行的代码负责整个系统的调度,如果未来的变化仅仅是修改这四百行代码而不会大量添加代码,那么把这四百多行代码集中在一个函数里面,比将它拆分成十来个Class更加容易维护。


五、 讨论几个具体的模式
1、 创建模式(Creational Pattern)
工厂(Factory Method)模式是常用的模式。工厂模式的应用情景明确,设计思想简单。从?用多态到只用一个静态方法,工厂模式的变化形式有很多。我习惯简单地使用工厂模式,也就是使用只有静态方法的工厂模式。下面的工厂模式代码简单、干净:

  MyFactory.GetClassInstance().DoFunction();
  
类厂并不承载业务逻辑,需求变化对类厂的影响通常很小。因此使用重量级的工厂模式往往并不划算。一组包含层次关系的重量级的工厂类,可能意味着过度设计。
单例(Singleton)模式和工厂模式关系密切。从实现的角度讲,单例模式是工厂模式的一个特例,但是两个模式的应用情景不同,因此它们属于不同的模式。
抽象工厂(Abstract Factory)模式是工厂模式的推广。抽象工厂模式的应用情景更加特殊和严格。在一个使用抽象工厂的设计中,如果未来发生不同产品族各自演化的情形,那么抽象工厂模式就可能崩溃了。在实际应用中,不同产品族各自演化,最终分道扬镳的情形是有的,用户提出这样的需求的确让人“触目惊心”。在使用抽象工厂模式之前,一定要保证从现在到未来都能够用一致的方式使用这些产品族。
将工厂模式稍加变化可以得到建造(Builder)模式。工厂模式的“加工工艺”是隐藏的,而建造模式的“加工工艺”是暴露的。这点不同,使建造模式在更加灵活的同时也有失优雅。
2、 模板模式(Template Method)和策略(Strategy)模式
模板模式和策略模式的应用情景类似,但实现方式不同,前者使用继承,后者使用委托。
模板模式有可能是最“古老”的模式之一,在使用面向对象技术的早期,“继承”大行其道,很多设计人员可能不自觉地使用过模板模式。模板模式的缺点是把具体实现和通用算法紧密地耦合起来,使得具体实现只能被一个通用算法操纵。然而在继承关系中,父类的信息可以更多地暴露给子类,这种(违背面向对象设计原则的)微妙的沟通在一些特定应用中显得更加灵活和方便。
策略模式是委托的经典用法。策略模式消除了通用算法和具体实现的耦合,使得具体实现可以被多个通用算法操纵。策略模式也增加了类层次,比模板模式复杂。
模板模式和策略模式通常可以互相替换。它们都像试卷,模板模式是填空题,策略模式是选择题。
3、 简化问题的模式
门面(Facade)模式把一组复杂的接口隐藏在一个简单且特定的接口后面。
调停者(Mediator)模式把对象之间的引用关系包装在一个特定的容器里面。
组合(Composite)模式描述了整体与部分的结构关系,并且允许用一致的方式处理这个结构。
上面几个模式对使用者而言,都在一定程度上起到了简化问题的作用。
4、 扩展功能的模式
访问者(Visitor)模式和装饰(Decorator)模式都可以在不改变现有类结构的基础上,动态地增加功能。
访问者模式把现有类结构上的对象“分配”到一个名为访问者的类中,在访问者的相应方法中配置对象、改变对象或扩展功能。
装饰模式把现有类结构上的对象“注入”一个装饰类中,在装饰类中扩展它的功能。
访问者模式和装饰模式在实际效果上是不同的。访问者模式可以把对象分配到相应的方法里,从而对每个对象分别进行加工或扩展。而装饰模式只能用一致的方式对所有的被装饰对象进行加工或扩展,要想实现不同的加工或扩展,只能增加新的装饰类。
过多的“装饰类”有可能使业务逻辑分散,并且使程序结构复杂。针对每一个具体的派生类,“访问类”都要有一个对应的方法,增加派生类的时候也要增加访问类的方法。扩展功能的需求是经常发生的,是否有必要使用上述模式则值得再三考虑。
5、 其他常用的模式
桥梁(Bridge)模式。Class是封装了行为和属性的容器,然而Class的一组行为可能独立演化,这时最直接的想法是使用继承,把各不相同的行为封装在不同的子类里。桥梁模式从另外的角度解决了这个问题。桥梁模式把独立演化的行为封装在另外一个类体系里,与原来的类体系分别独立演化,两个类体系在抽象层次是“使用”关系。在很多OO教材里面用Shape类封装属性和Draw方法,在桥梁模式里,“形状”和“画笔”是两组独立演化的类体系,在抽象层次,“形状”使用“画笔”绘制自己。
适配器(Adapter)模式是常用模式,它比较简单,有时和其他的模式配合使用。
命令(Command)模式被Martin称为“最简单、最优雅的模式之一”。命令模式的魅力在于它为每个类“培训”出了相同的技能,经过“培训”的类“柔性”更强,能够产生不可思议的能力。
6、 不太需要的模式
观察者(Observer)模式。Java和C# 都实现了观察者模式。
迭代子(Iterator)模式。在Java和C#语言里,可以用聚集类代替。
备忘录(Memento)模式。可以用Class的序列化能力代替。
责任链(Chain of Responsibility)模式。可以用其他的方式替代,例如观察者模式、语言本身提供的消息机制等。
解释器(Interpreter)模式。个人认为,它是个算法,不是模式。
代理(Proxy)模式。如果在一开始就知道某些底层策略一定会被替换掉,那么使用代理来隔离这些策略还是有必要的。否则,几乎没有使用的必要。

昨日新闻 – 做营销2.0之前要反思的几个问题

归类于: 未分类 — misuisui @ 6:59 pm
2007年02月04日 7:19 AM

Trackback: http://tb.donews.net/TrackBack.aspx?PostId=1125262

Time To Say Goodbye

归类于: 未分类 — misuisui @ 6:59 pm
2007年01月31日 6:23 AM

http://blog.donews.com/images/blog_donews_com/keso/117963/o_donews_namecard.png近两年以来,我一直使用Donews的名片。我顽固地把自己当作Donews的人,即使她已经被千橡收购,我从来没有打算换成千橡的名片。并不是我不能接受这样的收购,也不是我不喜欢千橡的名片,仅仅因为,Donews是我的精神寄托。

另外一个原因,Donews给我的自由,我知道大概没有任何其他公司可以给我。我一直相信,自由是惟一值得追求的东西,其他,不过是浮云。同时我也很清楚,自由是一件稀缺的东西,所以它昂贵。

这一年,我游离在所有的漩涡之外,全然不知身处漩涡中的人们,到底在经历着什么。在这个商场如战场的互联网上,我几乎从未被施加过任何我不想承受的压力,但我明白,那些我不想承受的压力,一定有人替我承受了。尽管我从没说过,但我在心底无数次地重复着,谢谢你,刘韧。

像刘韧一样,我也信仰互联网,并且已经信了10年,大概还会继续信下去。像刘韧一样,我也珍爱Donews,并且已经珍爱了6年,大概还会继续珍爱下去。不管将来还能不能继续使用Donews的名片,Donews都是那样一个无法被替代的家园。

我不知道未来,我所知道的是,只要你走,无论走到什么地方,都是未来。关键是,你身边永远都有值得信任的朋友,哪怕你们只是默默地走,一言不发。

Andrea Bocelli & Sarah Brightman – Time To Say Goodbye (mp3)

Trackback: http://tb.donews.net/TrackBack.aspx?PostId=1122730