eBay的网站架构演进以及技术特点解析
eaby技术架构变迁
ebay的系统架构的变迁主要经历了4个阶段,下面一幅图展现了ebay系统架构变迁的时间表
在ebay的V1版本,ebay采用的是FREEBSD + APACHE + PERL +DGBM,这是一个比较原始的模型,而且相对比较简单,操作系统,应用服务器,web服务器 以及 数据库服务器都是在同一台机器中,网络结构在物理上只有一层。整个网站有四个域名,每个域名对应不同的应用,每组应用对应一台服务器。
图表 1 ebayV1系统架构
随着业务量以及访问量的不断上升,ebay在1999年开始对架构进行升级,技术架构发生了较大的变化,这期间主要是从1999-2004年,而架构的版本号则从V2.0到V2.5 ,下面我们来看看Ebay V2.0技术架构
V2.0
开始采用ORACLE服务器,数据库服务器和web服务器分开,数据库独立部署到一台新的机器上面
程序逻辑上面已经开始分层,也就是我们常说的mvc3层结构:显示层、业务逻辑层、数据访问层,而在物理上面还是两层结构 web服务器 以及 数据库服务器
编程语言采用C++,那个时候java刚兴起,估计也没有其他好的语言选择了。
V2.1
每组应用对应多台服务器,而多台服务器组成一个 servler pool(服务池),通过一个负载均衡服务器来分别转发请求到不同的服务器
数据库部署到性能更加好的服务器上面
V2.2
增加了一台数据库服务器作为 备份服务器,防止失败
V2.3
这个版本只是对每个应用增加了更多的服务器,不断的进行server pool
V2.4
这个版本最大且最重要的改变就是对数据库进行垂直拆分,即把数据库按照不同的功能模块进行划分,例如交易库,会员库,帐务库
V2.5
这个版本在2.4的版本上面,对部分数据库进行读写分离,同时对Item(物品条目)数据库进行水平拆分,把Items按照不同的Categoty分配到不同的Categoty商品库里面,,这样大大的扩展了对Items数据库的访问性能。
图表 2 ebayV2系统架构
从上可以看出ebay V2的架构变迁,主要是通过服务器的添加,数据库的垂直拆分以及水平拆分,数据库的读写分离操作 来提高整个网站的性能。在web层,通过添加服务器来进行水平扩展,同时对应用服务功能进行垂直拆分,按照不同的业务功能划分到不同的系统。在数据库层面,进行了读写分离尝试,对数据库进行垂直拆分,同时把Items库按照Category进行水平拆分,这样做,分散了对产品库items的集中访问,不过需要在DAL层提供透明的访问机制,ebays这里貌似还并没有这个成熟的框架,同时不知道 分布式事务ebay在这个阶段是如何实现的。
V3
整个应用程序开发平台全部替换为j2ee平台,用java改写了整个网站。看来是一次比较大的工作。目的是为模块解耦 以及模块复用,从这里,我们可以看出java在开发复杂企业应用的优势。
V3版本在数据库层面上面做了更加优化的设计,ebay继续在数据库上面进行优化
垂直拆分数据库,按照 功能模块 拆分为更多的子库
水平拆分数据库,对同一类数据,按照key值的不同数据分配到不同的数据库中(具体水平分库的方式有多种,这里就不再介绍了。)在进行水平拆分数据库的时候,ebay也必须建立一套透明的DAL访问方式,必须提供透明的数据库访问机制以及透明的数据库路由功能,数据库的物理结构变更不会影响到代码的逻辑变动。
在这里,ebay也在数据库层给出了最佳实践:
尽量减少数据库CPU的消耗,例如不使用存储过程,只使用少量的触发器
减少数据库层面的逻辑功能,例如数据转化,组合,这些都放在逻辑层
减少动态SQL,主要是SQL中参数的动态生成功能,这一点,公司的DBA也在强调
尽可能的缩短数据库的事务时间,尽可能早的结束事物
尽可能的采用异步更新数据库方式,分散数据库的压力,例如消耗数据库时间的操作要放在夜间处理。
不使用分布式事务,看来分布式事务的确不使用高并发性的系统
在应用逻辑层面,ebay把系统按照功能划分成许多不同的模块,每个模块作为一个子系统,同时通过水平扩展子系统服务器数量来提高整个系统的伸缩性。
下面看看ebay在应用层面给出的最佳实践
保持应用层子系统完全是无状态的,可以水平进行无限扩展以提高伸缩性,通过负载均衡服务器均等分配到各个子系统的实例池里面。
尽可能的使用缓存,缓存能够减少数据库的压力,使用空间来换时间
严格划分系统的各个层面,表现层,业务逻辑层,服务集成层,DAO层,基础设施层。
在应用层的设计上面,ebay通过不同的功能划分了很多domain,每个domain只负责自己的功能的业务逻辑,domain与domain之间是不会依赖的,同时还会提供common domain 提供各个 domain之间的交互以及依赖,见下图:
由于ebay的数据库按照逻辑划分了很多不同的字库,那么ebay必须提供透明的访问数据库的能力,举个例子:ebay把Items按照categoray分成了很多sub items库,假如需要查询出来某一个用户所购买的所有Items,那么必须要查询所有的sub items库,把数据库组合出来,那么DAL层必须屏蔽数据库的物理结构,一次性的把所有的sub items库中对应的数据查询出来。而这个访问,对应用来说是透明的。应用不需要关注到底items有多少个子库。
ebay的架构特点:
Partition Everything
当一个网站刚开始时,可能一天只有几十个人访问,或者几百个,可能一台普通的服务器就足够了,db和应用统统都可以放在一起,可是随着用户的增加,业务的增加,一台服务器远远不够了,就自然想增加服务器,系统应该跟随改变。多一台服务器,也就减轻了一台压力。这样就出现了分割业务和分割数据。
其实要做到恰到好处,也非常不容易,ebay按照业务功能水平划分应用,水平划分数据库。这个在国内好多网站都是这样做,不足为奇了,不过水平划分功能后,单个功能应用的分割也大有文章可做。怎么划分,很早以前ebay的架构文档说到这个事情。
在水平按照业务划分数据库后可以再根据一定的规则划分表数,其中规则有很多,可以按照主要业务生产者为引导进行分割,所有数据跟随生产者一起,至于什么规则可以各抒己见。
Asynchrony Everywhere
同步应用会带来强耦合,可用性保障差,特别是在用户体验方面极度失败,试想一个网站首页要获取那么多业务信息如果同步的话会流失很大一部份用户,如果再加上网络慢,等到蚊子都睡觉了,人哪里还有时间看,其实分布式系统应该尽量使用异步处理。
EBay的应对策略为:事件驱动和pipeline、多播消息,涉及的技术为:消息中间件(无序、至少一次到达)、基于SRM技术的可靠多播。
Automate Everything
配置信息的动态化,涉及的技术:配置发布/订阅机制的实现、机器学习。这个超级牛,不知道国内有多少网站做到了,听说淘宝做到了(呵呵)。
Remember Everything Fails
故障检测和回滚
这个现在很多网站都做,不过ebay做地比较牛,ebay差不多每天有2TB 的日志,通过监控事件作出有效的判断和预警,淘宝也做得很好。
eBay的应对策略为:异常后发消息、接收者获取消息警报、按功能实现降级,保障核心功能的可用性,涉及的技术有:消息中间件、如何实现按功能降级。
Embrace Inconsistency
其实这个有点象我们整天说的“拥抱变化”。在系统中如果事务过多,极大影响性能,特别是分布式事务,如果一味追求一致性会严重性能,ebay的做法是过程不一致,最终一致。涉及的技术有:消息中间件、CAP(Consistency 一致性;Availability 可用性; Tolerance of network Partition 分区容忍性(可理解为部分节点故障或节点之间连接故障下系统仍可正常工作))等
Expect (R)evolution
这里eBay讲到的主要是如何更好的应对变化,这包括了功能演变、架构演变,eBay的应对策略为:灵活的schema、可插拔的处理流程以及增量的系统发布,这方面的技术还是相当复杂的,eBay采用的是:配置化处理流程、系统发布过程支持多版本共存。
Dependencies Matter
这点随着分布式的应用和异步的应用,以及功能的不断增加后,就会变得比较明显,eBay也是如此。
他们的应对策略:服务拓扑管理、设计上的控制(只允许依赖…)、客户端承担责任。
说到这点,不得不说下,客户端承担责任这点其实真的很重要,现在很多架构都喜欢放在服务端上解决N多问题,但很多场合确实有必要放到客户端去做,当然,这也会带来一些问题,例如升级等。