这篇文档转载jdon上的。
在HPTS 2009上,ebay 架构师Randy Shoup又列出了五个lessions.它们分别是:
1 Expect (R)evolution
2 Dependencies Matter
3 Be Authoritative
4 Never Enough Data
5 Custom Infrastructure
我结合ebay以前的5个lessions,总结一下可伸缩性和高性能的系统架构的一些最佳的实践:
一 Partition Everything
在一个大型的系统架构和设计当中,我们会面临各种各样的挑战,而为了能使得系统具有良好的可伸缩性,我们就需要“切分系统的每个部分”,而这里的切分又设计到一些方向性或者是策略性的问题,也就是如何切分,从什么方向入手去切分,我结合Ebay架构师的经验以及自己的想法,总结如下。
1 垂直切分
说到垂直切分,我们能第一时间想到的就应该是系统的分层架构,一个系统可以分为好几个层次,比如在目前J2EE系统的开发当中,我们一般都会分为表现层,应用层(负责业务逻辑的封装),领域模型层(负责业务逻辑的实现),和持久层(负责对底层数据源的访问),按照分层的思想切分以后,系统的每一个层都是高内聚的,同时层与层之间也是低耦合的,这就符合了高内聚和低耦合的原则,这样以来系统的各个层次可以独立的进行维护,扩展和伸缩。分层的好处还可以参见我的一篇文章:系统为什么要分层?
2 水平切分
当系统按照分层原则分为几个层次以后,虽然层与层之间实现了好的解耦,从而容易维护和伸缩,但是随着负载的增大,单个层的伸缩也会遇到瓶颈,而这个时候就需要水平的切分各个层次,这里又可以按照逻辑功能的水平切分和存储或者数据的水平切分。
2.1 应用水平切分
在一个大型的系统中往往会涉及到很多的错综复杂的逻辑,这个时候架构师就需要根据不同的功能对系统进行水平的分割,比如按照用户,商品,交易,搜索等功能进行水平的分割。而在具体架构和设计的过程中,我们一般通过不同的jar,bundle等来进行分割。
在按照功能进行切分以后,我们还需要注意一点就是尽量采用无状态的架构,因为系统的伸缩性很大部分上取决于你的应用的状态如何保存,因此无状态的架构对于水平的切分很重要,只有尽量的采用了无状态的架构以后,我们的系统才可以能更好的进行水平的伸缩。
2.2 存储水平切分
一个大型的系统往往会有非常巨大的数据量,这个时候就需要对数据也进行切分,比如将数据分为用户数据库,交易数据库,商品数据库等。在对数据按照功能进行切分以后,我们还可以对其进行进一步的切分,此时一般采用“Shard”技术,比如将前100W条记录保存一台主机上,然后依次类推。
二 Abstract and Virtualize at all Levels
在第一条"Partition Everything"中,我们将切分融入了系统的血液当中,这样也就使得系统具有了良好可伸缩性的血液,但是在切分以后,也给系统带来了其它的问题,比如在存储层面上,因为我们将数据按照功能进行了水平的切分,这样以来就使得数据的访问复杂了起来,这个时候就需要对数据访问层进行合理化得抽象和虚拟化,使得物理上分割的数据库对外界来说是一个统一的整体,而此时一般我们可以采用DAL技术。
在Ebay的系统中,搜索是系统很重要的构成部分,一般用户的一次搜索都需要通过一个聚合器对搜索结果的进行整合,对于外界来说通过聚合器封装和抽象了搜索系统。
因此抽象和虚拟化使得系统的伸缩性的实现更加容易和方便,它使得伸缩性的系统更加方便管理和维护。
三 Asynchrony Everywhere
目前J2EE其实都是同步的API(JMS除外),同步必然带来组件与组件之间的紧耦合,而组件之间的耦合度越高,也就不能独立对其进行伸缩,从而影响到伸缩性。假如系统中A组件调用了B组件,从基本的数理逻辑来看,如果A可以用,那么B可以用,反过来,如果B不可以用,那么A也不可以用,这就是同步调用给系统可用性带来的损失。因此只有通过一种松耦合的方式对组件进行解耦,这样才能使得系统具有好的可用性和伸缩性,而通过异步的方式是一种比较好的解耦的方式。关于异步大家可以参考一下这篇文章:Java EE meets Web 2.0
Ebay将异步这条原则贯彻的非常彻底。在组件内部使用SEDA来实现异步性,组件和组件之间的交互也尽量的采用异步,将业务程分为很多个阶段,各个阶段通过异步的方式连接起来。在Ebay中,异步主要用了Event Queue和消息多播等技术。
说到这里,我也想说说目前比较流行的DDD如何引入异步,在传统的J2EE开发当中,业务逻辑实现都是在action或者service,业务逻辑的实现是通过action和service这些技术的组件来驱动的,而采用领域驱动设计以后,业务逻辑的操作是由Model驱动的,Model触发Domain Event,然后异步的驱动技术性的组件来完成对Domain Event的响应,这样以来整个系统的核心就是Domain Model,而各种的技术性的组件仅仅是一种为Domain Model服务的tools。Domain Model和Domain Event的结合可以参见下图:
四 Avoid Distributed Transactions
事务和性能,伸缩性是相互矛盾的,系统中事务用的越多,那么性能和伸缩性就会变得越差,因此必须合理化得利用事务。尤其是传统的分布式事务,采用2PC来提交,这样就要求所有事务性的资源必须都准备好,只要一个有问题,那么整个事务都会受到限制,更严重的是2PC是非常影响性能和伸缩性的。从Ebay的架构中也可以看的出来,Ebay坚决的杜绝分布式事务。如果不采用传统那种分布式事务,那么采用什么样的事务策略呢?答案就是BASE策略。
在说BASE策略之前,我们有必要来了解一下Eric Brewer大叔的CAP理论,CAP是Consistency,Availability,Partition_tolerance的缩写,Consistency表示系统的状态对所有的Client都是即时一致的。Availability表示系统的可用性,它主要是指任何一个业务操作都能在预定的时间内完成。最后一项Partition_tolerance表示分区容错性,它主要是指业务操作不能受单个系统组件的影响,即使某一些组件不能使用,业务操作也必须完成。理解了CAP理论的这三个方面以后,我们来看看CAP理论到底告诉了我们什么,CAP告诉我们,任何一个分布式系统不可能同时满足这三个条件,最多只能同时满足两个(是不是有点失望*^__^*).
我们现在明白了CAP,那么BASE是什么?它和传统的ACID又有什么区别和联系呢?接着往下看,你就会明白啦呵呵。BASE是basically available,soft state,eventually consistent的缩写,BASE表示基本可用,事务软状态和最终一致性。BASE采用一种乐观策略,它不要求事务状态的即时一致性,而是要求一种最终一致性,也就是说事务状态在某一个用户可以接受的范围内是不一致的,但是最终会变的一致,而传统的ACID事务策略采用一种悲观的方式,它要求事务状态在业务操作结束以后必须是即时一致的,是一种Hard state,一种面向连接的状态,炫绷得越紧越容易断,事务也是一样的,ACID这跟炫也非常容易断,但是无论是BASE还是ACID都无法摆脱CAP的限制,BASE通过一种事务的软状态和弱一致性换来了可用性,同时也满足分区容错性,而ACID采用了强的一致性,而牺牲了可用性。因此BASE适合于对可用性最求大于一致性需求的场合,而ACID适合于对一致性要求很严格的场合,比如一些股票软件系统就适合ACID。最后,如果大家对BASE和ACID还是不理解的话,推荐大家看看Dan Pritchett大哥的这篇文章:BASE: An Acid Alternative
五 Cache
缓存存在的地方很多,系统中用缓存的方式也有很多方式,我这里仅仅说说我自己的理解,这些也是我目前公司的项目中所运用的方式。
我这里主要说一下缓存如何和领域模型进行结合使用。在传统的软件开发中,我们一般采用action -->service-->Dao中,系统的业务逻辑充斥在action或者Service里面,最终的结果就是action和service非常庞大,非常的难于理解,尤其是在设计到事务的时候,到项目后期,你会发现事务配置在action和service都不合适,这都是传统的SSH传统的开发带来的负面影响。那么采用DDD以后,业务逻辑的实现是通过Domain model驱动技术组件去完成功能,所有的业务逻辑都被封装在了Domain Model里面,但是这样也带来一个问题,Domain model一般聚合了很多的东西,如果我们用完了就是把它扔掉,那么每次从持久层构建它是非常耗费性能的,因此这就需要将其放在某一个地方,这个地方就是缓存。当然了随着目前KEY-VALUE存储系统的不断发展,以后我们可以直接用KEY-VALUE存储系统来讲Domain Model保存起来。如果大家对于Domain model为什么要聚合很多东西,为什么也不能聚合不该聚合的东西,请大家参考另外一篇文章:Improving performance and scalability with DDD
六 Not Only SQL
对象和关系数据库很矛盾,这个经常来本站的人应该都清楚。我就不多说了,目前随着KEY-VALUE存储系统的逐渐成熟和普及,我想一种:面向业务的分析和设计(DDD)+面向业务的存储(KEY-VALUE)的新的架构方式也将会诞生。
七 Embrace Inconsistency
这一点其实也还可以算是一致性和性能,伸缩性,高可用性之间的博弈
八 Automate Everything
九 Remember Everything Fails
十 Expect (R)evolution
十一 Dependencies Matter
十二 Be Authoritative
十三 Never Enough Data
十四 Custom Infrastructure
分享到:
相关推荐
hpts(http-proxy-to-socks) 一个nodejs客户端将socks代理转换为http代理
它的特点是甲状旁腺分泌副甲状腺激素过多,以维持对低钙血症的磷酸钙稳态,降低1.25二羟基维生素D3和高磷血症。 目的:分析继发性甲状旁腺功能亢进症(HPTS)的甲状旁腺切除术(PTX)的结果,报告术后病程以及早期...
3. `hpts32.cat`、`hptsx3.cat`:这些是Windows系统安全性的数字签名文件,确认驱动程序的来源和完整性,防止恶意篡改。 4. `hpts64.cat`、`hptsx6.cat`:与上面的32位版本相对应,这些是64位系统的安全签名文件。 ...
支持HAProxy 、 socks协议和http-proxy服务器: polipo 、 privoxy和hpts 。 此外,您可以查看以前运行的TOR进程并为所有或选定的进程创建新身份。 multitor已在以下基础上完全重写: 由Jan Seidl编写的Multi-TOR...